0

I've always had trouble with has_many :through relationships on join tables and am stuck again on where I'm going wrong. I think it might be in my controller as I'm still getting to grips with how it all works.

I have three models:

class Role < ActiveRecord::Base

    has_many :assignments, inverse_of: :role
    has_many :employees, :through => :assignments
    accepts_nested_attributes_for :assignments
end

class Employee < ActiveRecord::Base

  has_many :assignments, inverse_of: :employee
  has_many :roles, :through => :assignments
  accepts_nested_attributes_for :assignments

end

class Assignment < ActiveRecord::Base
    belongs_to :employee, inverse_of: :assignment
    belongs_to :role, inverse_of: :assignment
    accepts_nested_attributes_for :employee
    accepts_nested_attributes_for :role
end

I'd like to be able to set the pre-created role for an employee when creating or editing an employee. My New Employee form is as follows:

<%= semantic_form_for @employee do |f| %>
  <%= render 'shared/error_messages' %>
  <%= f.inputs do %>
    <%= f.input :first_name %>
    <%= f.input :last_name %>
    <%= f.input :email %>
    <%= f.input :password %>
    <%= f.input :password_confirmation %>
    <%= semantic_fields_for :roles do |role| %>
        <%= role.input :role, :as => :select, :collection => Role.all %>
        <%= role.semantic_fields_for :assignments do |assignment| %>
          <%= assignment.input :start_date, :as => :date_select %>
          <%= assignment.input :end_date, :as => :date_select %>
          <%= assignment.input :assignment_no %>
          <%= assignment.input :assignment_id %>
        <% end %>
      <% end %>
  <% end %>
  <%= f.actions do %>
    <%= f.action :submit, :as => :button %>
    <%= f.action :cancel, :as => :link %>
  <% end %>
<% end %>

and finally my Employee Controller is:

class EmployeesController < ApplicationController
  before_action :set_employee, only: [:show, :edit, :update, :destroy]

  def index
    @employees = Employee.paginate(page: params[:page])
  end

  def show
  end

  def new
    @employee = Employee.new
    role = @employee.roles.build
  end

  def edit
     @employee = Employee.find(params[:id])
  end

  def create
    @employee = Employee.new(employee_params)
    if @employee.save
      @employee.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end

  def update
    respond_to do |format|
      if @employee.update(employee_params)
        flash[:success] = "Profile updated"
        format.html { redirect_to @employee, notice: 'Employee was successfully updated.' }
        format.json { render :show, status: :ok, location: @employee }
      else
        format.html { render :edit }
        format.json { render json: @employee.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    Employee.find(params[:id]).destroy
    flash[:success] = "Employee deleted"
    respond_to do |format|
      format.html { redirect_to employees_url, notice: 'Employee was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_employee
      @employee = Employee.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def employee_params
      params.require(:employee).permit(:avatar, :email, :first_name, :last_name, :password, :assignments_attributes => [:employee_id, :role_id, :roles_attributes => [:id, :employee_id, :PID]])
    end
end

I appreciate that this subject is always on Stackoverflow, but I can't seem to translate any of the problems into where I am. Any help would be greatly appreciated!

The console output is as follows:

Started POST "/employees" for 127.0.0.1 at 2015-05-16 18:05:34 +0200
source=rack-timeout id=d5933405c94d9c2e8bca3332564528ec timeout=60000ms service=25ms state=active
Processing by EmployeesController#create as HTML
  Parameters: {"utf8"=>"✓",     "authenticity_token"=>"TgHHELkt2zXUtS474WwGeHcmfKKw/broHxRdhlsF1P4JyGoa+03rchb6mfxbOSXKdrPgcJMeBCyIlCMHqPlQBA==", "employee"=>{"first_name"=>"John", "last_name"=>"Smith", "email"=>"john@smith.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "roles"=>{"role"=>"2", "assignments"=>{"start_date(1i)"=>"2012", "start_date(2i)"=>"7", "start_date(3i)"=>"5", "end_date(1i)"=>"2016", "end_date(2i)"=>"3", "end_date(3i)"=>"1", "assignment_no"=>"4", "assignment_id"=>"A3392822"}}, "button"=>""}
Unpermitted parameter: password_confirmation
   (0.2ms)  BEGIN
source=rack-timeout id=d5933405c94d9c2e8bca3332564528ec timeout=60000ms service=1113ms state=active
  SQL (70.3ms)  INSERT INTO "employees" ("email", "first_name", "last_name", "password_digest", "created_at", "updated_at", "activation_digest") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["email", "john@smith.com"], ["first_name", "John"], ["last_name", "Smith"], ["password_digest", "$2a$10$g3PNppheVZ8AFnnKuWg6secBdGev0NlCXjUx.RXsky03Xl9L3CubO"], ["created_at", "2015-05-16 16:05:35.422312"], ["updated_at", "2015-05-16 16:05:35.422312"], ["activation_digest", "$2a$10$L0yFuvmlJon7fWod6lHj..O7yDRaqwqTlTkJgD7Evqx.dA4pDTlBC"]]
   (133.0ms)  COMMIT

(I'm working on a very slow computer!)

Dave C
  • 367
  • 5
  • 19
  • I don't fully understand your problem, the title makes it sound like you are trying to save additional attributes on the Assignment table? – fatfrog May 16 '15 at 00:09
  • Yes I am, which is why I chose a has_many through relationship, allowing additional data for the assignments model, but none of the details are saving to the database. – Dave C May 16 '15 at 00:11
  • The join model is only going have the 2 foreign keys populated automatically (role_id and employee_id. You are going to need to find the record in the join model and update it manually. @employee.assignments.where(role_id: @role.id).first – fatfrog May 16 '15 at 00:27
  • http://stackoverflow.com/questions/10568393/access-extra-attributes-in-join-table-when-using-though-in-has-many-relationship – fatfrog May 16 '15 at 00:30
  • That's fine, but currently even the foreign keys aren't being updated. – Dave C May 16 '15 at 10:07
  • Can you paste in the output from the console when the params are being submitted? – fatfrog May 16 '15 at 15:45
  • I've added the output from the Console as requested. Looks like there's only a save on the Employee model. – Dave C May 16 '15 at 16:12
  • Ok, so I've just realised that my inverse statements should have been plural in the Assignment model. Now the roles appear in the console, but still aren't saving to the DB. – Dave C May 16 '15 at 20:31

0 Answers0