I have two models Employee and Documents which are as follows:
Employee.rb
class Employee < ActiveRecord::Base
has_one :document #,dependent: :destroy
attr_accessible :age, :dob, :empNo, :first_name, :gender, :last_name, :middle_name, :document_attributes
accepts_nested_attributes_for :document
validates :first_name, presence: true , length: { maximum: 50 }
validates :empNo, presence: true, uniqueness:{ case_sensitive: false }
validates_length_of :empNo, :minimum => 5, :maximum => 5
#before save { |user| user.email = email.downcase }
end
Document.rb
class Document < ActiveRecord::Base
belongs_to :employee,foreign_key: "empno"
attr_accessible :idate, :iedate, :insuranceno, :iqamano, :iqedate, :iqidate, :passportno, :pedate, :pidate, :vedate, :vidate, :visano
end
and the controller file is employees_controller.rb(I have only shown new,create,show funcs)
def show
@employee = Employee.find(params[:id])
@document=Document.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @employee }
end
end
# GET /employees/new
# GET /employees/new.json
def new
@employee = Employee.new
@document= Document.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json=>{:employee=> @employee,:document=>@document}, status: :created, :location=>{:employee=> @employee,:document=>@document} }
end
end
# POST /employees
# POST /employees.json
def create
@employee = Employee.create!(params[:employee])
@document = Document.create!(params[:document])
respond_to do |format|
if @employee.save and @document.save
format.html { redirect_to @employee, notice: 'Employee was successfully created.' }
format.json { render :json=>{:employee=> @employee,:document=>@document}, status: :created, location: @employee }
else
format.html { render action: "new" }
format.json { render json: @employee.errors, status: :unprocessable_entity }
end
end
end
When I create a new employee I get the following error
ActiveModel::MassAssignmentSecurity::Error in EmployeesController#create
Can't mass-assign protected attributes: document
The requsts parameters are fine as seen below
{"utf8"=>"✓",
"authenticity_token"=>"vXSnbdi+wlAhR5p8xXvTWhi85+AVZgOZufClx73gc8Q=",
"employee"=>{"empNo"=>"11111",
"first_name"=>"Thaha",
"middle_name"=>"Muhammed",
"last_name"=>"Hashim",
"age"=>"25",
"gender"=>"M",
"dob(1i)"=>"2014",
"dob(2i)"=>"7",
"dob(3i)"=>"18",
"document"=>{"passportno"=>"bycucde63"}},
"commit"=>"Create Employee"}
I have gone through nearly all posts on stackoverflow dealing with this issue and mostly the issue is related to
attr_accessible
accepts_nested_attributes_for
:document_attributes
If I change the value of config.active_record.whitelist_attributes
to false then the error goes away(There is a warning in developer log about the same) and both the models are created but only attributes of employee model is filled with passed values wheras the attributes of document model is nil.
EDIT #1 If I tried to add :document to attr_accessible then I get the following error
ActiveRecord::AssociationTypeMismatch in EmployeesController#create
What is that I am doing wrong here?
Understanding Mass Assignment
Mass Assignment is the name Rails gives to the act of constructing your object with a parameters hash. It is "mass assignment" in that you are assigning multiple values to attributes via a single assignment operator.
The following snippets perform mass assignment of the name and topic attribute of the Post model:
Post.new(:name => "John", :topic => "Something")
Post.create(:name => "John", :topic => "Something")
Post.update_attributes(:name => "John", :topic => "Something")
In order for this to work, your model must allow mass assignments for each attribute in the hash you're passing in.
There are two situations in which this will fail:
You have an attr_accessible
declaration which does not include :name
You have an attr_protected
which does include :name
It recently became the default that attributes had to be manually white-listed via a attr_accessible in order for mass assignment to succeed. Prior to this, the default was for attributes to be assignable unless they were explicitly black-listed attr_protected or any other attribute was white-listed with attr_acessible.