视图/控制器中的关系问题

时间:2010-11-17 22:11:42

标签: ruby-on-rails activerecord ruby-on-rails-3

我有两个类似的模型(简化):

RECIPE(has_one video)

  • id
  • 姓名
  • descripion

视频(belongs_to食谱)

  • ID
  • 链接
  • recipe_id

在RecipesController #new中,我渲染了一个用于创建资源的视图。 我使用form_for @recipe和所有常规f.helpers

问题是我需要一个字段来填充链接属性,这属于另一个对象(视频)。因此,由于f.helpers使用resource [field]作为前缀,我使用了常规的text_field_tag:link。

到目前为止,一切顺利。在RecipesController #create中我做:

@recipe = Recipe.new(params[:recipe])
@recipe.video = Video.new(params[:link])

将视频分配给食谱。

在此之后我做了通常的@ recipe.save,这就是我被困住的地方。

我预计如果视频中包含任何错误,配方将不会保存,并且我将能够使用@ recipe.errors对象来获取所有错误(也来自视频中的错误)。

但不仅配方保存,@ recipe.errors不包含来自视频的消息。 我使用(部分“错误”,:object => @recipe)列出所有消息,但这不会获取视频对象触发的消息。

我尝试了各种各样的东西,例如,在部分内部我有一个最初检查的条件:

if object.errors.any?
 object.errors.full_messages ...
end

我把它换成了:

if(object.errors.merge!(object.video.errors))。any? 但它没有悲伤地工作。

在这种情况下我该怎么办?如何在视频出错时阻止@recipe保存,以及如何将它们无缝地列在一起?

1 个答案:

答案 0 :(得分:1)

处理嵌套对象需要一些工作,但并不难。从Rails 2.3开始,出现了“嵌套属性”和“嵌套对象形式”的概念(参见:http://guides.rubyonrails.org/2_3_release_notes.html#nested-attributeshttp://guides.rubyonrails.org/2_3_release_notes.html#nested-object-forms)。

基本上,这可以让你做这样的事情:

<% form_for @recipe do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :description %>
  <% f.fields_for :video do |v| %>
    <%= v.text_field :link %>
  <% end %>
<% end %>

如您所见,代码告诉表单在配方中有field_for:视频对象。然后您可以改变您的食谱:

class Recipe < ActiveRecord::Base
  has_one :video
  accepts_nested_attributes_for :video
end

此代码告诉ActiveRecord您可以使用配方传入视频对象的属性。所以现在,你所要做的就是。 。

Recipe.create(params[:recipe])

。 。 。它将创建配方和视频记录,因为您的表单包含视频信息,Recipe类接受_nested_attributes_for:video。

-

只是澄清一些关于代码的事情。你将params [:link]传递给Video.new。 Video.new不期望一个字符串,它期望一个属性的哈希。所以,你在打电话。 。

Video.new("example.com/video_file.mp4")

。 。 。当你真的想要传入时。

Video.new(:link => "example.com/video_file.mp4")

不是哈希,ActiveRecord不知道您尝试通过“新”设置哪个属性。你也可以这样做。 。

v = Video.new
v.link = params[:link]

。 。 。并设置该方式的属性。另外,根据控制器中的其他内容,您可能无法将recipe_id分配给视频,而您可能不会调用@ video.save。有时,ActiveRecord的酷感可以让它看起来好像不会发生这些事情 - 如果你使用的东西如accept_nested_attributes_for,你不需要做那些事情。但是,如果要手动执行此操作,则必须确保将它们全部保存,分配关联,检查两个对象是否存在错误以及管理事务。

-

关于这个的Rails文档并不错,并且经历了很多:http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Ryan Daigle也有一篇很好的博客文章:http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes