Reputation: 149
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
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.)
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
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
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