如何使用Ember Data&Rails在单个Ember.js表单中保留hasMany关联?

我在使用Ember.js,Ember Data和Rails确定使用单个表单保持hasMany关联的正确方法时遇到了麻烦。 客户有很多项目。 我有一个新的项目表单,有两个字段:项目名称和客户端名称。 http://cl.ly/image/3z0P0R3M1t2u

我试图将我的创建逻辑保留在Ember.js ClientsControllerProjectsController中 ,但我是否需要将其中一部分移动到我的ProjectsNewView上的提交操作中?

更新:我在发现此问题后更新了我的代码。 我越来越近了,但Rails ProjectsController仍然没有收到相关的client_id。 它不是控制器接收的参数的一部分。 我觉得我可能不是最好的方式。

楷模:

轨道

class Client  true end class Project  true validates :client, :presence => true end 

Ember.js

 App.Client = DS.Model.extend name: DS.attr('string') projects: DS.hasMany('App.Project', { embedded: true }) validate: -> if @get('name') is null or @get('name') is '' 'Client requires a name.' App.Project = DS.Model.extend name: DS.attr('string') client: DS.belongsTo('App.Client') validate: -> if @get('name') is `undefined` or @get('name') is null or @get('name') is '' return 'Projects require a name.' if @get('client') is `undefined` or @get('client') is null or @get('client') is '' 'Projects require a client.' 

控制器:

轨道

 class Api::ClientsController < Api::BaseController def create @client = Client.find_or_create_by_name(params[:client][:name]) respond_to do |format| if @client.save format.json { render json: @client, status: :create } else format.json { render json: @client.errors, status: :unprocessable_entry } end end end end class Api::ProjectsController < Api::BaseController def create @project = Project.new(params[:project]) respond_to do |format| if @project.save format.json { render json: @project, status: :created, location: @project } else format.json { render json: @project.errors, status: :unprocessable_entry } end end end end 

Ember.js

 App.ClientsController = Em.ArrayController.extend createClient: (data) -> @transaction = App.store.transaction() client = @transaction.createRecord(App.Client, data) project_data = data.projects_attributes[0] client.get('projects').createRecord(project_data) validation_errors = client.validate() if validation_errors App.displayError validation_errors client.destroy() else @transaction.commit() App.ProjectsController = Em.ArrayController.extend createProject: (data) -> @transaction = App.store.transaction() project = @transaction.createRecord(App.Project, data) validation_errors = project.validate() if validation_errors App.displayError validation_errors project.destroy() else @transaction.commit() App.get('router').transitionTo('projects') 

浏览次数:

Ember.js

 App.ProjectsNewView = Em.View.extend classNames: ['form row'] tagName: 'form' templateName: 'projects/new' init: -> @_super() submit: (event) -> event.preventDefault() client = {} client.name = @get('client') project = {} project.name = @get('name') client.projects_attributes = [] client.projects_attributes.push project App.router.clientsController.createClient(client) 

@David我不是专家,但我再次查看你的问题,我认为要获得相关的client_id,你必须在RestAdapter上调用toJSON方法并传递它:

 {associations: true} 

以下链接说明了如何做到这一点:

https://stackoverflow.com/questions/10184213/is-there-a-way-to-post-embedded-objects-back-to-the-api-with-ember-data

Ember数据嵌入对象存储为单独的对象

Emberjs – 无法查询嵌入式模型或关联

更新

在我回答代码中使用toJSON的位置的问题之前,我想回过头来看一下我刚才用代码设计观察到的东西。

您正尝试在子记录中创建parentRecord,因为Client是父项,而project是子项。 如果你观察得很好,你链接到的问题-115 ,断然说将使用parentRecord商店来创建记录。 此外,如果您在关于issue-115 合并的 evenutual pull-request中检查测试,您将再次看到它在parentRecord中创建一个子记录

但是你正在反过来,即在子记录中创建parentRecord 。 你需要改变这一点。

另外, 在rails模块中 ,在Client Model中 ,您调用了accepts_nested_attributes_for:projects ,就像emberjs一样,它只允许您从Client创建项目记录,反之亦然。 有关如何在rails指南 , railscasts和嵌套属性中使用accepts_nested_attributes_for的所有示例都显示了从父模型中的表单创建的子模型的字段。

所以rails和emberj都在这个用例中从子记录创建parentRecord。 这可能是您遇到client-id问题的原因。 所以扭转你的设计 ,再试一次。 如果它仍然没有发送客户端ID。 然后你应该在客户端模型上调用toJSON,它是父关联,如我发布的初始链接的第一个链接所示,建议你在restAdapter中调用toJson上的{associations:true}

  App.Client ## toJSON: (options={}) -> options['associations'] = true @_super(options) 

我希望这有帮助。 请回顾一下有效或无效的内容,以便遇到类似问题的其他人发现这篇文章可以知道从哪里开始。

最后,使用active_model_serializer gem创建rails api也没什么坏处,这是ember-core团队推荐的用于为ember-data和RestAdapter创建rails api的gem。 通过这种方式,您可以从ember端和rails端侧载和嵌入关联。