Search code examples
ruby-on-railsformsmethodsrails-routing

Incrementing model integer via custom method and form_for


I'm extremely new to Rails and so I apologize if this is a simple question. I am attempting to build a simple site that allows users to vote as whether or not they liked the lunch that day. Lunches are associated with providers (restaurants) and thus providers will have many different "lunches."

I know it is possible to auto increment by adding this to a method in the controller (discussed more here) and my current setup looks like this:

The view:

<%-# Show current like and dislike counts. -%>
<div> Likes: <%= @lunch.liked %> </div>
<div> Dislikes: <%= @lunch.disliked %> </div>


<div>
    <%= form_for :lunch url: lunch_path, method: :put do |f| %>
      <div><%= f.hidden_field :disliked %></div>
      <div><%= f.hidden_field :id %></div>
    <%= f.submit "Disike Lunch", class: "btn btn-large btn-primary" %>
    <% end %>
</div>

The controller:

  def downvote_lunch
    @lunch = Lunch.find(params[:id])
    @lunch.increment!(:disliked)
    redirect_to lunch_path
  end

Routes:

 resources :lunches

...

match '/dislike',      to: 'lunches#downvote_lunch',      via: 'get'

However, when I click on the "Dislike Button" it tells me that there is no view for "update" - I've defined update as an empty method in the controller, but I'm not sure why it's accessing update - all I'm looking for is to reload lunches/:id with the updated count for "disliked."

My question: How do I get the form to point to the custom "downvote_lunch" method, and have it redirect back to the lunches/:id after successfully incrementing the "dislikes" integer in the model?


Solution

  • For it you have to do

    In view

     <div>
       <%= form_for :lunch url: downvote_lunch_lunch_path(params[:id]), method: :put do |f| %>
        <div><%= f.hidden_field :disliked %></div>
        <div><%= f.hidden_field :id %></div>
       <%= f.submit "Disike Lunch", class: "btn btn-large btn-primary" %>
      <% end %>
    </div>
    

    In routes

     resources :lunches do
      member do
        put :downvote_lunch
      end
     end
    

    In controller

      def downvote_lunch
        @lunch = Lunch.find(params[:id])
        @lunch.increment!(:disliked)
        redirect_to @lunch
      end
    

    it will work as you want