我正在开发一个复杂的表单,一次更新一个模型的几个记录,同时更新相关的模型。看起来有点像这样:
class Sport
has_one :photo
end
class Photo
belongs_to :sport
acts_as_fleximage
end
class Page
# the page is not related to either of the previous models
end
仅仅为了一些背景信息,Page模型是一个通用模型,用户可以根据自己的喜好创建任意数量的模型(CMS)。此外,他们在注册时会获得少量强制性“系统”页面。当他们尝试编辑系统页面时,表单与通用页面表单略有不同。
其中一个系统页面是“运动”页面。他们可以为他们的每项运动添加一些文字(保存在“运动”模型中)并上传照片(保存在“照片”模型中)。
我制作了一个似乎正在耍手段的表格。我不会发布视图,但这里是它发送的参数示例:
:id => 1
:page => {"title"=>"Our sports"}
:sport => {
"1" => {
"description" => "<p>I love playing hockey...</p>"
"photo_attributes" => {
"image_file" => #<File:/tmp/RackMultipart20100126-955-k0gxu8-0>,
"description" => "Me in my hockey kit"
}
},
"2" => { #more of the same}
}
现在,为了保存所有这些,我的控制器/动作看起来像这样:
def update_sports_page
@page = Page.find params[:id]
@page.update_attributes params[:page]
Sport.update(params[:sport].keys, params[:sport].values)
redirect_to #etc
end
现在,当我编辑体育页面时,所有内容都会正确保存和更新,除非我更改照片,而不是更新数据库中的现有记录,它只是创建一个新记录并设置sport_id
将旧记录改为NULL
。
所以最终,经过多次编辑后,数据库中存在大量的孤儿记录。
有人能发现我在这里做错了吗?
(ps,如果相关,我在Photo模型上使用fleximage)
答案 0 :(得分:1)
这可能是正确的行为,因为该关联已设置:dependent =&gt; :默认为nullify,不是:dependent =&gt; :破坏
可以用以下方法修复它:
class Photo
belongs_to :sport,
:dependent => :destroy
end
那应该自动删除孤儿记录。
在执行任何查找或更新操作时,您还应该小心捕获异常。
def update_sports_page
@page = Page.find params[:id]
@page.update_attributes params[:page]
params[:sport].each do |sport_id, sport_params|
sport = Sport.find(sport_id)
sport.update_attributes!(sport_params)
end
redirect_to #etc
rescue ActiveRecord::RecordNotFound
render(:partial => 'page_not_found', :status => :not_found)
rescue ActiveRecord::RecordInvalid
render(:action => 'edit')
end
这就是一个例子。编辑和更新方法应该有一个通用的“运动加载器”机制,它可以处理检索页面的所有相关记录,而不必在更新期间复制此功能。它负责捕获更新错误并在编辑页面上显示它们以供审核。