嵌套关联中的Rails Active Record Callbacks错误

时间:2012-11-22 06:12:03

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

我在包含accepts_nested_attributes

的模型中遇到Active Record回调问题

我使用build_associated_parties回调来呼叫after_create,但这些值未被保存,我收到<nil>错误。我也尝试过使用before_create&amp; after_initialize回调没有成功。

是什么导致回调失败?

connection.rb

class Connection < ActiveRecord::Base 
  attr_accessible :reason, :established, :connector, :connectee1,
                  :connectee2, :connectee1_attributes,
                  :connectee2_attributes, :connector_attributes 

  belongs_to :connector, class_name: "User" 
  belongs_to :connectee1, class_name: "User"
  belongs_to :connectee2, class_name: "User"

  accepts_nested_attributes_for :connector, :connectee1, :connectee2 

  belongs_to :permission 

  after_create :build_associated_parties    

  # builds connectee's, connector, permission objects
  def build_associated_parties   
    build_connector
    build_connectee1
    build_connectee2
    build_permission
  end

connection_controller.rb

class ConnectionsController < ApplicationController
  def new
    @connection = Connection.new
  end

  def create        
    @connection = Connection.new params[:connection]
    if @connection.save     
      flash[:notice] = "Connection created successfully!"
      redirect_to @connection
    else
      render :new
    end
  end
end

但是,如果我在控制器内部构建这些属性,如下所示,我不会收到错误。这很好,但似乎反对将业务逻辑代码保留在控制器之外。

class ConnectionsController < ApplicationController
  def new
    @connection = Connection.new
    @connection.build_connectee1
    @connection.build_connectee2
    @connection.build_connector
  end
end

如何使用模型中的代码实现相同的功能?将它保留在模型中是否有优势?

3 个答案:

答案 0 :(得分:1)

您在创建build_associated_parties后调用了方法connection,所以这些方法如何:

 build_connector
 build_connectee1
 build_connectee2
 build_permission

知道它会使用什么样的参数?因此,他们不知道传递给方法的值是什么,然后他们会得到错误。在控制器中,他们没有错误,因为他们使用了params[:connection]的值。

在您的表单上,如果您已经有connector, connectee1, connectee2的字段,则应该在新控制器中放置初始化对象的代码。保存@connection时,它也会保存这些对象。我认为这些代码不需要放入模型中。您的模型应该只放置其他逻辑代码,如搜索或计算...

答案 1 :(得分:0)

after_create是一个很大的问题。在模型中使用after_initialize,并在self方法中使用build_associated_parties。看看是否有效。

答案 2 :(得分:0)

将逻辑移出控制器并返回模型。但是,build_*代码覆盖了我传递给嵌套属性的值。

通过向这些build_方法添加除非{attribute} ,我能够正确传入值。

class Connection&lt;的ActiveRecord :: Base的         attr_accessible:reason,:established,:connector,:connectee1,:connectee2,                 :connectee1_attributes,:connectee2_attributes,:connector_attributes

  belongs_to :connector, class_name: "User"
  belongs_to :connectee1, class_name: "User"
  belongs_to :connectee2, class_name: "User"

  accepts_nested_attributes_for :connector, :connectee1, :connectee2

  belongs_to :permission

  after_initialize :build_associated_parties

  validates :reason, :presence => true
  validates_length_of :reason, :maximum => 160

  #builds connectee's, connector, permission objects
  def build_associated_parties
    build_connector unless connector
    build_connectee1 unless connectee1
    build_connectee2 unless connectee2
  end