Need help with implementing Railscast 198 in Rails 3 - ruby-on-rails

I have been trying to implement Ryan Bates Railscast 198 into rails 3 for like 4 days... at least at night if you know what I mean. Anyway, here is the code I have right now:
User controller actions (Devise setup to show the different states of approved):
def index
if params[:approved] == "false"
#users = User.find_all_by_approved(false)
elsif
#users = User.find_all_by_approved(true)
else
#users = User.all
end
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to root_path flash[:notice] = "User was successfully updated." }
else
format.html { render :action => "edit" }
end
end
end
def edit_individual
#users = User.find(params[:user_ids])
end
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
flash[:notice] = "Users updated"
redirect_to users_url
else
render :action => "edit_individual"
end
end
end
My User#index
<h1> Users</h1>
<%= link_to "All Users", :action => "index" %> |
<%= link_to "Users awaiting approval", :action => "index", :approved => "false"%>
|
<%= link_to "Approved Users", :action => "index", :approved => "true" %>
<%= form_tag edit_individual_users_path, :method => :put do %>
<table>
<tr>
<th>Email Address</th>
<th>Approved</th>
<th></th>
</tr>
<% for user in #users %>
<tr>
<td> <%= user.email %></td>
<td><%= check_box_tag user.id %></td>
<td> <%= link_to "Edit", edit_user_path(user) %></td>
</tr>
<% end %>
<p><%= submit_tag "Edit Checked" %></p>
</table>
<% end %>
And the User#edit_individual
<%= form_tag update_individual_users_path, :method => :put do %>
<% for user in #users %>
<%= fields_for "users[]", user do |f| %>
<h2><%=h user.name %></h2>
<p><%= check_box_tag user.id %></p>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
routes.rb
devise_for :users
resources :users do
collection do
post :edit_individual
put :update_individual
end
end
end
So I handled the basic by googling: fields_for needs an "=" stuff like that. #index shows fine but if I check a checkbox and then hit the edit checked button I get the following error:
ActiveRecord::RecordNotFound in UsersController#update
Couldn't find User with id=edit_individual
Any ideas??? thanks so much

Please check your routes.rb and controller code, as it's quite a bit off from the code on Railscast 198's page: http://railscasts.com/episodes/198-edit-multiple-individually
It's best to just copy it in if you're new to rails and adjust for using users instead of products. Then go through it to try to understand what it does.

Related

Issue with form_tag in rails

I am using form_tag in my create.html.erb file. Under this form_tag there is a button. Now I wish that after clicking the button the page will be refreshed only ,I dont want to redirect anywhere . So what should I write in my form tag as path?
For session controller my view/sessions/create.html.erb file is:
<h4>Database contents here:</h4>
<table>
<tr>
<th>ID</th>
<th>AGE</th>
<th>NAME</th>
</tr>
<% #data.each do |data| %>
<tr>
<td><%= data.id %></td>
<td><%= data.age %></td>
<td><%= data.name %></td>
</tr>
<% end %>
</table>
<div>
<%= form_tag :method => :get do %>
<%= button_tag type: 'submit' do %>
<%= content_tag :div do%>
<h4>View Data </h4><h4><%= #num %></h4>
<% end %>
<% end %>
<% end %>
</div>
And my contollers/sessions_controller file is:
class SessionsController < ApplicationController
def new
end
def index
end
def create
user = User.authenticate(params[:email], params[:password])
#data=Information.all
#num=Information.count()
#tym=Time.now.getutc
if user
session[:user_id] = user.id
#redirect_to root_url, :notice => "Logged in!"
#this part is for showing the content of the information table
respond_to do |format|
format.html
format.xml { render xml: #data }
end
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged out!"
end
end
If you simply want to refresh your page then you do not need to do a form_tag, why not you redirect back to that page on button click
<%= button_to "Refresh", sessions_path, :method => :get %>

Adding a user's ID to a teacher from a form in rails

I have the following as a table in my HTML for having a student select a teacher
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th></th>
</tr>
</thead>
<tbody>
<% #teachers.each do |teacher| %>
<tr>
<td><%= teacher.name %> </td>
<td><%= teacher.email %> </td>
<td><%= teacher.phone %> </td>
<%= form_for teacher do |f| %>
<td><%= f.submit yield(:button_text), class: "btn btn-primary" %></td>
<%= f.hidden_field :user_id, value: #user.id %>
<% end %>
</tr>
<% end %>
</tbody>
</table>
But when I click the "Select" button (which is yielded from :button_text), it doesn't assign the student to the teacher. The controller code for the update action within teachers_controller is
def update
#teacher = Teacher.find(params[:id])
if params[:user_id]
#user = User.find(params[:user_id])
if #teacher.users << #user
flash[:success] = "Profile updated"
redirect_to #user
else
render 'select'
end
else
if #teacher.update_attributes(teacher_params)
flash[:success] = "Teacher updated"
redirect_to #teacher
else
render 'edit'
end
end
end
I'm trying to make it so that if the hidden_field of the user's ID is present then the only attribute of teacher that is updated is their students, otherwise their attributes (shown in the table) are updated. What am I doing wrong?
What am I doing wrong?
You'll not be passing params[:user_id] from your form; it will be params[:teacher][:user_id]
def update
#teacher = Teacher.find(params[:id])
if params[:teacher][:user_id]
#user = User.find params[:teacher][:user_id]
if #teacher.users << #user
--
You'll be better putting this functionality into a separate method, as to not butcher your update action:
#config/routes.rb
resources :teachers do
match :users, via: [:patch, :delete] #-> url.com/teachers/:teacher_id/users
end
#app/views/teachers/index.html.erb
<% #teachers.each do |teacher| %>
<%= button_to "Add", teacher_users_path(teacher), method: :patch, params: { user_id: #user.id } %>
<% end %>
#app/controllers/teachers_controller.rb
class TeachersController < ApplicationController
def users
#teacher = Teacher.find params[:teacher_id]
if params[:user_id]
#user = User.find params[:user_id]
#teacher.users << #user if request.patch?
#teacher.users.delete #user if request.delete?
end
redirect_to teachers_path
end
end
ah, you only need one HTML form in your view. you can use a collection select, like so:
...
<tbody>
<tr>
<td>
<%= form_for teacher do |f| %>
<%= collection_select(:student, :teacher_id, Teacher.all, :id, "#{teacher.name} #{teacher.email} #{teacher.phone}", prompt: true)
</td>
<td>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
</td>
</tr>
<% end %>
</tbody>
...
...then you'll get a params[:student][:teacher_id] posted to your controller. You might need to futz with the collection_select (or just use a regular select) a bit depending on what your models are like. Not totally sure about the hidden field or the if/else in your controller. However, using form_for and collection_select correctly should get you a long ways. Be sure to RTFM: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

Noob error: No route matches [POST] "/users/1/edit"

Sooo... I'm a noob and I haven't found an answer that gets me through this yet. I've been struggling through this and I know it's a simple question, but I'm just not experienced enough to know how to solve this one.
I'm receiving the error:
No route matches [POST] "/users/1/edit"
Here are the routes for the issue: (simple, I know)
Rails.application.routes.draw do
resources :users
Here is the Controller:
class UsersController < ApplicationController
def new
#user=User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to #user
else
render 'edit'
end
end
def delete
#user = User.find(params[:id])
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to(:action => 'index')
end
def show
#user = User.find(params[:id])
end
def index
#users=User.all.order("created_at ASC")
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :username, :admin, :email, :birthday)
end
end
And, here is the view:
<DOCTYPE!! HTML>
<html>
<h1>Edit User</h1>
<%= #user.username %>
<%= link_to "Back to User Index", users_path %>
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
<table summary="Edit user form fields">
<tr>
<th>First Name</th>
<td><%= f.text_field(:first_name) %></td>
</tr>
<tr>
<th>Last Name</th>
<td><%= f.text_field(:last_name) %></td>
</tr>
<tr>
<th>Username</th>
<td><%= f.text_field(:username) %></td>
</tr>
<tr>
<th>Password</th>
<td><%= f.text_field(:password) %></td>
</tr>
<tr>
<th>Birthday</th>
<td><%= f.date_field(:birthday) %></td>
</tr>
<tr>
<th>Is Admin?</th>
<td><%= f.text_field(:admin) %></td>
</tr>
</table>
<%= submit_tag("Update User") %>
<% end %>
</html>
I know this is probably not worth serious time for you to answer, but I haven't been able to figure it out. Please help, and let me know if you need more info. Thanks again in advance!
Change
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
to
<%= form_for(#user) do |f| %>
In this instance, you don't need to specify the action to use. The default conventions in Rails will take care of this for you.
As you already got an answer, so as a suggestion you can also add method parameter as given here
<%= form_for #user, url: edit_user_path(#user), method: :get do |f| %>
...
<% end %>

Multiple submit buttons rails

I am trying to make multiple submit buttons for a form, but I keep getting this error:
Couldn't find User with id=edit_individual
Found in:
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
My controller page:
def edit_individual
if User.find_by_id (params[:user_ids])
if params[:Delete_multiple]
#users = User.find(params[:user_ids])
#users.each do |user|
user.destroy
end
redirect_to :back, notice: 'All selected users were successfuly deleted'
else
#users = User.find(params[:user_ids])
end
else
redirect_to :back, alert: 'No users were selected for editing'
end
end
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
redirect_to :back, notice: "Users updated"
else
render :action => "edit_individual"
end
end
My index page:
<%= form_tag edit_individual_users_path do %>
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th><%= sort_link #q, :firstName, "First name" %></th>
<th><%= sort_link #q, :lastName, "Last name" %></th>
<th><%= sort_link #q, :registrationNumber, "Registration number" %></th>
<th><%= sort_link #q, :email, "Email" %></th>
<th></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<% if (user.archive == false) %>
<tr>
<td><%= check_box_tag "user_ids[]", user.id %></td>
<td><%= user.firstName %></td>
<td><%= user.lastName %></td>
<td><%= user.registrationNumber %></td>
<td><%= user.email %></td>
<td><%= link_to 'View', user, class: 'btn btn-info btn-mini', title: 'View users\'s information' %></td>
<td><%= link_to 'Edit', edit_user_path(user), class: 'btn btn-warning btn-mini', title: 'Edit users\'s information', method: 'get' %></td>
<td><%= link_to 'Delete', user, class: 'btn btn-danger btn-mini', title: 'Delete user', method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
<p><%= select_tag :field, options_for_select([["All Fields", ""], ["First name", "firstName"], ["Last name", "price"], ["Registration number", "registrationNumber"], ["Email", "email"]]) %></p>
<p><%= submit_tag "Edit checked", name: 'Edit_multiple' %></p>
<p><%= submit_tag "Delete checked", name: 'Delete_multiple', data: { confirm: 'Are you sure you want to delete multiple users?' } %></p>
<% end %>
The edit_individual page:
<% form_tag update_individual_users_path, :method => :put do %>
<% for product in #products %>
<% fields_for "users[]", users do |f| %>
<h2><%=h user.name %></h2>
<%= render :partial "fields", :locals => { :f => f, :user => user } %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
The routes file:
resources :users do
get 'archive', on: :collection
post 'edit_individual', on: :collection
put 'update_individual', on: :collection
end
The delete part works fine. Also, the edit part actually edits the field, but displays that error (so it does not redirect back to the index page which makes it look bad).
Can anyone help me fix this? Spent a lot hours to have both edit and delete so it would be pretty bad if I had to delete the edit part.
EDIT 1: Also, If I am editing for example 3 users and click the submit button allowing only 2/3 to pass (due to validation), there is no error (I just get redirected back to edit_individual.html to finish the last user) and then if I have click submit again and everything passes, I get an error.
I have actually managed to find what was wrong.
The problem was with:
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
redirect_to :back, notice: "Users updated"
else
render :action => "edit_individual"
end
end
Instead of:
redirect_to :back
It should be:
redirect_to users_path
Or any other fixed path I suppose. Is there a way to keep "redirect_to :back", or do I have to create new methods for other views (within the same controller) that will use this?
it should not be run because you has not any params[:id]
if you user before_filter then
before_filter: set_user except: [:update_individual, :edit_individual]
def set_user
#user = User.find(params[:id])
end
and where you call update_individual in edit_individual

Rails withdraw_event_path 'undefined local method'

I found a great solution to a problem of mine here
I've built it into my own project, but I can't seem to call the withdraw event.
show.html.erb
<p><strong>Attendees: </strong>
<ul>
<% for attendee in #event.users %>
<% if attendee.id == current_user.id %>
<li><strong><%= attendee.name %></strong>
<%= link_to 'Withdraw From Event', withdraw_event_path(#event.id), :method => :post, :class => 'btn btn-danger' %>
</li>
<% else %>
<li><%= attendee.username %></li>
<% end %>
<% end %>
</ul>
</p>
<p>
<%= link_to 'Attend Event', attend_event_path(#event.id), :method => :post %>
</p>
event_controller.rb
def attend
#event = Event.find(params[:id])
current_user.events << #event
redirect_to #event, notice: 'You are now attending this event'
end
def withdraw
event = Event.find(params[:id])
attendee = Attendee.find_by_user_id_and_event_id(current_user.id, event.id)
if attendee.blank?
redirect_to event
end
attendee.delete
redirect_to event, notice: 'You are no longer attending this event.'
end
when I call event->show I get this error
undefined local variable or method `withdraw_event_path' for #<#<Class:0x007fd5d575a910>:0x007fd5d22a72e0>
Any ideas why the path isn't working? I'm new to rails
THanks
you need to add withdraw to your routes, that will create the method withdraw_event_path
resources :events do
member do
post 'withdraw'
end
end

Resources