rails: ActionController::RoutingError (No route matches [PATCH] "/article/viewing-article-2"): - ruby-on-rails

I am currently learning rails and facing a totally weird issue.
I am trying to update an existing article by following a tutorial that I am doing, however it is not getting updated. I am receiving the following errors from the terminal and browser respectively:
- Terminal:
* Started PATCH "/article/viewing-article-2" for 127.0.0.1 at 2018-03-28 18:54:46 +0200
* No route matches [PATCH] "/article/viewing-article-2"
- Browser: ActionController::RoutingError (No route matches [PATCH] "/article/viewing-article-2"):
My routes are such as
**routes.erb**
Rails.application.routes.draw do
root to: 'pages#index'
post 'article/create-new-article', to: 'pages#create'
get 'article/viewing-article-:id', to: 'pages#show', as: 'article'
get 'article/:id/edit', to: 'pages#edit', as: 'article_edit'
patch 'article/:id/update', to: 'pages#update', as: 'update_article'
get 'article/new-article', to: 'pages#new'
get 'article/destroy', to: 'pages#destroy'
end
and my controller:
controller.erb
def index
#articles = ##all_articles.all
end
def show
#article = Article.find(params[:id])
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
article_params = params.require(:article).permit(:title, :author, :publisher, :content)
#article.update(article_params)
redirect_to root_path
end
and my html:
edit.html.erb
<% content_for :title do %>Editing <%= #article.title %><% end %>
<% content_for :bodycontent do %>
<h3>Editing <%= #article.title %></h3>
<%= form_for #article do |f| %>
<%= f.text_field :title, class: 'form-control'%>
<%= f.text_field :author, class: 'form-control'%>
<%= f.text_field :publisher, class: 'form-control'%>
<%= f.text_area :content, class: 'form-control'%>
<%= f.submit class: 'form-control btn btn-primary' %>
<% end %>
<% end %>
I am not surely what I am doing wrong, as the selected article does not get updated.
I have loved rails so far, and hope to get better at it. Will appreciate any help.

Modify form_for as follows with custom url
<%= form_for #article, url: #article.new_record? ? article_create_new_article_path : update_article(#post)do |f| %>
but I will suggest you to use Resourceful Routing instead.

At first, you really should using resource routing for you article model:
Rails.application.routes.draw do
root 'pages#index'
resources :articles
end
This is what controller should look like. About permit params read here.
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def edit
#article = Article.find(params[:id])
end
def update
return unless request.patch?
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to root_path
else
render :edit
end
end
private
def article_params
params.require(:article).permit(:title, :author, :publisher, :content)
end

Related

Ruby on Rails blog and adding comments to posts and editing and deleting comments

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.

NoMethodError for new controller in 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

no method error in posts#edit (take 2)

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'

Having some error issues about designing a blog in Ruby on Rails

I tried to use paperclip to include Images in my design of a blog. I keep getting the error :
ActionController::UrlGenerationError in ArticlesController#create
No route matches {:action=>"show", :controller=>"articles"} missing required keys: [:id]
Now, whenever I click on the submit button to create a new article, it says "Could not find article without id". I tried also accessing the view for the show page through a link and I could not.
Extracted source (around line #30):
Here is my Articles Controller
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
#article.save
redirect_to article_path
end
def edit
#article = Article.find(params[:id])
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
def update
#article = Article.find(params[:id])
#article.update(article_params)
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path
end
def article_params
params.require(:article).permit(:title, :body, :tag_list, :image)
end
end
Here is my articles Helper:
module ArticlesHelper
def article_params
params.require(:article).permit(:title, :body, :tag_list, :image)
end
end
Here is my articles/show.html.erb
<h1><%= #article.title %></h1>
<p>
Tags:
<% #article.tags.each do |tag| %> <%= link_to tag.name, tag_path(tag) %>
<% end %>
</p>
<% if #article.image.exists? %>
<p><%= image_tag #article.image.url %></p>
<% end %>
<p><%= #article.body %></p>
<h3>Comments (<%= #article.comments.size %>)</h3>
<%= render partial: 'articles/comment', collection: #article.comments %>
<%= render partial: 'comments/form' %>
<%= link_to "<< Back to Articles List", articles_path %>
<%= link_to "delete", article_path(#article), method: :delete, data: {confirm: "Really delete the article?"} %>
<%= link_to "edit", edit_article_path(#article) %>
And here is my routes file
TheBlog::Application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
get 'article' => 'articles#show'
resources :users
resources :articles do
resources :comments
end
resources :tags
end
The error is telling you that you're missing the :id parameter when attempting to generate the article show route in your ArticlesController.
The resources :articles line in your config/routes file will generate a number of routes helper methods, including article_path for the show route. By default, this helper method requires one argument - one that is can translate into the aforementioned :id param. This argument should be an article id or, more commonly, an instance of an article. You need to tell Rails to which article show page to send the user, right?
Hence, you need to pass an article instance to your call to article_path in your create action (and update it appears). Here is a rewrite of your create action:
def create
#article = Article.new(article_params)
#article.save
redirect_to article_path(#article)
end

NoMethodError in PostsController#create following the getting started guide

I am a Rails newbie and therefore I am following the getting started guide, available here: http://edgeguides.rubyonrails.org/getting_started.html and here: http://guides.rubyonrails.org/getting_started.html but I can't get the point 5.6 / 5.7 to work.
This is my controller:
class PostsController < ApplicationController
def new
end
def show
#post = Post.find(params[:id])
end
def create
#post = Post.new(post_params)
#post.save
redirect_to #post
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
and this is my form:
<%= form_for :post, url: posts_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %> <br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
This is the routes.rb
Blog::Application.routes.draw do
get "welcome/index"
root 'welcome#index'
resource :posts
end
but when I submit it, I get this error:
NoMethodError in PostsController#create
undefined method post_url' for #<PostsController:0x007f733c415418> with the extract source highlighting the line redirect_to #post.
What am I doing wrong? I have ruby 1.9.3 and rails 4.0.0
In your routes.rb I see you've
resource :posts
I believe, it should be:
resources :posts
You might have missed to add the Post part in your routes. Try running rake routes and see what results you get on this :
rake routes | grep post
if you have mentioned post in your routes then may be you are using the wrong path here.
Did you add the following line to your config/routes.rb?
resources :posts

Resources