2010-11-17 83 views
1

我有两个模型(简体)与此类似:关系问题/控制器

食谱(HAS_ONE视频)

  • ID
  • descripion

VIDEO(belongs_to recipe)

  • ID
  • 链接
  • recipe_id

在的RecipesController#新我使创建资源视图。 我使用form_for @recipe,与所有常规f.helpers

事情是,我需要一个字段来填写链接属性,并且属于不同的对象(视频)。所以,由于f.helpers前缀与资源[字段]的一切,我用了一个常规的text_field_tag:链接。

到目前为止一切顺利。在的RecipesController#创建我做的:

@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 

我换它:

如果(object.errors.merge(对象。 video.errors))。任何? 但它并没有悲伤地工作。

在这种情况下应该怎么做?如何防止@recipe在视频发生错误时保存,以及如何无缝地列出它们?

回答

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 %> 

正如你看到的,代码是有fields_for一个告诉的形式。然后你可以改变你的食谱,像这样:

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

这段代码告诉ActiveRecord的,你可能会在属性传递的视频对象与配方。所以现在,你所要做的就是。 。 。

Recipe.create(params[:recipe]) 

。 。 。它会创建配方和视频记录,因为您的表单具有视频信息和Recipe类accep_nested_attributes_for:video。

-

只是为了澄清一些关于你的代码的东西。你传递参数[:链接]到Video.new。 Video.new不期望一个字符串,它期望一个哈希的属性。所以,你在打电话。 。 。

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

。 。 。当你真的想要通过时。 。

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

不是散列,ActiveRecord不知道你试图通过“new”设置哪个属性。你也可以做。 。 。

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

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

-

这个Rails的文档也不错,去了不少呢:http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

瑞安英对照精华文章也有一个很好的博客帖子大约是:http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

+0

谢谢!我不知道嵌套的对象形式。这将非常方便,因为我经常会碰到这个问题。 – zyash 2010-11-17 22:45:29

+0

事实上,我遇到了一个小问题,我不太清楚控制器中该做什么,目前看起来像这样:RecipesController#new:@recipe = Recipe.new,RecipesController#create:@recipe = Recipe.new (params [:recipe])... if @ recipe.save ...但它不会在视图中显示嵌套窗体。我在#new部分添加了以下内容:@ recipe.video = Video.new,并将其显示出来,但是当我提交表单时,我没有得到视频的字段:/ – zyash 2010-11-19 17:56:34

+0

糟糕,这是因为在配方模型中,我没有添加:video_attributes to attr_accessible。现在工作正常。再次感谢!! – zyash 2010-11-19 18:05:22