I'm working through a small exercise while learning Rails 4, but running into a routing error while trying to update an object. I keep getting an error message: No route matches [POST] "/movies/1/edit" but can't see where my code is not correct:
my movies_controller.rb
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
def show
#movie = Movie.find(params[:id])
end
def new
#movie = Movie.new
end
def create
#movie = Movie.create(movie_params)
if #movie.save
redirect_to "/movies/#{#movie.id}", :notice => "Your movie was saved!"
else
render "new"
end
end
def edit
#movie = Movie.find(params[:id])
end
def update
#movie = Movie.find(params[:id])
if #movie.update_attributes(params[:movie])
redirect_to "/movies"
else
render "edit"
end
end
def destroy
end
private
def movie_params
params.require(:movie).permit(:name, :genre, :year)
end
end
Here's my edit.html.erb
<h1>Now Editing:</h1>
<h3><%= #movie.name %></h3>
<%= form_for #movie.name do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<br>
<%= f.label :genre %>
<%= f.text_field :genre %>
<br>
<%= f.label :year %>
<%= f.number_field :year %>
<br>
<%= f.submit "Update" %>
and the routes.rb file:
MovieApp::Application.routes.draw do
get "movies" => "movies#index"
post "movies" => "movies#create"
get "movies/new" => "movies#new"
get "movies/:id" => "movies#show"
get "movies/:id/edit" => "movies#edit"
put "movies/:id" => "movies#update"
end
last, here's the output from running rake routes:
Prefix Verb URI Pattern Controller#Action
movies GET /movies(.:format) movies#index
POST /movies(.:format) movies#create
movies_new GET /movies/new(.:format) movies#new
GET /movies/:id(.:format) movies#show
GET /movies/:id/edit(.:format) movies#edit
PUT /movies/:id(.:format) movies#update
form_for #movie.name should be form_for #movie. I can't tell what's going on, but I suspect this is somehow giving you a <form action="">.
Your error message shows that you are sending a post request to the edit url.
No route matches [POST] "/movies/1/edit"
Whereas in the route you have specified a get request.
get "movies/:id/edit" => "movies#edit"
I believe that is somehow causing the problem and so you could change the request to post.
post "movies/:id/edit" => "movies#edit"
in index file if you are using
button_to 'Edit', edit_movie_path(movie)
change it to
link_to 'Edit', edit_movie_path(movie)
because button send it as POST but the link will send it as GET.
Related
I am seeing the following error while trying to access the new page of my new model in rails 6.1 after I upgraded rails to version 6.1 from 5.2 and ruby to 2.7 from 2.5 respectively.
No route matches {:action=>"show", :controller=>"friends", :format=>nil, :id=>#<Friend id: nil, first_name: nil, last_name: nil, created_at: nil, updated_at: nil>}, possible unmatched constraints: [:id]
here is my friends model
class Friend < ApplicationRecord
end
here is the friends controller
class FriendsController < ApplicationController
before_action :set_friend, only: [:show, :edit, :update, :destroy]
# GET /friends
def index
#friends = Friend.all
end
# GET /friends/1
def show
end
# GET /friends/new
def new
#friend = Friend.create
end
# GET /friends/1/edit
def edit
end
# POST /friends
def create
#friend = Friend.new(friend_params)
if #friend.save
redirect_to #friend, notice: 'Friend was successfully created.'
else
render :new
end
end
# PATCH/PUT /friends/1
def update
if #friend.update(friend_params)
redirect_to #friend, notice: 'Friend was successfully updated.'
else
render :edit
end
end
# DELETE /friends/1
def destroy
#friend.destroy
redirect_to friends_url, notice: 'Friend was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_friend
#friend = Friend.find(params[:id])
end
# Only allow a list of trusted parameters through.
def friend_params
params.require(:friend).permit(:first_name, :last_name)
end
end
here is the new friends view which is throwing the error
<h1>New Friend</h1>
<%= render 'form', friend: #friend %>
<%= link_to 'Back', friends_path %>
and here is the _form which the view is referring to
<%= form_with(model: friend) do |form| %>
<% if friend.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(friend.errors.count, "error") %> prohibited this friend from being saved:</h2>
<ul>
<% friend.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :first_name %>
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :last_name %>
<%= form.text_field :last_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
The /friends/new is calling show for some reason and since the show needs an :id, the call fails with the error. This might be happening die to my recent upgrades of rails and ruby
this is my routes file
RailsRoot::Application.routes.draw do
resources :friends
root :to => "accounts#index"
resources :accounts
end
here is what I see when I run rails routes
Prefix Verb URI Pattern Controller#Action
friends GET /friends(.:format) friends#index
POST /friends(.:format) friends#create
new_friend GET /friends/new(.:format) friends#new
edit_friend GET /friends/:id/edit(.:format) friends#edit
friend GET /friends/:id(.:format) friends#show
PATCH /friends/:id(.:format) friends#update
PUT /friends/:id(.:format) friends#update
DELETE /friends/:id(.:format) friends#destroy
root GET / accounts#index
accounts GET /accounts(.:format) accounts#index
POST /accounts(.:format) accounts#create
new_account GET /accounts/new(.:format) accounts#new
edit_account GET /accounts/:id/edit(.:format) accounts#edit
account GET /accounts/:id(.:format) accounts#show
PATCH /accounts/:id(.:format) accounts#update
PUT /accounts/:id(.:format) accounts#update
DELETE /accounts/:id(.:format) accounts#destroy
The problem with the new view is occurring in all of my models and views not just the friends controller (other controller is accounts).
Here is the link to the full stack trace of the error : https://pastecode.io/s/6g8itf96
trying to open my model's new view and expecting an empty form where I can fill in the fields and save . I suspect the /friends/new is calling the show without the :id being the reason of the problem. This was probably not happening before the I upgraded rails to 6.1
I think the main problem is in the #new method in the controller because you are creating a new friend by saving it in the DB with the .create method. Instead of creating an empty object for the form
Thy to change it to
# GET /friends/new
def new
#friend = Friend.new
end
I'm working on a ROR blog and have encountered some issues along the way. I'm currently learning Rails and just feel completely lost with connecting all the pieces. I've been working on my comments section for days and was finally able to create comments on posts, but I can't edit or delete them. I also referenced the SO questions below but am still running into problems.
Add Comment to User and Post models (Ruby on Rails)
Here's my layout:
Comment model params:
body \ user_id \ post_id
Model associations:
user.rb
has_many :posts
has_many :comments
post.rb
belongs_to :user
has_many :comments
comment.rb
belongs_to :user
belongs_to :post
routes.rb:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get '/' => 'users#index'
get '/posts' => 'posts#index'
post '/posts/create' => 'posts#new'
post '/posts/edit' => 'posts#edit'
get '/signin' => 'sessions#new', as: :new_session
post '/create-session' => 'sessions#create', as: :create_session
get 'signout' => 'sessions#destroy', as: :destroy_session
resources :users
resources :posts
resources :comments
end
comments controller:
class CommentsController < ApplicationController
def index
#comment = Comment.all
end
def new
user = session[:user_id]
#comment = Comment.new(post_id: params[:post_id])
#post = Post.find(params[:post_id])
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = session[:user_id]
#postid = params[:id]
if #comment.save
flash[:notice] = "comment created."
redirect_to '/posts'
else
flash[:error] = "Error creating comment."
redirect_to '/posts'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#comment = Comment.find_by_id(params[:id])
#comment.update(comment_params)
flash[:notice] = "Comment updated."
redirect_to '/posts'
end
def destroy
#comment = Comment.find(params[:comment_id])
#comment.destroy
redirect_to '/posts'
end
private
def comment_params
params.require(:comment).permit(:body, :user_id, :post_id)
end
end
Posts show.html.erb page in views/posts folder:
<%# show all posts %>
<div id="single-post">
<h1>User - <%= #post.user.username %></h1>
<h2>Post - <%= #post.body %> </h2>
<%= link_to("Edit Post", edit_post_path(#post)) %>
</br>
<%= link_to("Delete Post", #post, method: 'delete') %>
</br>
<%= link_to("Add Comment", new_comment_path(post_id: #post.id)) %>
<%#<%= link_to("Edit Comment", edit_comment_path(post_id: #post.id, comment_id: #comment.id))%>
</div>
<h3><% #post.comments.reverse.each do |c| %> </h3>
<div id="single-comment">
<h4>Comment</h4>
<h5>From - <%= c.user.username %></h5>
<h6><%= c.body %> </h6>
</br>
<%= link_to("Edit Comment", edit_comment_path(#post.id)) %>
</br>
<%= link_to("Delete Comment", comment_path(#post.id), method: :delete) %>
</div>
<% end %>
</div>
new.html.erb form in views/comments folder
<div id="comment-form">
<%= form_for #comment do |f| %>
<%= f.label :body %>
<%= f.text_area :body, class: "text-area" %>
<%= f.hidden_field :post_id %>
<%= f.submit %>
<% end %>
</div>
Again I can add comments to posts. When I hover over the edit tag on the comment I'm seeing this: localhost:3000/comments/72/edit
I see this error when I click on edit
When I hover over the delete button I see this: localhost:3000/comments/72
I see this error when I click on delete
I'm at the point where I'm completely lost and feel I have tried everything possible but nothing seems to work. Please help! Here's the GitHub repo as well: https://github.com/angelr1076/rails-blog
The First argument in form cannot contain nil or be empty is telling you that #comment in <%= form_for #comment do |f| %> is nil. This is because in the edit action of your CommentsController you are setting #post instead of #comment.
Change this to be:
def edit
#comment = Comment.find(params[:id])
end
For deleting a comment, the Couldn't find Comment without an ID is telling you that the value you're passing to find is nil. This is because you're trying to use params[:comment_id] instead of params[:id]. Change the destroy action to:
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to '/posts'
end
Update:
Also as per your code, you should change edit and delete links to below
<%= link_to("Edit Comment", edit_comment_path(c)) %>
<%= link_to("Delete Comment", comment_path(c), method: :delete)
You are passing #post.id which is an id of post. Instead you should pass id of the comment using the block variable from your comments.each, noticing that the .id isn't needed here because it can be inferred by Rails.
Cities#new controller shows error involving cities_path, but I don't have it in any file nor in CitiesController. I checked all files, tried to restart the server but still nothing.
undefined method `cities_path' for #<#<Class:0x007f9e4c1cb348>:0x00000003836140>
Did you mean? city_path
CitiesController
class CitiesController < ApplicationController
def index
#cities = City.all
end
def show
find_city
end
def new
#city = City.new
end
def edit
find_city
end
def update
find_city
if #city.save
redirect_to city_path(#city)
else
render "edit"
end
end
def create
#city = City.new(city_params)
if #city.save
redirect_to index_path
else
render "new"
end
end
private
def find_city
#city = City.find(params[:id])
end
def city_params
params.require(:city).permit(:name, :icon_url)
end
end
Routes
get "/cities/new" => "cities#new", as: "new_city"
post "/index" => "cities#create"
get "/cities/:id" => "cities#show", as: "city"
get "/cities/:id/edit" => "cities#edit", as: "edit_city"
patch "/city/:id" => "cities#update"
Form (error is raised on first line)
<%= form_for #city do |f| %>
<% if #city.errors.any? %>
<div class="errors">
<ul>
<% city.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label "Name:" %>
<%= f.text_field :name, class: "form-control" %>
<%= f.label "Icon:" %>
<%= f.text_field :icon_url, class: "form-control" %>
<%= f.submit "Pošalji" %>
<% end %>
When you use form_for #city, and #city is a new record, form_for will try to find a cities_path to POST the new attributes back to.
You should be using resources :cities in your routes file to automatically define the routes and their names. If you want to define a limited set of routes, you can use :only or :except:
resources :cities, only: %i(new create show edit update)
If you don't use resources, you either need to explicitly specify a path for your form_for call, or you need to provide a route named cities_path manually:
post "/index" => "cities#create", as: :cities
Note that index routes don't typically actually contain the word index, you should really just be posting to /cities, not /index.
post "/cities" => "cities#create", as: :cities
I posted a question before but my pictures weren't posting so now I am just gonna copy and paste the code. I am trying to make a blogging web app is Rails and I am in the "edit" phase and basically I am getting a no method error.
here is my controller code:
class PostsController < ApplicationController
def index
#post = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path(#post)
end
def edit
#post = Post.find(params[:id])
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
and here is my edit.html.erb view page
This is the edit page for
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %><br />
<%= f.label :body %>:
<%= f.text_field :body %><br />
I am guessing the problem is somewhere in there
here is my routes.rb:
Rails.application.routes.draw do
get "pages/about" => "pages#about"
get "pages/contact" => "pages#contact"
get "/posts" => "posts#index"
post "/posts" => "posts#create"
get "post/:id" => "posts#show", as: :show
get "/posts/new" => "posts#new"
get "post/:id/edit" => "posts#edit", as: :edit_post
end
Please help this is really frustrating :/
You need to add a line in your route file such as:
resources :posts
Also add a update method in your posts_controller:
def update
#post = Post.find(params[:id])
#post.update(post_params)
redirect_to #post
end
I hope this helps you !
When you use form_for like
<%= form_for #post do |f| %>
It's a shorthand for something that looks like this
<%= form_for #post, as: :post, url: post_path(#post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
So form_for expects that you have defined post_path helper, which you get when you use resources to define your routes, like this
resources :photos
Since you haven't defined your routes like that you don't have path helper that form_for expects and you get an error.
here is the error message:
NoMethodError in Posts#edit
Showing /Users/Hisham/Desktop/Rails_projects/myblog/app/views/posts/edit.html.erb where line #6 raised:
undefined method `post_path' for #<#:0x007fcdc84fd7b8>
Did you mean? posts_path
posts_new_path
font_path
Extracted source (around line #6):
4
5
6
7
8
9
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %><br />
Rails.root: /Users/Hisham/Desktop/Rails_projects/myblog
Application Trace | Framework Trace | Full Trace
app/views/posts/edit.html.erb:6:in `_app_views_posts_edit_html_erb___871381459853082993_70260921890920'
So I'm trying to make a form that would allow users to comment on specific posts. Im currently having trouble after the submit button is clicked. The entry does get put into the database, however it looks like im experiencing some routing problems.
Here is the URL I get redirected to:
"localhost:3000/groups/13/posts/62/comments"
I get the following error after submission:
No route matches {:action=>"show", :controller=>"groups"}
I ran rake routes to find this:
group GET /groups/:id(.:format) groups#show
Here is my comments controller:
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].merge({:user_id => current_user.id}))
redirect_to :action => :show, :controller => :groups
end
end
Here is my form for the comment:
<%= form_for([post.group, post, post.comments.build]) do |f| %>
<p>
<%= f.label :comment %><br />
<%= f.text_area :body, :rows => 3, :cols => 55 %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Does anyone have any ideas what might be wrong? Why is it redirecting to the url "localhost:3000/groups/13/posts/62/comments"
Thanks
I would do:
class CommentsController < ApplicationController
respond_to :html
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment]) do |comment|
comment.user = current_user # user_id shouldn't be an attr_accessible
end
respond_with #comment, location: group_path(#post.group)
end