Reputation: 1446
Quick question about a simple problem I am facing (and I want to use as a way to understand a few things about associations and rails in a deeper level). Here goes:
The two associated models are
class Employee < ActiveRecord::Base
attr_accessible :name
attr_accessible :age
belongs_to :role
attr_accessible :role_id
end
class Role < ActiveRecord::Base
attr_accessible :title
attr_accessible :salary
has_many :employees
end
so that every new employee has a fixed salary, according to his role (which is the case most of the times). However, what if I want to set a different salary for a specific employee?
Using simple_form
I have so far written the following:
<%= f.input :name, label: 'Employee Name', :required => true %>
<%= f.association :role, as: :radio_buttons, :required => true %>
<%= f.input :salary, label: 'Employee Salary', :input_html => { :value => 0 }, :required => true %>
Which of course gives me a can't mass assign protected attributes: salary
error.
To fix that, I added attr_accessible :salary
to the Employee
model but that just changed the error to unknown attribute: salary
.
From what I understand I have to first change something in the new employee and then also in the employee model and controller so it accepts a value for the salary and knows how to handle it, right?
I 've also seen accepts_nested_attributes_for
used but I am not entirely sure in which side of the association it should go - as I am not entirely sure the association is architectured in the best way either.
Upvotes: 0
Views: 150
Reputation: 35350
You need to add a salary
column to your employees
table if you are in fact wanting to allow a custom salary to be specified on the Employee
. In your terminal, create a new migration and apply it
rails generate migration AddSalaryToEmployees salary:integer
RAILS_ENV=development rake db:migrate
By the way, you don't need to call attr_accessible
multiple times; it accepts an arbitrary # of symbols
attr_accessible :name, :age, :role_id, :salary
Also, since you mentioned it, I'll comment on it: accepts_nested_attributes_for
currently has no place in your models (given the code you've shown so far).
To answer the questions raised in your comment:
Isn't that duplication of code (having salary in both models I mean)?
No, they serve two different purposes. :salary
in Role
is the default salary applied to all Employees
associated with that Role
. :salary
on Employee
is an 'override' for special circumstances where an Employee
's salary doesn't fit the mold of the Role
they're associated with.
Role
just for this purpose (assuming the custom salary is the only difference for the Employee
)Role
itself, because that would affect the salary of the other Employees
associated with that Role
And doesn't that need another method (to make sure that the role salary is set as the employee's salary if none is specifically set)?
Another method? No. Customizing the existing attr_reader for salary
on Employee
to return the default from the Role
if an 'override' hasn't been set? If you want
def salary
return role.salary if read_attribute(:salary).blank?
read_attribute(:salary)
end
Upvotes: 1