ruby-on-railsmodelattributesinitializationdry

How do I initialize attributes when I instantiate objects in Rails?


Clients have many Invoices. Invoices have a number attribute that I want to initialize by incrementing the client's previous invoice number.

For example:

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

I want to get this functionality into my Invoice model, but I'm not sure how to. Here's what I'm imagining the code to be like:

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

However, attributes[:client_id] isn't set when I call @client.invoices.build.

How and when is the invoice's client_id initialized, and when can I use it to initialize the invoice's number? Can I get this logic into the model, or will I have to put it in the controller?


Solution

  • Generate a migration that adds invoices_number column to users table. Then in Invoice model write this:

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

    This will automatically increase invoices_count attribute for user once the invoice is created.