在Rails中创建关联对象时出错

时间:2009-02-06 16:43:48

标签: ruby-on-rails associations

我有一个创建动作,试图一次创建一个评级和一个程序:

  def create
    @rating = current_user.ratings.create(params[:rating])
    @rating.create_programme(params[:programme])
    redirect_to ratings_path
  end

在此代码中,评级属于用户和程序以及用户

  has_many :ratings
  has_many :programmes, :through => :ratings

和一个程序

  has_many :users, :through => :ratings
  has_many :ratings

当我在RatingsController中调用上面的create动作时,由于某种原因,程序不会被@rating保存。所以,如果我打电话给:例如:

rating.programme.channel 

在视图中的评级上,它告诉我该程序是一个零对象。但是,程序保存得很好 - 它只是尚未保存的关联。我确信这是一个非常基本的东西,但我无法弄明白。有人能指出我正确的方向吗?

谢谢,

4 个答案:

答案 0 :(得分:2)

回答您的问题,以帮助使代码更清洁:

def create
  @rating = Rating.new(params[:rating])
  @rating.user      = curent_user
  @rating.programme = Programme.find_or_create_by_title(params[:programme])
  @rating.save

  redirect_to ratings_path
end

首先,你调用find_or_create作为标题,然后保存它,但是记录将在那里创建,所以保存根本不做任何事情。其次,虽然关联代理对于轻松创建夸张的对象很酷,但是它们可能会像你在这里一样处于更加复杂的关系中而变得非常毛茸茸,并使代码更难以阅读。

因此,不是使用关联代理来创建记录,而是直接分配会更好。它更容易一目了然地告诉我们发生了什么以及信息来自何处,并且不需要在那里进行丑陋的合并调用。它还要长一点,但我认为它一目了然就更容易被理解了。

最后,您可能不需要@programme作为独立的实例变量,因为您可以在视图中从@rating.programme轻松访问该对象。在大多数情况下,最好尽可能少地传递实例变量,尤其是当对象具有易于访问的直接关系时。在这种情况下尤其如此,因为你根本没有渲染模板。

答案 1 :(得分:0)

您的代码看起来正确。试试这个。点击此创建操作后立即进入脚本/控制台,看看是什么时候进行的。类型:

Rating.last

它应该返回刚刚创建的评级。在输出中查找user_idprogramme_id,看看它们是否已设置。如果他们那么你在其他地方有一个错误。也许你没有看到你认为自己的评价或其他什么。

答案 2 :(得分:0)

您是否正在尝试从孩子创建父级(评级属于Program,对吗?)。我觉得这不行。

Programme.ratings.create可行。

答案 3 :(得分:0)

我通过以下方式使创建操作正常工作。如果有人能让我知道是否有一种更优雅的方式让它发挥作用,我将不胜感激:)

  def create
    @programme = Programme.find_or_create_by_title(params[:programme])
    @programme.save
    @rating = current_user.ratings.create!(params[:rating].merge(:programme_id => @programme.id))
    redirect_to ratings_path
  end

和j