0

I have a model of goals with a number of attributes.

Once a goal is complete, it's marked as complete on a button press and then redirected to a new form which can add additional attributes to the goal model.

To me it made sense to store them on the goal model, as they are only ever linked to the goal, however, I can't get it to work correctly as I always get param is missing or the value is empty: goal.

Goal params are used as the standard CRUD params.

The goal_review_params are used once the goal is complete.

Is this possible to do outside of the 'update' action?

Controller:

class GoalsController < ApplicationController
  before_action :authenticate_user!, except: [:index, :show, :completedgoals]
  before_action :set_goal, only: [:show, :edit, :update, :destroy, :mark_completed, :goal_completed ]

 def goal_completed
    @authorize
    if @goal.update(goal_review_params)
        format.html { redirect_to @goal, notice: 'Goal review was successfully updated.' }
        format.json { render :show, status: :ok, location: @goal }
      else
        format.html { redirect_to goal_completed_goal_path(@goal) }
        format.json { render json: @goal.errors, status: :unprocessable_entity }
      end
  end



private
    def set_goal
      @goal = Goal.find(params[:id])
    end

#category_ids:[] needs to be added back to goal_params when they're added back in
    def goal_params
      params.require(:goal).permit(:goalname, :goaldesc, :goalhow, :goalwhy, :goalreward, :goalduedate, :goalstatus )
    end

    def goal_review_params
      params.require(:goal).permit(:goaldifficult, :goallearned, :goalnext)
    end

View:

 <%= form_for (@goal) do |form| %>
<div class="col-md-12 goalform">
    <%= form.label :goaldifficult, value: "Name your Goal" %><br>
    <%= form.text_field :goaldifficult, :rows => 2, style: 'width:80%;', 
    placeholder: "...'" %>
</div>

<div class="col-md-12 goalform">
    <%= form.label :goallearned, value: "Name your Goal" %><br>
    <%= form.text_field :goallearned, :rows => 2, style: 'width:80%;', 
    placeholder: "...'" %>
</div>

<div class="col-md-12 goalform">
    <%= form.label :goalnext, value: "Name your Goal" %><br>
    <%= form.text_field :goalnext, :rows => 2, style: 'width:80%;', 
    placeholder: "...'" %>
</div>

<div class="col-md-12 goalform">
    <%= form.submit class:"btn btn-primary" %>
</div>

Routes:

 resources :goals do
    ...
    member do
      get 'goal_completed', to: 'goals#goal_completed', as: 'goal_completed'
Olliedee
  • 79
  • 2
  • 10
  • 1
    Can you dump the console log (with `params`) after performing `create` and `update` action you mentioned about? – Kartikey Tanna May 30 '18 at 18:02
  • This sounds like an issue with StrongParameters and whatever your form is posting. Can you provide your full Rails log for the GoalsController#goals_completed action please? – danielricecodes May 30 '18 at 19:48

2 Answers2

0

You're still hitting the update method.

To hit a different method, follow form_for but to post to a different action

form_for @goal, :url => url_for(:controller => 'goal', :action => 'goal_completed')

Mark
  • 6,112
  • 4
  • 21
  • 46
  • might want to add `method: :get` given the routes posted or recommend a routing verb change – engineersmnky May 30 '18 at 18:52
  • Thanks @Mark. I've changed it to the below: `<%= form_for @goal, :url => url_for(:controller => 'goal', :action => 'goal_completed') do |form| %>` but still getting the same error. – Olliedee May 30 '18 at 19:03
0

You have the param is missing or the value is empty: goal error because your goal_review_params are indeed missing.

When you redirect your created/updated goal to the "goal_completed" view form, you're doing a "get" request. And as you defined it in your routes, the request is going to read the named method inside the controller and stop at this line:

if @goal.update(goal_review_params)

at this point of the request all the goal_review_params are missing because you have a GET like this:

Started GET "/goals/4/goal_completed" for ...
Processing by GoalsController#goal_completed as HTML
Parameters: {"id"=>"4"}

To achieve what you want you can create two custom routes, one for "GET" one for "PATCH", or if you really want only one action, handle multiple requests on it like that:

resources :goals do
  member do
    get 'goal_completed'  #<== to get the view form
    patch 'goal_completed' #<== to handle the update fields
  end
end

in your controller:

def goal_completed
  if request.patch?
    respond_to do |format|
      if @goal.update(goal_review_params)
        format.html { redirect_to @goal, notice: 'Goal review was successfully updated.' }
        format.json { render :show, status: :ok, location: @goal }
      else
        format.html { redirect_to goal_completed_goal_path(@goal) }
        format.json { render json: @goal.errors, status: :unprocessable_entity }
      end
    end
  end
end

and in your view form specify the custom path of your submit to prevent the basic "update" action:

<%= form_for @goal, url: goal_completed_goal_path(@goal) do |form| %>
  # the form
<% end %>
Sovalina
  • 5,410
  • 4
  • 22
  • 39