从after_save块访问父对象

时间:2011-05-12 16:24:23

标签: ruby-on-rails

这是我的模特:

class Why < ActiveRecord::Base
  belongs_to :story
  after_save :complete

  private
    def complete
      self.story.update_attributes(:completed => true)
    end
end

和控制器代码:

class WhiesController < ApplicationController

  def index
    @whies = Why.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @whies }
    end
  end

  def show
    @why = Why.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @why }
    end
  end

  def new
    @why = Why.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @why }
    end
  end

  def create
    @story = Story.find(params[:story_id])
    @why = @story.build_why(params[:why])

    respond_to do |format|
      if @why.save
        format.html { redirect_to story_path(@why.story) }
        format.xml  { render :xml => @why, :status => :created, :location => @why }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @why.errors, :status => :unprocessable_entity }
      end
    end
  end

  def destroy
    @why = Why.find(params[:id])
    @why.destroy

    respond_to do |format|
      format.html { redirect_to(whies_url) }
      format.xml  { head :ok }
    end
  end

end

我从完整的after_save方法得到The error occurred while evaluating nil.update_attributes错误。任何人都可以建议问题是什么,或解决方法?

2 个答案:

答案 0 :(得分:2)

我假设你的Storyhas_one :why

在控制台中玩游戏,看起来你的代码运行得很好,我第一次运行它。如果我再这样做(使用相同的@story),我收到了你的错误。

当您执行build_why时,Rails正在检查@story是否已经有另一个Why对象与之关联,如果是,则删除该关联。当它删除此关联时,它会对上一个故事执行after_save回调,此时self.story现在为nil。在您拨打@why.save之前,您会在日志中看到这种情况。

您可能只需将update_attributes来电包裹在if self.story条件中,但程序中的逻辑可能存在较大的缺陷。

答案 1 :(得分:1)

实际上你的代码很好。

试试这个:

@story = Story.find(params[:story_id])
@why = Why.new(params[:why])
@why.story = @story