【问题标题】:Complex After save association in ruby on rails在 ruby​​ on rails 中保存关联后复杂
【发布时间】:2013-03-02 05:35:40
【问题描述】:

理论:- 在customer bill 中创建记录后,我将发送两组数据和两个不同的模型。一组数据发送到ledger,一组数据发送到ledger_line_item。复杂性在于,在发送数据后,我希望将ledger_id 存储在ledger_line_item 中。代码如下

代码:-

class CustomerBill < ActiveRecord::Base
  after_create :creating_ledger_line_items, :creating_ledger_items

  def creating_ledger_items
    CustomerLedger.create(:customer_id =>self.customer_id,/*rest of attributes*/)
  end

  def creating_ledger_line_items
    CustomerLedgerLineItem.create(:customer_id =>self.customer_id,/*rest of attributes*/)
  end
end

在我写的分类帐中

class CustomerLedger < ActiveRecord::Base
  after_save :update_record_line_items

  def update_record_line_items
    a = CustomerLedgerLineItem.find_by_customer_id(self.customer_id)
    a.update_attributes(:customer_ledger_id => self.id)
  end
end

上面的代码工作正常,没有错误,但ledger_id 没有发布在ledger_line_items 中。我无法确定为什么会发生此错误?在创建账单后,我还有其他方法可以实现在ledger_line_items 中发布ledger_id 的目标吗? 需要指导。提前谢谢你。

【问题讨论】:

  • 我看到的方式是您手动创建给定属性列表的项目。您可以通过查看 accepts_nested_attributes_for 来实现您想要的,这将简化您的代码。

标签: ruby-on-rails activerecord callback ruby-on-rails-3.2 after-save


【解决方案1】:

你可以改变你的模型如下:

我假设你有Customer Model

class Customer < ActiveRecord::Base
  has_one :customer_ledger
  has_many :customer_ledger_line_items, :through => :customer_ledger   
  accepts_nested_attributes_for :customer_ledger

end

class CustomerLedger < ActiveRecord::Base
  has_many :customer_ledger_line_items
  accepts_nested_attributes_for :customer_ledger_line_items
end

class CustomerBill < ActiveRecord::Base
  belongs_to :customer
  after_create :creating_ledger_items, :creating_ledger_line_items

  def creating_ledger_line_items
   cl = self.customer.customer_ledger.build(your_attributes)
   cl.save!
  end

  def creating_ledger_items
    cli = self.customer.customer_ledger.customer_ledger_items.build(your_attributes)
    cli.save!     
  end
end

【讨论】:

    【解决方案2】:

    如果您想在 *after_create* 挂钩上创建模型,我将解释问题所在。

    当您在 Rails 中创建模型时,您有 *after_create*、*before_update* 等钩子。所有更新都发生在事务中,因此如果其中任何一个引发异常,则不会更新任何内容。

    在这种情况下,在事务中,您试图获取尚不存在的 CustomerLedger 的 ID,因为由于所有内容都在事务中,因此在执行事务之前不会将记录保存到数据库中,这就是在 CustomerLedger#update_record_line_items 上,self.id 始终为 nil 的原因。

    使用 codeit 提出的嵌套属性可能是解决您问题的最佳方法,但如果您觉得嵌套属性是一个高级主题,您可以执行以下操作:

    class CustomerBill < ActiveRecord::Base
    
      after_create :created_leder_data
    
      def create_ledger_data
        customer_ledger = CustomerLedger.build(customer_id: self.customer_id, # Rest of attributes)
        customer_ledger.customer_ledger_line_items.build(customer_id: self.customer_id, # Rest of attributes)
        customer_ledger.save!
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多