问题
In my sub-ledger accounting rails app I have a funds model
class Fund < ActiveRecord::Base
belongs_to :agency
has_many :gl_accounts
accepts_nested_attributes_for :gl_accounts
attr_accessible :name, :agency_id, :fund, :user_stamp, :active
attr_accessible :gl_accounts_attributes
and a gl_accounts model
class GlAccount < ActiveRecord::Base
belongs_to :agency
belongs_to :fund
has_many :class_sessions
has_many :facilities
validates :agency_id, :fund_id, :name, :gl_account_number, :active, :user_stamp, :account_type, :presence => true
validates_uniqueness_of :account_type, :scope => :fund_id, :if => :unique_account_type
attr_accessible :agency_id, :fund_id, :name, :gl_account_number, :active, :user_stamp, :account_type
def unique_account_type
[3,4,6,7,8].include? account_type
end
When a new fund is created there are 5 gl_accounts that must be created at the same time so I am using fields_for
to create the 5 new records in the gl_account model when the new record is created for fund. It all seems to work OK until I submit the form and I get an error saying that "Gl accounts fund cannot be blank."
There is no "fund" attribute on the gl_accounts model. I thought that maybe rails was dropping the "_id" part (since there is a fund_id foreign key field) but I was under the understanding that using nested models and fields_for
automatically added the proper value in the fund_id field (the foreign key of the gl_account model). But even if I add a hidden field in the form with a value for fund_id I still get the error saying that "fund" cannot be blank.
So, maybe rails is trying to tell me I have something else wrong?
Here are the params:
{"utf8"=>"✓",
"authenticity_token"=>"MNWLFOnLOE+ZRsUf9mogf2cq/TeQ+mxtrdaVu3bEgpc=",
"fund"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"name"=>"Junk",
"fund"=>"44",
"active"=>"1",
"gl_accounts_attributes"=>{"0"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"account_type"=>"6",
"name"=>"Cash Account",
"active"=>"1",
"fund_id"=>"1",
"gl_account_number"=>"44-498-965-789"},
"1"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"account_type"=>"7",
"name"=>"Credit Card Account",
"active"=>"1",
"fund_id"=>"1",
"gl_account_number"=>"44-498-965-163"},
"2"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"account_type"=>"3",
"name"=>"Customer Account Balances",
"active"=>"1",
"fund_id"=>"1",
"gl_account_number"=>"44-498-965-254"},
"3"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"account_type"=>"8",
"name"=>"Refunds Pending Account",
"active"=>"1",
"fund_id"=>"1",
"gl_account_number"=>"44-498-965-456"},
"4"=>{"agency_id"=>"1",
"user_stamp"=>"6",
"account_type"=>"4",
"name"=>"Deferred Revenue Account",
"active"=>"1",
"fund_id"=>"1",
"gl_account_number"=>"44-498-965-159"}}},
"commit"=>"Add New Fund"}
回答1:
Try removing fund_id from the presence true validation in GlAccount class.
validates :agency_id, :name, :gl_account_number, :active, :user_stamp, :account_type, :presence => true
And also don't add fund_id as hidden field because , you are right, 'fields_for' will automatically take care of that but that will happen after validations.
So you don't need fund_id to be validated for presence.
Update
Also to ensure that fund_id is never null you can put a constraint in database table. Create a migration with the following code.
change_column :gl_accounts, :fund_id, :integer, :null => false
Update 2
To ensure that fund is there you need to check for presence of fund not fund_id.
validates :fund, :presence => true
And for this to work you need to declare your associations with 'inverse_of' like below.
class Fund < ActiveRecord::Base
has_many :gl_accounts, inverse_of: :fund
accepts_nested_attributes_for :gl_accounts
end
class GlAccount < ActiveRecord::Base
belongs_to :fund, inverse_of: :gl_accounts
validates_presence_of :fund
end
For more details please refer this guide. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#label-Validating+the+presence+of+a+parent+model
来源:https://stackoverflow.com/questions/18290752/rails-error-message-using-fields-for