0

I have in routes.rb

resources :reckoners do
  resources: shift_requirements
end

In my partial for a new shift_requirement I have -

<%= form_for ([@reckoner, ShiftRequirment.new]) do |f| %>

but that's calling the path 'shift_requirement_path' which is throwing an error, though the page it's throwing an error on will be along the lines of http://localhost:3000/reckoners/2/shift_requirements/new

My routes say

reckoner_shift_requirement GET    /reckoners/:reckoner_id/shift_requirements/:id(.:format)      shift_requirements#show

etc.

How do I fix the form?

reckoner.rb has_many :shift_requirements and shift_reqiurement.rb belongs_to :reckoner

shift_requirements_controller.rb -

class ShiftRequirementsController < ApplicationController
  before_action :set_shift_requirement, only: [:show, :edit, :update, :destroy]

  # GET /shift_requirements
  # GET /shift_requirements.json
  def index
    @shift_requirements = ShiftRequirement.where(reckoner_id: params[:reckoner_id])
    @shift_requirement = ShiftRequirement.new
  end

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

  # GET /shift_requirements/new
  def new
    @shift_requirement = ShiftRequirement.new
  end

  # GET /shift_requirements/1/edit
  def edit
  end

  def create
    @shift_requirement = ShiftRequirement.new(shift_requirement_params)
    zero_ise @shift_requirement
    totalise_FTEs @shift_requirement

    respond_to do |format|
      if @shift_requirement.save
        format.html { redirect_to shift_requirements_path(reckoner_id:@shift_requirement.reckoner_id), notice: 'Shift requirement was successfully created.' }
        format.json { render :show, status: :created, location: @shift_requirement }
      else
        format.html { render :new }
        format.json { render json: @shift_requirement.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    totalise_FTEs @shift_requirement
    respond_to do |format|  
      if @shift_requirement.update(shift_requirement_params)

        format.html { redirect_to shift_requirements_path(reckoner_id: @shift_requirement.reckoner_id), notice: 'Shift requirement was successfully updated.' }
        format.json { render :show, status: :ok, location: @shift_requirement }
      else
        format.html { render :edit }
        format.json { render json: @shift_requirement.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @shift_requirement.destroy
    respond_to do |format|
      format.html { redirect_to shift_requirements_url, notice: 'Shift requirement was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    def set_shift_requirement
      @shift_requirement = ShiftRequirement.find(params[:id])
    end

    def shift_requirement_params
      params.require(:shift_requirement).permit(:shift, :hours, :mon_count, :tue_count, :wed_count, :thu_count, :fri_count, :sat_count, :sun_count, :TotalFTE, :reckoner_id)
    end

    def zero_ise(shift)
      shift.mon_count ||= 0.0
      shift.tue_count ||= 0.0
      shift.wed_count ||= 0.0
      shift.thu_count ||= 0.0
      shift.fri_count ||= 0.0
      shift.sat_count ||= 0.0
      shift.sun_count ||= 0.0
    end

    def totalise_FTEs(shift)
      zero_ise shift
      shift.TotalFTE = (shift.mon_count + shift.tue_count + shift.wed_count + shift.thu_count + shift.fri_count + shift.sat_count + shift.sun_count)*shift.hours/Reckoner.find_by_id(shift.reckoner_id).weekly_hours
    end
end
dan
  • 1,030
  • 1
  • 9
  • 24

1 Answers1

2

Firstly, you will need to set the Reckoner for which there is a new shift_requirement. Here is how you can do it in your controller (Edited new and create action. Edited the index action to keep up with best practices :). Also added a before action and set_reckoner private method )

class ShiftRequirementsController < ApplicationController
  before_action :set_shift_requirement, only: [:show, :edit, :update, :destroy]
  before_action :set_reckoner

  # GET /shift_requirements
  # GET /shift_requirements.json
  def index
    @shift_requirements = @reckoner.shift_requirements.all
  end

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

  # GET /shift_requirements/new
  def new
    @shift_requirement = @reckoner.shift_requirements.new
  end

  # GET /shift_requirements/1/edit
  def edit
  end

  def create
    @shift_requirement = @reckoner.shift_requirements.new(shift_requirement_params)
    zero_ise @shift_requirement
    totalise_FTEs @shift_requirement

    respond_to do |format|
      if @shift_requirement.save
        format.html { redirect_to shift_requirements_path(reckoner_id:@shift_requirement.reckoner_id), notice: 'Shift requirement was successfully created.' }
        format.json { render :show, status: :created, location: @shift_requirement }
      else
        format.html { render :new }
        format.json { render json: @shift_requirement.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    totalise_FTEs @shift_requirement
    respond_to do |format|
      if @shift_requirement.update(shift_requirement_params)

        format.html { redirect_to shift_requirements_path(reckoner_id: @shift_requirement.reckoner_id), notice: 'Shift requirement was successfully updated.' }
        format.json { render :show, status: :ok, location: @shift_requirement }
      else
        format.html { render :edit }
        format.json { render json: @shift_requirement.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @shift_requirement.destroy
    respond_to do |format|
      format.html { redirect_to shift_requirements_url, notice: 'Shift requirement was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    def set_shift_requirement
      @shift_requirement = ShiftRequirement.find(params[:id])
    end

    def set_reckoner
      @reckoner = Reckoner.find(params[:reckoner_id])
    end

    def shift_requirement_params
      params.require(:shift_requirement).permit(:shift, :hours, :mon_count, :tue_count, :wed_count, :thu_count, :fri_count, :sat_count, :sun_count, :TotalFTE, :reckoner_id)
    end

    def zero_ise(shift)
      shift.mon_count ||= 0.0
      shift.tue_count ||= 0.0
      shift.wed_count ||= 0.0
      shift.thu_count ||= 0.0
      shift.fri_count ||= 0.0
      shift.sat_count ||= 0.0
      shift.sun_count ||= 0.0
    end

    def totalise_FTEs(shift)
      zero_ise shift
      shift.TotalFTE = (shift.mon_count + shift.tue_count + shift.wed_count + shift.thu_count + shift.fri_count + shift.sat_count + shift.sun_count)*shift.hours/Reckoner.find_by_id(shift.reckoner_id).weekly_hours
    end
end

Then in your form do this ():

<%= form_for ([@reckoner, @shift_requirement]) do |f| %>
Aaditi Jain
  • 6,969
  • 2
  • 24
  • 26
  • 1
    In new action, although new method would work but build is the method we use in has many associations, also instead of creating a new instance variable for shift_requirement you can simply use `@reckoner.shift_requirements.build` and in form you'll have to use a symbol `=form_for ([@reckoner, :shift_requirement]) do |f|`. If rails still doesn't make correct polymorphic path then you can specify the [`url option`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for) – Mandeep Oct 15 '14 at 05:45
  • Thanks Mandeep :). Just one thing, as far as I understand, with Rails 4, 'build' and 'new' are alias of each other. Both yield a new object of the child and set the parent_id for it. (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb) – Aaditi Jain Oct 15 '14 at 06:17
  • Hi thank you both for looking at this - however making the change that Aaditi has put in the answer, I get 'undefined method `shift_requirements' for nil:NilClass' - it's failing in the controller. – dan Oct 15 '14 at 07:20
  • 1
    Did you add the 'set_reckoner' method that is added in the private section and also `before_action : set_reckoner` at the start of your controller. If no, please add it and it should work. If you have already added it, then probably your params are missing :reckoner_id key. In that case please put up the view from where you are calling the new shift_requirement method – Aaditi Jain Oct 15 '14 at 07:28
  • @AaditiJain yeah i know they are alias, mentioned that in comment also that it would work just fine. I just prefer using [`build as it's documented`](http://guides.rubyonrails.org/association_basics.html#has-many-association-reference). Guess it's a matter of choices :). @RADan setting that before filter should fix it – Mandeep Oct 15 '14 at 07:49
  • Is that in the shift_requirements controller? Did it and got 'undefined method `set_reckoner' for #' – dan Oct 15 '14 at 08:00
  • You will also need to add the method `set_reckoner` in the controller. Its a private method.Check towards the end of the controller code, its already there. :) – Aaditi Jain Oct 15 '14 at 08:05