代码之家  ›  专栏  ›  技术社区  ›  nfm

在Rails中实例化对象时,如何初始化属性?

  •  2
  • nfm  · 技术社区  · 16 年前

    Clients 有许多 Invoices . 发票有A number 属性,我希望通过增加客户端以前的发票号来初始化该属性。

    例如:

    @client = Client.find(1)
    @client.last_invoice_number
    > 14
    @invoice = @client.invoices.build
    @invoice.number
    > 15
    

    我想把这个功能放到我的 Invoice 模特,但我不知道怎么做。以下是我对代码的想象:

    class Invoice < ActiveRecord::Base
      ...
      def initialize(attributes = {})
        client = Client.find(attributes[:client_id])
        attributes[:number] = client.last_invoice_number + 1
        client.update_attributes(:last_invoice_number => client.last_invoice_number + 1)
      end
    end
    

    然而, attributes[:client_id] 不是 当我呼叫时设置 @client.invoices.build .

    发票是什么时候怎么开的 client_id 已初始化,何时可以使用它初始化发票 数 ?我能把这个逻辑放到模型中吗,还是必须把它放到控制器中?

    4 回复  |  直到 14 年前
        1
  •  7
  •   Eimantas    16 年前

    生成一个迁移,添加 invoices_number 列到用户表。然后在 Invoice 模型写下:

    class Invoice < ActiveRecord::Base
      belongs_to :user, :counter_cache => true
      ...
    end
    

    这将自动增加 invoices_count 创建发票后的用户属性。

        2
  •  5
  •   Patrick Klingemann    16 年前

    这个怎么样?

    class Invoice < ActiveRecord::Base
      ...
      def initialize(attributes = {})
        super
        self.number = self.client.invoices.size + 1 unless self.client.nil?
      end
    end
    
        3
  •  1
  •   Matt Briggs    16 年前

    首先,您不需要使用属性集合,只需 self.client_id . 更好的是,只要你有 belongs_to :client 在你 Invoice ,你可以这么做 self.client.last_invoice_number . 最后,如果更新或创建失败,您几乎总是希望引发异常,因此习惯于使用 update_attributes! ,这是一个更好的默认选择。(如果您对这些要点有任何疑问,请提问,我将详细介绍)

    现在,这已经过时了,您遇到了一些使用ActiveRecord的gotcha,初始值设定项方法几乎永远都不是正确的选择。AR为您提供了一系列方法来连接到您需要的生命周期的任何点上。这些是

    after_create
    after_destroy
    after_save
    after_update
    after_validation
    after_validation_on_create
    after_validation_on_update
    before_create
    before_destroy
    before_save
    before_update
    before_validation
    before_validation_on_create
    before_validation_on_update
    

    你可能想要的是在你创建之前加入。像这样的东西

    def before_create
      self.number ||= self.client.last_invoice_number + 1 unless self.client
    end
    

    它将为您的客户机访问数据库,获取最后一个发票编号,将其递增一个,并将其设置为新编号,但前提是您尚未设置编号(=将分配,但仅当左侧为零时),并且仅当您在保存之前设置了客户机(或客户机_id)。

        4
  •  1
  •   Zoltan Toth    14 年前

    下面是一些有用的讨论 after_initialize 根据Jonathan R.Wallace的上述评论: http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html

    推荐文章