场景:我有一个 has_many 关联(Post 有很多作者),并且我有一个嵌套的 Post 表单来接受作者的属性。
我发现当我调用 post.update_attributes(params[:post]) 其中 params[:post] 是一个带有 post 和所有要添加的作者属性的哈希时,似乎没有办法让 Rails 只如果满足某些条件,则创建作者,例如作者的用户名已经存在。如果用户名在模型中具有唯一性验证,Rails 会做的只是失败并回滚 update_attributes 例程。如果没有,Rails 将添加一个新记录 Author,如果没有 id 的记录在哈希中。
现在我在 Post 控制器中的更新操作代码变成了这样:
def update
@post = Post.find(params[:id])
# custom code to work around by inspecting the author attributes
# and pre-inserting the association of existing authors into the testrun's author
# collection
params[:post][:authors_attributes].values.each do |author_attribute|
if author_attribute[:id].nil? and author_attribute[:username].present?
existing_author = Author.find_by_username(author_attribute[:username])
if existing_author.present?
author_attribute[:id] = existing_author.id
@testrun.authors << existing_author
end
end
end
if @post.update_attributes(params[:post])
flash[:success] = 'great!'
else
flash[:error] = 'Urgg!'
end
redirect_to ...
end
有没有更好的方法来处理我错过的这个问题?
编辑:感谢@Robd'Apice 让我考虑覆盖默认的 authors_attributes= 函数,该函数代表我插入到模型中,我能够想出更好的东西:
def authors_attributes=(authors_attributes)
authors_attributes.values.each do |author_attributes|
if author_attributes[:id].nil? and author_attributes[:username].present?
author = Radar.find_by_username(radar_attributes[:username])
if author.present?
author_attributes[:id] = author.id
self.authors << author
end
end
end
assign_nested_attributes_for_collection_association(:authors, authors_attributes, mass_assignment_options)
end
但是我对此并不完全满意,一方面,我仍然直接从调用者那里获取属性哈希,这需要了解这些哈希的逻辑是如何工作的(例如:id set or not set),以及两个,我正在调用一个适合此处的函数。如果有办法告诉“accepts_nested_attributes_for”只在不满足特定条件时创建新记录,那就太好了。一对一关联有一个 :update_only 标志,它执行类似的操作,但缺少一对多关系。
有更好的解决方案吗?