Noob error: No route matches [POST] "/users/1/edit" - ruby-on-rails

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 %>

Related

Index view of Rails model printing string with all model data

I just finished Rails' Getting Started guide and everything works perfectly except for this mysterious entry that's being printed in the Index view as shown below. I've been trying to find the cause to no avail, neither have I found no suitable terms to Google this issue.
Index.html.erb
<h1>Index</h1>
<%= link_to 'New Client', new_client_path %>
<table>
<tr>
<th>Name</th>
<th>Issued On</th>
<th>Notes</th>
<th>Finished?</th>
<th>Payments</th>
</tr>
<%= #clients.each do |client| %>
<tr>
<td><%= client.name %></td>
<td><%= client.date %></td>
<td><%= client.note %></td>
<td><%= client.finished %></td>
<td><%= client.payment %></td>
<td><%= link_to 'Show', client_path(client) %></td>
<td><%= link_to 'Edit', edit_client_path(client) %></td>
<td><%= link_to 'Destroy', client_path(client),
method: :delete,
data: { confirm: 'This client will be permanentally deleted, do you want to continue?' } %></td>
</tr>
<% end %>
</table>
Clients Controller
class ClientsController < ApplicationController
def index
#clients = Client.all
end
def show
#client = Client.find(params[:id])
end
def new
#client = Client.new
end
def edit
#client = Client.find(params[:id])
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to #client
else
render 'new'
end
end
def update
#client = Client.find(params[:id])
if #client.update(client_params)
redirect_to #client
else
render 'edit'
end
end
def destroy
#client = Client.find(params[id])
#client.destroy
redirect_to clients_path
end
private
def client_params
params.require(:client).permit(:name, :date, :note, :finished, :payment)
end
end
Remove = from <%= #clients.each do |client| %>. It is outputting result of each which you don't need to print.
In ERB,
<%= %>
executes ruby code as well as outputs the result
For example: <%= client.name %>
<% %>
executes ruby code but doesn't output the result
For example: <% #clients.each do |client| %>....<% end %>

Rendering 'form' is giving me an ArgumentError

I am trying to create an activity feed, and trust me, it will take a while to create as I am new to ruby on rails. Sorry for a basic question.
However, I am trying to render '_form.html.erb' as I want the user to be able to create a 'story' and for it to be listed on the same page, like any activity feed. Could someone explain to me what the problem is?
My index.html.erb:
<p id="notice"><%= notice %></p>
<h1>This is a list of posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.email %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story) %></td>
<td><%= link_to 'Destroy', story, method: :delete, data: { confirm: 'Are you sure?'} %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'New Story', new_story_path %>
<%= render 'form' %>
_form.html.erb:
<%= form_for #story do |f| %>
<%= render 'shared/errors', object: #story %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: 'form-control', required: true, cols: 3 %>
</div>
<%= f.submit 'Create Story', class: 'btn btn-primary' %>
<% end %>
Story Controller:
class StoriesController < ApplicationController
before_action only: [:destroy, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = current_user.stories.build
end
def create
#story = current_user.stories.build(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
#story = Story.find(params[:id])
end
def update
#story = Story.find(params[:id])
if #story.update_attributes(params.require(:story).permit(:name, :description))
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
#story = Story.find(params[:id])
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
redirect_to root_path
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:name, :description)
end
end
My error in terminal:
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
1: <%= form_for #story do |f| %>
2: <%= render 'shared/errors', object: #story %>
3:
4: <div class="form-group">
You should add #store variable to index action.
def index
#stories = Story.order('created_at DESC')
#story = current_user.stories.build
end

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

NoMethodError in Admin::Posts#index

I am having problem with my post code please see this.
The error is saying
NoMethodError in Admin::Posts#index Showing
/home/muba/rblog/app/views/admin/posts/index.html.erb where line #2
raised:
undefined method `exists?' for nil:NilClass
post> index.html.erb is here:
<h2 class="page-header">Posts <%= link_to "Create New", new_admin_post_path, class:'btn btn-success pull-right' %></h2>
<% if #posts.exists? %>
<table class="table table-striped">
<tr>
<th>Post Title </th>
<th>Date Created</th>
<th>Post Category </th>
<th> Actions </th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.created_at.to_time.strftime('%B %e at %l:%M %p') %></td>
<td><%= post.category.name %></td>
<td><%= link_to "Edit", edit_admin_post_path(post), class:'btn btn-primary' %> <%= link_to "Delete", admin_posts_path(post), class:'btn btn-danger', method: :delete, data: {confirm: 'Are you sure'} %></td>
</tr>
<% end %>
</table>
<%= will_paginate #posts %>
<% else %>
<p> There are no posts </p>
<% end %>
And The Posts Controller is:
class PostsController < ApplicationController
def new
#page_title = 'Add Post'
#post = Post.new
end
def create
#post = post.new(post_params)
if #post.save
flash[:notice] = 'Post Created'
redirect_to admin_posts_path
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
flash[:notice] = 'Post Updated'
redirect_to admin_posts_path
else
render 'new'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
flash[:notice] = 'Post Removed'
end
def index
#posts = Post.all
end
private
def category_params
params.require(:post).permit(:title, :category_id, :user_id, :tags, :image, :body)
end
Please give me a solution :(
Check #post like this:-
<% if #posts.present? %>
<% end %>
May be this works:
<% unless #posts.nil? %>
As per the documentation, exists? generally used for comparison, takes argument to check whether exist or not.
You can also try this :
<% if !#posts.nil? %>
<%= your code... %>
<% end %>
This will also help your cause .

Need help with implementing Railscast 198 in Rails 3

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.

Resources