0

I'm trying to create a form using form_for which will add Employees. For an employee i want to assign multiple specializations such as c#, asp, etc as the values dynamically. I'm using the following code in the form

<%= f.select :specilization, Specialization.all.collect{|p| [p.name, p.id]}, {}, :multiple => true %>

I've also made HABTM between employees and specialization like

Employee.rb

class Employee < ActiveRecord::Base
has_and_belongs_to_many :specializations
end

Specialization.rb

class Specialization < ActiveRecord::Base
has_and_belongs_to_many :employees
end

with these done, im not able to save the selected values in db(MySQl). Would appreciate if anyone could solve my problem or guide me on how to get this right?

Thanks in advance.

Jarno Lamberg
  • 1,530
  • 12
  • 12
Abhishek
  • 31
  • 5

1 Answers1

0

I usually solve this by using has_many :through and then in my form the select is a field_for on the join model. Like this:

class Employee < ActiveRecord::Base
  has_many :employees_specializations
  has_many :specializations, through: :employees_specializations
  # we will be creating these join models on the employee form
  accepts_nested_attributes_for :employees_specializations
end

class Specialization < ActiveRecord::Base
  has_many :employees_specializations
  has_many :employees, through: :employees_specializations
end

class EmployeesSpecialization < ActiveRecord::Base
  belongs_to :employee
  belongs_to :specializations
end

Now it's important to note that with this simplified approach I'm assuming Specializations already exist in the database and we're just selecting them and joining them to the employee we're creating/editing:

# in your controller make sure to build at least 1 new instance, the fields_for needs this
@employee.employees_specializations.build

# remember to add to your strong parameters the new join attributes
params.require(:employee).permit(
  # ... other attributes ...
  employees_specializations_attributes: [:id, :specialization_id]
)

You need to declare :id, :specialization_id as sub fields since employees_specializations_attributes will be a nested hash with those keys inside.

# now in your form use fields_for
<%= f.fields_for :employees_specializations do |ef| %>
  <%= ef.select :specialization_id, Specialization.all.map{|p| [p.name, p.id]}, {}, multiple: true %>
<% end %>

That f.fields_for :employees_specializations will create form fields named employee[employees_specializations_attributes][][specialization_id]. Which basically says we are creating a nested association employees_specializations and setting that nested association's specialization_id (remember employees_specialization belongs_to :specialization) to the selected specialization. Note the [] in the middle of the field name, this means its an array of nested employees_specializations.

Post that and barring any validation errors you should be able to create/edit an employee and set it's specializations by selecting from a list of existing specializations and creating a join model between them.

Further reading:

Community
  • 1
  • 1
DiegoSalazar
  • 13,361
  • 2
  • 38
  • 55
  • Thank you. I followed your step. But i get a **no implicit conversion of Symbol to integer** error in the controller `def employee_params params.require(:employee).permit(:name, :specialization, :employees_specialization[:id, :specialization_id]) end` – Abhishek Sep 03 '14 at 13:17
  • You have a syntax error. The colon (:) is on the wrong side of `employees_specialization`. And also, it's not `employees_specialization`, it's `employees_specializations_attributes`. Make it: `employees_specializations_attributes: [:id, :specialization_id]` – DiegoSalazar Sep 03 '14 at 14:49
  • still no luck. not able to save it has an array. can save the same when i don't use the 'multiple' option in my select field in the form. – Abhishek Sep 10 '14 at 07:32