Rails 3: validates_presence_of validation errors on default value and in associated model
model-associations, ruby, ruby-on-rails
Solution
Both of these validation errors are occurring because validations get called before save (and before the `before_save` callback).
I'm assuming that you're using a nested_form to create the invoice and it's line items at the same time. If this is the case, you don't want to `validates :invoice_id, :presence => true` on the line items - the invoice and the line items are coming in at the same time, and the invoice hasn't been saved yet, so it doesn't have an id. If you leave the validation in, you'll need to create and save an empty invoice first, and then create the line items later so the invoice_id is available. If you only want to make sure invoice_id is still set after any edits, you can enforce this via `validates :invoice_id, :presence => true, :on => :update` this will skip the validation when the line item is being created (and the invoice_id isn't available yet).
You're running into problems with `validates :status, :presence => true` for similar reasons - the values coming in via the request are being validated against, and the "status" value isn't there. The `before_save` callback runs after validation. You can set the default value in the `before_validation` or `after_initialization` callback and the values will be there when validations are run.
Check out the Callbacks documentation for Rails for more info.
Problem
I have a basic invoice setup with models: Invoice, Item, LineItems. ``` # invoice.rb class Invoice < ActiveRecord::Base has_many :line_items, :dependent => :destroy validates_presence_of :status before_save :default_values def default_values self.status = 'sent' unless self.status end end # item.rb class Item < ActiveRecord::Base has_many :line_items validates_presence_of :name, :price end # line_item.rb class LineItem < ActiveRecord::Base belongs_to :item belongs_to :invoice before_save :default_values validates_presence_of :invoice_id validates :item_id, :presence => true end ``` There is more in the model but I only presented the above for simplicity. I get the following errors: ``` 2 errors prohibited this invoice from being saved: Line items invoice can't be blank Status can't be blank ``` So two problems: If I remove `validates :invoice_id, :presence => true` I don't get the `Line items invoice can't be blank` error message anymore, but why? I do want to validate the invoice_id on line_items, ALL line_items are supposed to have an invoice_id. How can I validate the invoice_id on line_items without getting an error? Why am I getting the `Status can't be blank` error if I set it as a default value? I can probably set it up on the invoices_controller but I think the default value should be set in the model, right? How can I validate the presence of status and still have a default value in the model for it?