Search code examples
ruby-on-railscontrollerupdate-attributes

Rails link_to update attribute from controller action


I want to be able to have a link that when pressed updates one attribute based up a controller action. How would I be able to do this? Do I have to create a separate update route? I am new at this so please bear with me.

controller

def completed
 @meeting = Meeting.find(params[:id])
 if @meeting.day_of_meeting == @meeting.days
  @meeting.update_attribute(:day_of_meeting, '1')
  redirect_to :back
 else
  @meeting.increment!
  redirect_to :back
 end
end

model

def increment!
  update_attribute(:day_of_meeting, day_of_meeting + 1)
end

view

<%= link_to meetings_completed_path(@meeting), remote: true do %>

routes

resources :meetings do
  get 'meetings/completed'
end

Solution

  • There are several issues with your code

    1. Since you are updating a record you need to include method: :patch in your link and also you need to modify the routes file to include appropriate route.

      In your routes file add

      #routes.rb
      resources :meetings do
        member do
          patch 'completed'
        end
      end
      

      In your view

      <%= link_to "Mark as completed", completed_meeting_path(@meeting), remote: true, method: :patch  %>
      
    2. Since you have a remote:true in your link so rails will try to render a javascript template and since you are not rendering a javascript template you will get a template missing error

      In your controller

      def completed
        @meeting = Meeting.find(params[:id])
        respond_to do |format|
          # if something ...
            # update meeting record and then render js template
            format.js {render :status => :ok} # it will render completed.js.erb inside 'app/views/meetings/' directory
          # else
            # something else
            format.js {render :action => "different_action"} # it will render different_action.js.erb inside 'app/views/meetings/' directory 
        end
      end 
      

    Now all you need to do is to write some basic javascript in the js templates to update the view.

    Note : If you don't want to render anything simply use format.js { render :nothing => true }. Also if you want to use redirect_to calls instead of rendering js template just remove remote: true form you link .