Search code examples
ruby-on-rails-4twitter-bootstrap-3strong-parametersx-editable

x-editable ActionController::ParameterMissing (param is missing or the value is empty: employee)


I am trying to get the x-editable gem, found here: Bootstrap-x-editable-rails GitHub. I have been searching for a solid 1-2 days and have not been able to resolve the issue, so I am posting it here.

In my attempt to integrate the x-editable functionality into my datatable, I have made it to the point where i can click on a table element and an edit box will pop-up. However, when I press enter to confirm the change i get this error in the console:

Started PUT "/employees/3" for 66.186.164.130 at 2015-03-18 16:15:59 +0000
Processing by EmployeesController#update as JSON
  Parameters: {"PUT"=>{"company_name"=>"New Compa"}, "id"=>"3"}
  Employee Load (33.9ms)  SELECT  "employees".* FROM "employees" WHERE "employees"."id" = $1 LIMIT 1  [["id", 3]]
Completed 400 Bad Request in 38ms

ActionController::ParameterMissing (param is missing or the value is empty: employee):
  app/controllers/employees_controller.rb:79:in `employee_params'
  app/controllers/employees_controller.rb:51:in `update'


  Rendered /usr/local/rvm/gems/ruby-2.1.4@rails4/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_source.erb (5.5ms)
  Rendered /usr/local/rvm/gems/ruby-2.1.4@rails4/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_trace.text.erb (1.1ms)
  Rendered /usr/local/rvm/gems/ruby-2.1.4@rails4/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_request_and_response.text.erb (0.9ms)
  Rendered /usr/local/rvm/gems/ruby-2.1.4@rails4/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/diagnostics.text.erb (109.0ms)

Here is the view:

          <table class="table table-striped table-bordered table-hover" id="sample_1">
                <thead>
                  <tr>
                    <th>Company name</th>
                    <th>Family</th>
                    <th>First name</th>
                    <th>Last name</th>
                    <th>Dob</th>
                    <th>Sub status</th>
                    <th>Gender</th>
                    <th>Uses tobacco</th>
                    <th>Tobacco cessation</th>
                    <th>Emp status</th>
                    <th>Coverage type</th>
                    <th>Currently enrolled</th>
                    <th>Current anthem</th>
                    <th>Current plan</th>
                    <th>Quote</th>
                    <th>Premium</th>
                  </tr>
                </thead>

                <tbody>
                  <% @employees.each do |employee| %>
                    <tr>
                     <td> 
                          <a href="#" data-xeditable="true" data-pk="<%= employee.id %>" data-model="PUT" data-type="text" data-name = "company_name" data-url="/employees/<%= employee.id %>" data-title="Enter title">

                             <%= employee.company_name %>
                          </a>
                     </td>

                      <td><%= employee.family_id %></td>
                      <td><%= employee.first_name %></td>
                      <td><%= employee.last_name %></td>
                      <td><%= employee.dob %></td>
                      <td><%= employee.sub_status %></td>
                      <td><%= employee.gender %></td>
                      <td><%= employee.uses_tobacco %></td>
                      <td><%= employee.tobacco_cessation %></td>
                      <td><%= employee.emp_status %></td>
                      <td><%= employee.coverage_type %></td>
                      <td><%= employee.currently_enrolled %></td>
                      <td><%= employee.current_anthem %></td>
                      <td><%= employee.current_plan_id %></td>
                      <td><%= employee.quote_id %></td>
                      <td><%= employee.premium %></td>

                    </tr>
                  <% end %>
                </tbody>
              </table>

Here is the view's controller:

class EmployeesController < ApplicationController
  before_action :set_employee, only: [:show, :edit, :update, :destroy]
  skip_before_filter :verify_authenticity_token
  def import
    Employee.import(params[:file])
    redirect_to employees_url, notice: "Census imported."
  end


  # GET /employees
  # GET /employees.json
  def index
    @employees = Employee.all
  end

  # GET /employees/1
  # GET /employees/1.json
  def show
  end

  # GET /employees/new
  def new
    @employee = Employee.new
  end

  # GET /employees/1/edit
  def edit
  end

  # POST /employees
  # POST /employees.json
  def create
    @employee = Employee.new(employee_params)

    respond_to do |format|
      if @employee.save
        format.html { redirect_to @employee, notice: 'Employee was successfully created.' }
        format.json { render :show, status: :created, location: @employee }
      else
        format.html { render :new }
        format.json { render json: @employee.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /employees/1
  # PATCH/PUT /employees/1.json
  def update
    respond_to do |format|
      if @employee.update(employee_params)
        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

  # DELETE /employees/1
  # DELETE /employees/1.json
  def destroy
    @employee.destroy
    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

    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def employee_params
      params.require(:employee).permit(:company_name, :family_id, :first_name, :last_name, :dob, :sub_status, :gender, :uses_tobacco, :tobacco_cessation, :emp_status, :coverage_type, :currently_enrolled, :current_anthem, :current_plan_id, :quote_id, :premium)
    end


end

I know the skip_before_filter :verify_authenticity_token snippet makes the application vulnerable and it won't be left long term, its only a band-aid for another issue I was having until i figure it out.

Employee routes:

import_employees POST   /employees/import(.:format)         employees#import
       employees GET    /employees(.:format)                employees#index
                 POST   /employees(.:format)                employees#create
    new_employee GET    /employees/new(.:format)            employees#new
   edit_employee GET    /employees/:id/edit(.:format)       employees#edit
        employee GET    /employees/:id(.:format)            employees#show
                 PATCH  /employees/:id(.:format)            employees#update
                 PUT    /employees/:id(.:format)            employees#update
                 DELETE /employees/:id(.:format)            employees#destroy

Please let me know if there is anything additional i can provide to help find a solution.


Solution

  • In your controller your strong parameter definition looks like this:

    def employee_params
      params.require(:employee).permit(:company_name, :family_id, :first_name, :last_name, :dob, :sub_status, :gender, :uses_tobacco, :tobacco_cessation, :emp_status, :coverage_type, :currently_enrolled, :current_anthem, :current_plan_id, :quote_id, :premium)
    end
    

    What this means is that it expects the submitted data to contain a key called employee, with its value being a hash containing any of those permitted attributes as keys.

    If you look at the actual data that is being submitted (in the log) you can see this format is not being followed:

    {"PUT"=>{"company_name"=>"New Compa"}, "id"=>"3"}
    

    I'm guessing this is because you have data-model="PUT" on the <a> element in your view. Try changing it to data-model="employee" instead.