我无法确定使用 Ember.js、Ember Data 和 Rails 将 hasMany 关联与单个表单保持一致的正确方法。一个客户有很多项目。我有一个新的项目表单,它有两个字段:项目名称和客户名称。 http://cl.ly/image/3z0P0R3M1t2u
我试图将我的创建逻辑保留在 Ember.js ClientsController 和 ProjectsController 中,但我是否需要将其中的一些移动到我的 ProjectsNewView 上的提交操作中?
更新:找到这个 issue 后我更新了我的代码.我越来越近了,但 Rails ProjectsController 仍然没有收到关联的 client_id。它不是 Controller 接收的参数的一部分。我仍然觉得我可能不会以最好的方式去做。
型号:
rails
class Client < ActiveRecord::Base
attr_accessible :name
has_many :projects
accepts_nested_attributes_for :projects
validates :name, :presence => true
end
class Project < ActiveRecord::Base
attr_accessible :name, :client_id
belongs_to :client
validates :name, :presence => 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.'
Controller :
rails
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,您必须 调用 toJSON 方法 在 RestAdapter 上并传递它:
{associations: true}
下面的链接解释了如何做到这一点:
https://stackoverflow.com/questions/10184213/is-there-a-way-to-post-embedded-objects-back-to-the-api-with-ember-data
Ember-data embedded objects stored as separate objects
Emberjs - unable to query for embedded model or association
更新
在我回答代码在哪里使用 toJSON 的问题之前,我想回到我刚刚在代码设计中观察到的一些事情。
您正在尝试在子记录中创建 parentRecord,因为 客户 是 parent ,而 项目是 child 。如果你观察得好,issue-115您链接到的,明确表示 parentRecord 存储将用于创建记录。此外,如果您最终检查测试 pull-request that was merged关于问题 115 ,您将再次看到它表示为 在 parentRecord 中创建子记录.
但你正在做相反的事情,即 在子记录中创建 parentRecord .你需要扭转这一点。
另外,在 rails 一侧 , 在 客户型号 ,您调用了接受嵌套属性:项目 , 就像 emberjs 一样只允许你创建 项目来自客户的记录,反之亦然。所有使用示例接受_nested_attributes_for 在 rails guide , railscasts这个在nested attributes ,显示从父模型中的表单创建的子模型的字段。
所以在这个用例中,rails 和 emberjs 都是从子记录创建 parentRecord。这可能就是您遇到客户端 ID 问题的原因。 所以反转你的设计再试一次。如果它仍然没有发送客户端 ID。然后您应该在作为父关联的客户端模型上调用 toJSON,如 first link 所示。从我发布的初始链接建议您调用 {关联:真} 在 restAdapter 中的 toJson 上。
App.Client
##
toJSON: (options={}) ->
options['associations'] = true
@_super(options)
我希望这有帮助。请评论什么有效或无效,以便其他遇到类似问题的人找到这篇文章可以知道从哪里开始。
最后,创建您的 不会有什么坏处。 rails API 与 active_model_serializer gem ,这是 ember-core 团队推荐的用于创建 的 gem rails API 对于 ember-data 和 RestAdapter。这样你就可以从 ember 端和 rails 端加载和嵌入关联。
关于ruby-on-rails - 如何使用 Ember Data & Rails 在单个 Ember.js 表单中保持 hasMany 关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12439165/