D Kucher
D Kucher

Reputation: 149

Updating a record with rails 4

I'm trying to update a record with an admin user with a "validate" button that changes the record's status from pending to confirmed. I've created a form, and the route to do so, however the controller is giving me trouble, I'm not sure what to code for it to update the specific record i click validate for.

Hours controller

def index
    @allhours = HourLog.where(status:'Pending')
  end
def update
    @hour = HourLog.where(status:'Pending')
    @hour.update(@hour.id, :status)
  end

Hours/index.html.erb

<td><%=form_for(:hour_log, method: :put) do |f|%>
    <%= f.hidden_field :status, :value => 'Confirmed' %>
    <%= f.submit 'Validate'%>
    <%end%>
</td>

Any help would be fantastic, thanks!

error: NoMethodError in HoursController#update undefined method `id' for #

I know something is wrond with the (@hour.id) section of the controller in the update def, but I don't know what to replace it with

edit: rake routes

         Prefix Verb   URI Pattern                Controller#Action
           root GET    /                          welcome#index
         signup GET    /signup(.:format)          users#new
          users GET    /users(.:format)           users#index
                POST   /users(.:format)           users#create
       new_user GET    /users/new(.:format)       users#new
      edit_user GET    /users/:id/edit(.:format)  users#edit
           user GET    /users/:id(.:format)       users#show
                PATCH  /users/:id(.:format)       users#update
                PUT    /users/:id(.:format)       users#update
                DELETE /users/:id(.:format)       users#destroy
                GET    /users(.:format)           users#index
                PUT    /users(.:format)           users#update
          login GET    /login(.:format)           sessions#new
                POST   /login(.:format)           sessions#create
         logout DELETE /logout(.:format)          sessions#destroy
      dashboard GET    /dashboard(.:format)       hours#new
dashboard_hours GET    /dashboard/hours(.:format) hours#index
          hours PUT    /hours(.:format)           hours#update
                GET    /hours(.:format)           hours#index
                POST   /hours(.:format)           hours#create
       new_hour GET    /hours/new(.:format)       hours#new
      edit_hour GET    /hours/:id/edit(.:format)  hours#edit
           hour GET    /hours/:id(.:format)       hours#show
                PATCH  /hours/:id(.:format)       hours#update
                PUT    /hours/:id(.:format)       hours#update
                DELETE /hours/:id(.:format)       hours#destroy

hours Controller

class HoursController < ApplicationController
  before_action :require_user
  before_action :require_admin, only: [:index]
  def index
    @allhours = HourLog.where(status:'pending')
  end
  def new
    @hour = current_user.hour_logs.new
    @entry = current_user.hour_logs.all
  end
  def edit
    flash[:warning] =  "Hash: #{params}"
  end

  def create
    @hour = HourLog.new(hour_params)
    @hour.user_id = current_user.id if current_user
    @hour.status = 'pending'
    if @hour.save
      redirect_to '/dashboard'
    end
  end
  private
  def hour_params
    params.require(:hour_log).permit(:assignment, :hours, :supervisor, :date)
  end
  def update_hour_params
    params.require(:hour_log).permit(:status)
  end
end

HourLog method

class HourLog < ActiveRecord::Base
  belongs_to :user
end

Upvotes: 2

Views: 561

Answers (3)

Elvn
Elvn

Reputation: 3057

I see this has an answer accepted, but I'd like to propose an alternative solution for anyone who may come along and find this question. Assumptions: The base page is an index with all pending items and the click is a simple state change. (A state toggle could be easily added to this solution.)

(I'm using the naming from the question.)

Using link_to as a message

A state change from 'Pending' to 'Confirmed' for a flag could be implemented by using the link_to to trigger the controller action to update this flag. Hash params may be passed via a link_to enabling simplified logic in the controller.

VIEW: Index.html.erb

<% @allhours.each do |hour| %>
  <ul>
    <li><%= hour.textdescriptionvar %> is an item pending approval. 
        <%= link_to(" Click to approve", edit_hour_path(hour, :status => "Confirmed"))
    </li>
  </ul>

<% end %>

CONTROLLER: HourLogsController

       def edit
            flash[:info] =  "Hash: #{params}"
            @hour = HourLog.find(params[:id])
        end

        def update
            @hour = HourLog.find(params[:id])
            @hour.update_attributes(hours_params)
            if  @hour.save
               redirect_to @hour, :notice => "Successfully changed stat."
            else
                render 'index' # Any action here, index for example
            end
          end
    private

        def hours_params
          params.require(:hour_log).permit(:status)           
        end

I would recommend a data: confirm message be added to the link_to,but I wanted to mimic the poster's situation as posted.

Rails spec for link_to here.

Upvotes: 1

Andrew
Andrew

Reputation: 552

@hour = HourLog.where(status:'Pending') will return an ActiveRecord Relation, not a single record.

Try this:

@hour = HourLog.find_by(status: 'pending')
@hour.update_attribute :status, params[:hour_log][:status]

This method finds the first record with status ="pending" and updates that instead of the specific record.

Upvotes: 1

daslicious
daslicious

Reputation: 1534

You're going to want @hour.update params[:hour_log] instead because update_attribute doesn't run validations. and keep data in your database lowercase unless it's something written by a user. this link is useful http://www.davidverhasselt.com/set-attributes-in-activerecord/

Upvotes: 0

Related Questions