Rails Route Error Nested Routes (link_to user_post_path) - ruby-on-rails

Edit// Added an edit to the bottom. The issues seems to be linked to the user_post_path.
I tried typing:
<%= link_to 'show', user_post_path(post) %>
but get the error listed below before my edit.
Which led to:
No route matches {:action=>"show", :controller=>"posts", :user_id=>#<Post id: 1, topic:
"1st Post", mood: "happy", post: "I don't know. Omg this works!", created_at:
"2012-03-30 23:42:51", updated_at: "2012-04-01 06:01:48", user_id: 1>}
Ideas?
I've looked at the other posts related to this particular issue, but I've found no solution for my problem so far.
What I'm aiming for is to show a list of posts associated with a user. The rake routes says that /users/:user_id/posts should lead to the index file but strangely the error message refers to the :show action in the post controllers. Why? Also, why is the hash for :user_id empty?
All help is appreciated.
Here is my error in the browser:
No route matches {:action=>"show", :controller=>"posts", :user_id=>#<Post id: 1, topic:
"1st Post", mood: "happy", post: "I don't know. Omg this works!", created_at:
"2012-03-30 23:42:51", updated_at: "2012-04-01 06:01:48", user_id: 1>}
W
1 Testapp::Application.routes.draw do
2 resources :users do
3 resources :posts
4 end
5
6 root to: 'home#index'
Here is my rake routes:
user_posts GET /users/:user_id/posts(.:format) posts#index
POST /users/:user_id/posts(.:format) posts#create
new_user_post GET /users/:user_id/posts/new(.:format) posts#new
edit_user_post GET /users/:user_id/posts/:id/edit(.:format) posts#edit
user_post GET /users/:user_id/posts/:id(.:format) posts#show
PUT /users/:user_id/posts/:id(.:format) posts#update
DELETE /users/:user_id/posts/:id(.:format) posts#destroy
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
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root / home#index
Posts controller:
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.find_by_user_id(params[:user_id])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
# GET /posts/1
# GET /posts/1.json
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
# GET /posts/new
# GET /posts/new.json
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
Edit//
I scoped down the problem to a link_to.
14 <% #posts.each do |post| %>
15 <tr>
16 <td><%= post.topic %></td>
17 <td><%= post.mood %></td>
18 <td><%= post.post %></td>
19 <td><%= post.user_id %></td>
20 <td><%= link_to user_post_path(post) %> #this is giving me an error
21 </tr>
22 <% end %>
23 </table>

Since these are nested paths, have you considered passing the User as well as the Post? Your final URL expects a user_id as well as a post_id, so you may need to call the following:
<%= link_to user_post_path(post.user, post) %>
The documentation is here: Rails Guide on Nested Resources

Related

Couldn't find Resturant with 'id'=5

I am building this app and nested the reviews inside the restaurants. i have set all the permisions so only the users who are the owner of the review can delete their reviews. when i delete the review , the restaurant also gets deleted and i get this error Couldn't find Restaurant with 'id'=5. How can i solve that issue ? here's my code:
resturants_controller
class ResturantsController < ApplicationController
before_action :set_resturant, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , except: [:index,:show]
before_action :check_user , only: [:edit,:update,:destroy]
# GET /resturants
# GET /resturants.json
def index
#resturants = Resturant.all
end
# GET /resturants/1
# GET /resturants/1.json
def show
#reviews = Review.where(resturant_id: #resturant.id)
if #reviews.blank?
#average_rating = 0
else
#average_rating = #reviews.average(:rating).round(2)
end
end
# GET /resturants/new
def new
#resturant = Resturant.new
end
# GET /resturants/1/edit
def edit
end
# POST /resturants
# POST /resturants.json
def create
#resturant = Resturant.new(resturant_params)
#resturant.user_id = current_user.id
respond_to do |format|
if #resturant.save
format.html { redirect_to #resturant, notice: 'Resturant was successfully created.' }
format.json { render :show, status: :created, location: #resturant }
else
format.html { render :new }
format.json { render json: #resturant.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /resturants/1
# PATCH/PUT /resturants/1.json
def update
respond_to do |format|
if #resturant.update(resturant_params)
format.html { redirect_to #resturant, notice: 'Resturant was successfully updated.' }
format.json { render :show, status: :ok, location: #resturant }
else
format.html { render :edit }
format.json { render json: #resturant.errors, status: :unprocessable_entity }
end
end
end
# DELETE /resturants/1
# DELETE /resturants/1.json
def destroy
#resturant.destroy
respond_to do |format|
format.html { redirect_to resturants_url, notice: 'Resturant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_resturant
#resturant = Resturant.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def resturant_params
params.require(:resturant).permit(:name, :descirption, :website, :phone,:image)
end
def check_user
unless #resturant.user = current_user
redirect_to root_path , alert: "Sorry this Resturant belongs to someone else"
end
end
end
reviews_controller
class ReviewsController < ApplicationController
before_action :set_review, only: [:edit, :update, :destroy]
before_action :set_resturant
before_action :authenticate_user!
before_action :check_user, only: [:edit, :update, :destroy]
# GET /reviews/new
def new
#review = Review.new
end
# GET /reviews/1/edit
def edit
end
# POST /reviews
# POST /reviews.json
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.resturant_id = #resturant.id
respond_to do |format|
if #review.save
format.html { redirect_to resturant_path(#resturant), notice: 'Review was successfully created.' }
format.json { render :show, status: :created, location: #review }
else
format.html { render :new }
format.json { render json: #review.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reviews/1
# PATCH/PUT /reviews/1.json
def update
respond_to do |format|
if #review.update(review_params)
format.html { redirect_to #review, notice: 'Review was successfully updated.' }
format.json { render :show, status: :ok, location: #review }
else
format.html { render :edit }
format.json { render json: #review.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reviews/1
# DELETE /reviews/1.json
def destroy
#review.destroy
respond_to do |format|
format.html { redirect_to resturant_path(#resturant), notice: 'Review was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_review
#review = Review.find(params[:id])
end
def set_resturant
#resturant = Resturant.find(params[:resturant_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def review_params
params.require(:review).permit(:rating, :comment)
end
def check_user
unless #review.user = current_user
redirect_to root_path , alert: "Sorry this review belongs to someone else"
end
end
end
resturants/show.html.erb
<div class="row">
<div class="col-md-5">
<p id="notice"><%= notice %></p>
<%= image_tag #resturant.image_url %>
<div class="star-rating" data-score= <%= #average_rating %> ></div>
<p><%= "#{#reviews.length} reviews"%></p>
<p>
<strong>Name:</strong>
<%= #resturant.name %>
</p>
<p>
<strong>Descirption:</strong>
<%= #resturant.descirption %>
</p>
<p>
<strong>Website:</strong>
<%= link_to #resturant.website, #resturant.website %>
</p>
<p>
<strong>Phone:</strong>
<%= #resturant.phone %>
</p>
<%= link_to "Write a review", new_resturant_review_path(#resturant), class: "btn btn-danger"%>
<%= link_to 'Edit', edit_resturant_path(#resturant) %> |
<%= link_to 'Back', resturants_path %>
</div>
<div class="col-md-7">
<% if #reviews.blank? %>
<h3>No Reviews yet</h3>
<%else%>
<table class="table">
<tbody>
<% #reviews.each do |review|%>
<tr>
<td>
<div class="star-rating" data-score= <%= review.rating%> ></div>
<p><%= review.comment%></p>
<%if user_signed_in?%>
<%if (review.user == current_user)%>
<%= link_to "Edit", edit_resturant_review_path(#resturant,review)%>
<%= link_to "Delete", resturant_review_path(#resturant,review), method: :delete %>
<%end%>
<%end%>
</td>
</tr>
<%end%>
</tbody>
</table>
<%end%>
</div>
<script type="text/javascript">
$('.star-rating').raty({
path: 'https://s3.ap-south-1.amazonaws.com/starsratings',
readOnly: true ,
score: function() {
return $(this).attr('data-score');
}
});
</script>
the Routes file
Rails.application.routes.draw do
get 'pages/welcome'
get 'pages/about'
devise_for :users
root 'resturants#index'
resources :resturants do
resources :reviews , except: [:index,:show]
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
rake routes file
Prefix Verb URI Pattern Controller#Action
pages_welcome GET /pages/welcome(.:format) pages#welcome
pages_about GET /pages/about(.:format) pages#about
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
root GET / resturants#index
resturant_reviews POST /resturants/:resturant_id/reviews(.:format) reviews#create
new_resturant_review GET /resturants/:resturant_id/reviews/new(.:format) reviews#new
edit_resturant_review GET /resturants/:resturant_id/reviews/:id/edit(.:format) reviews#edit
resturant_review PATCH /resturants/:resturant_id/reviews/:id(.:format) reviews#update
PUT /resturants/:resturant_id/reviews/:id(.:format) reviews#update
DELETE /resturants/:resturant_id/reviews/:id(.:format) reviews#destroy
resturants GET /resturants(.:format) resturants#index
POST /resturants(.:format) resturants#create
new_resturant GET /resturants/new(.:format) resturants#new
edit_resturant GET /resturants/:id/edit(.:format) resturants#edit
resturant GET /resturants/:id(.:format) resturants#show
PATCH /resturants/:id(.:format) resturants#update
PUT /resturants/:id(.:format) resturants#update
DELETE /resturants/:id(.:format) resturants#destroy
models/review.rb
class Review < ApplicationRecord
belongs_to :user , dependent: :destroy
belongs_to :resturant , dependent: :destroy
end
**models/resturant.rb**
class Resturant < ApplicationRecord
mount_uploader :image, ImageUploader
belongs_to :user, dependent: :destroy
validates :name , :descirption , :website , :phone , presence: true
has_many :reviews
validates :phone , numericality: {
only_integer: true,
}
end
my github repo
When you delete a review then the restaurant gets deleted too because of this line:
belongs_to :resturant , dependent: :destroy
Change it to:
belongs_to :resturant
And you have a similar line in Resturant that means: when a resturant is deleted then delete the resturant's user too. You probably do not want to do that.
belongs_to :user, dependent: :destroy
The dependent option does not tell what should happen to self when the association is deleted, but what should happen to associated objects when self is deleted.
IMHO the following configuration would make more sense:
class Resturant < ApplicationRecord
belongs_to :user
has_many :reviews, dependent: :destroy
class Review < ApplicationRecord
belongs_to :resturant
belongs_to :user
class User < ApplicationRecord
has_many :resturants, dependent: :destroy
has_many :reviews, dependent: :destroy

/YYYY/MM/Title-Slug URL structure with Friendly_Id Solution Chokes on #new and #edit

I have a partial solution to my previous issue which is correctly displaying the posts#index and posts#show routes, but is choking after creating a post:
ActionController::UrlGenerationError in PostsController#create
No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id, :month, :year]
Extracted source (around line #32):
30 respond_to do |format|
31 if #post.save
32 format.html { redirect_to post_path, notice: 'Post was successfully created.' }
33 format.json { render :show, status: :created, location: #post }
34 else
35 format.html { render :new }
…and editing a post:
No route matches [PATCH] "/blog/example-post/blog/2015/09/example-post"
Here are all the files in question (working off the same very simple scaffolded blog):
$ rails new blog
[...]
$ cd blog
# (Add friendly_id to Gemfile & install)
$ rails generate friendly_id
$ rails generate scaffold post title content slug:string:uniq
[...]
$ rake db:migrate
routes.rb
Rails.application.routes.draw do
scope 'blog' do
get '', to: 'posts#index', as: 'posts'
post '', to: 'posts#create'
get '/new', to: 'posts#new', as: 'new_post'
get '/:id/edit', to: 'posts#edit', as: 'edit_post'
get '/:year/:month/:id', to: 'posts#show', as: 'post'
patch '/:id', to: 'posts#update'
put '/:id', to: 'posts#update'
delete '/:year/:month/:id', to: 'posts#destroy'
end
end
post.rb
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
def year
created_at.localtime.strftime("%Y")
end
def month
created_at.localtime.strftime("%m")
end
end
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
#post = Post.friendly.find(params[:id])
end
def new
#post = Post.new
end
def edit
#post = Post.friendly.find(params[:id])
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to post_path, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to post_path, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :content, :slug)
end
end
end
posts_helper.rb
module PostsHelper
def post_path(post)
"blog/#{post.year}/#{post.month}/#{post.slug}"
end
end
app/views/posts/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th>Slug</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= post.slug %></td>
<td><%= link_to 'Show', post_path(post) %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_post_path %>
In summary, here's what works:
/blog/index
/blog/2015/09/example-post
Creating a new post (up until the point where it's supposed to redirect to posts#show when you get the UrlGenerationError mentioned above)
That said, the new post is added to the DB so if you go back to /index the new post will be visible
Destroying a post
…What doesn't work:
Editing a post (the edit page with the form will render, but after submitting your changes you'll get the aforementioned error - and the changes never make it to the DB)
Completing the redirect after creating a new post (mentioned earlier).
/blog/2015/index
/blog/2015/09/index
I'm stoked that I've gotten this far - any guidance to resolving these outstanding issues would be really appreciated!
EDIT
With thanks to #brad-werth, post creation has been fixed with the following change:
posts_controller.rb
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to post_path(#post.year, #post.month, #post), notice: 'Post was successfully created.' }
I've also tried resolving the post edit problem in the following way:
Changed the edit route to get '/:year/:month/:id/edit', to: 'posts#edit', as: 'edit_post' and added the following override to posts_helper.rb to keep the index page from breaking:
def edit_post_path(post)
"#{post.year}/#{post.month}/#{post.slug}/edit"
end
And now the "edit" link from the index page is going to the correct URL (/blog/2015/09/example-post/edit - it used to go to /blog/example-post/edit) and successfully renders the edit page. But this results in PATCH breaking (indeed, the updates don't make it to the DB):
No route matches [PATCH] "/blog/2015/09/example-post/blog/2015/09/example-post"
I recognize that this duplication problem likely lies with this edit_post_path override, but the following attempts to force the correct PATCH route have no effect:
Update PATCH route to patch '/:year/:month/:id', to: 'posts#update'
Name the updated PATCH route to as: 'patch' and add PATCH path override to posts_helper:
def patch_path(post)
"#{post.year}/#{post.month}/#{post.slug}"
end
Change the override to:
def patch_path(post)
""
end
Un-name & change PATCH route to patch '', to: 'posts#update'
Looking at the posts_controller, it doesn't look like the problem is there since it's not the redirect is not the problem - and I don't see why #post.update(post_params) would be problematic:
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
So as far as I can tell the duplication in the URL is happening prior to the PATCH action, which brings us back to the EDIT flow - it must be passing the duplication to PATCH where it winds up choking. Ideas?
Your error states:
No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id, :month, :year]
As you can see from your failing line, format.html { redirect_to post_path, notice: 'Post was successfully created.' }, you are calling post_path with no arguments.
Your route get '/:year/:month/:id', to: 'posts#show', as: 'post' expects a year, month, and id. This jives with your error message above.
To fix, simply supply the missing parameters, like so:
format.html { redirect_to post_path(#post.year, #post.month, #post), notice: 'Post was successfully created.' }
in update and create actions change:
format.html { redirect_to post_path, notice: 'Post was successfully ...' }
with
format.html { redirect_to #post, notice: 'Post was successfully ...' }

update field from a link_to in rails 4

I just need a link_to link that automatically updates a value.
I have done the following:
1) Added the field i want to update into the post_controller permit list:
#post_controller.rb
def post_params
params.require(:post).permit(:title, :description, :file, :user_id, :category_id, :revisor_id, :visible)
end
2) Added the link_to link in the view:
<td><%= link_to 'Publish', post_path(post, visible: true), method: :put %></td>
any idea what im doing wrong?
#routes.rb
resources :posts do
get 'revisions', on: :collection
end
the error i'm getting is:
param is missing or the value is empty: post
Here is the controller:
#posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
def revisions
#posts = Post.where(revisor_id: current_user.id)
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.visible = true
#post.user_id = current_user.id
#petition = Petition.new(user_id: current_user.id, category_id: #post.category_id, status: "New")
#petition.save
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :description, :file, :user_id, :category_id, :revisor_id, :visible)
end
end
Here is the view:
#revisions.html.erb
<h1>Pending for revision</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>User</th>
<th>Category</th>
<th>Revisor</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.pending_posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.description %></td>
<td><%= post.user_id %></td>
<td><%= post.category_id %></td>
<% if !post.revisor_id %>
<td> No asignado </td>
<% else %>
<td><%= post.revisor_id %></td>
<% end %>
<td><%= link_to 'Publish', post_path(post, visible: true), method: :put %></td>
<!--<td><%#= link_to 'Edit', edit_petition_path(petition) %></td>-->
<!--<td><%#= link_to 'Destroy', petition, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
</tr>
<% end %>
</tbody>
</table>
Here is the model:
#post.rb
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :user
has_one :petition
scope :my_revisions, ->(user){ where("posts.user_id = ?", user.id)}
scope :visible_posts, -> {where(visible: true)}
scope :pending_posts, -> {where(visible: false)}
end
SERVER LOG:
Started PUT "/posts/12?visible=true" for 127.0.0.1 at 2014-07-16 10:07:31 +0100
Processing by PostsController#update as HTML
Parameters: {"authenticity_token"=>"authenticitytoken=", "visible"=>"true", "id"=>"12"}
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 12]]
Completed 400 Bad Request in 2ms
ActionController::ParameterMissing (param is missing or the value is empty: post):
app/controllers/posts_controller.rb:79:in `post_params'
app/controllers/posts_controller.rb:51:in `block in update'
app/controllers/posts_controller.rb:50:in `update'
Rendered /home/kbs23/.rvm/gems/ruby-2.1.0#global/gems/actionpack-4.1.2/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.6ms)
Rendered /home/kbs23/.rvm/gems/ruby-2.1.0#global/gems/actionpack-4.1.2/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.5ms)
Rendered /home/kbs23/.rvm/gems/ruby-2.1.0#global/gems/actionpack-4.1.2/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
Rendered /home/kbs23/.rvm/gems/ruby-2.1.0#global/gems/actionpack-4.1.2/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.7ms)
Here are my routes:
#rake routes
revisions_posts GET /posts/revisions(.:format) posts#revisions
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
I finally got to fix this by just changing the link from:
<td><%= link_to 'Publish', post_path(post, visible: true), method: :put %></td>
to this:
<td><%= link_to 'Publish', post_path(post, post: {visible: :true}), method: :put %></td>

Rails 4 Nested Resources/Routes... almost there...?

I have three models - users, manufacturers, and lines. I need users to have multiple manufacturers, and each manufacturer to have multiple lines. I'm to the point where lines is finally pulling the manufacturer_id on the _form, but now it's not saving the 'name' of the 'line', only the id. It'll save the 'name' as nil, like it's not passing in the name from the form. I've read the standard docs on this and I can't for the life of me get it working. It keeps hanging up on the final create stage in the controller, and I have a feeling that I've got a lot of things wrong in the paths of the form and the controller. Hoping someone will take it easy on me and help me get the whole shebang working.
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :manufacturers
end
manufacturer.rb
class Manufacturer < ActiveRecord::Base
belongs_to :user
has_many :lines
end
line.rb
class Line < ActiveRecord::Base
belongs_to :manufacturer
end
lines_controller.rb
class LinesController < ApplicationController
before_action :set_line, only: [:show, :edit, :update, :destroy]
before_filter :load_manufacturer
# GET /lines
# GET /lines.json
def index
#lines = Line.all
end
# GET /lines/1
# GET /lines/1.json
def show
end
# GET /lines/new
def new
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#line = #manufacturer.lines.build
end
# GET /lines/1/edit
def edit
end
# POST /lines
# POST /lines.json
def create
#line = #manufacturer.lines.build
respond_to do |format|
if #line.save
format.html { redirect_to #line, notice: 'Line was successfully created.' }
format.json { render action: 'show', status: :created, location: #line }
else
format.html { render action: 'new' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /lines/1
# PATCH/PUT /lines/1.json
def update
respond_to do |format|
if #line.update(line_params)
format.html { redirect_to #line, notice: 'Line was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lines/1
# DELETE /lines/1.json
def destroy
#line.destroy
respond_to do |format|
format.html { redirect_to lines_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line
#line = Line.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_params
params.require(:line).permit(:name, :manufacturer_id)
end
def load_manufacturer
#manufacturer = Manufacturer.find(params[:manufacturer_id])
end
end
lines/_form.html.erb
<%= form_for [#manufacturer,#line] do |f| %>
<% if #line.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#line.errors.count, "error") %> prohibited this line from being saved:</h2>
<ul>
<% #line.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :manufacturer_id %><br>
<%= f.text_field :manufacturer_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
routes.rb
Linecarder::Application.routes.draw do
resources :manufacturers do
resources :lines
end
devise_for :users
root "pages#home"
get "about" => "pages#about"
match 'users/:id' => 'users#show', :via => "get"
match '/users', :to => 'users#index', :as => "all_users", :via => "get"
match '/users/:name' => 'users#show', via: :get, as: :public_profile
end
rake routes
Prefix Verb URI Pattern Controller#Action
manufacturer_lines GET /manufacturers/:manufacturer_id/lines(.:format) lines#index
POST /manufacturers/:manufacturer_id/lines(.:format) lines#create
new_manufacturer_line GET /manufacturers/:manufacturer_id/lines/new(.:format) lines#new
edit_manufacturer_line GET /manufacturers/:manufacturer_id/lines/:id/edit(.:format) lines#edit
manufacturer_line GET /manufacturers/:manufacturer_id/lines/:id(.:format) lines#show
PATCH /manufacturers/:manufacturer_id/lines/:id(.:format) lines#update
PUT /manufacturers/:manufacturer_id/lines/:id(.:format) lines#update
DELETE /manufacturers/:manufacturer_id/lines/:id(.:format) lines#destroy
manufacturers GET /manufacturers(.:format) manufacturers#index
POST /manufacturers(.:format) manufacturers#create
new_manufacturer GET /manufacturers/new(.:format) manufacturers#new
edit_manufacturer GET /manufacturers/:id/edit(.:format) manufacturers#edit
manufacturer GET /manufacturers/:id(.:format) manufacturers#show
PATCH /manufacturers/:id(.:format) manufacturers#update
PUT /manufacturers/:id(.:format) manufacturers#update
DELETE /manufacturers/:id(.:format) manufacturers#destroy
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / pages#home
about GET /about(.:format) pages#about
GET /users/:id(.:format) users#show
all_users GET /users(.:format) users#index
public_profile GET /users/:name(.:format) users#show
Update the create action as below:
def create
#line = #manufacturer.lines.build(line_params) ## Pass the params via line_params
respond_to do |format|
if #line.save
format.html { redirect_to #line, notice: 'Line was successfully created.' }
format.json { render action: 'show', status: :created, location: #line }
else
format.html { render action: 'new' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
You are not passing the params that you received from the form. Hence, name of line is not getting saved in database.
Also, in order to permit the attributes for mass-assignment(strong parameters) pass them via line_params method.
UPDATE for OP's question in the comment to resolve
undefined method 'line_url'... for 'format.html { redirect_to #line, notice: 'Line was successfully created.' }'
Use this
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully created.' }
instead of
format.html { redirect_to #line, notice: 'Line was successfully created.' }

How to Create a Blog from Scratch Using Ruby on Rails - from rails 2.x to 3.x - no visable comments

Im working with How to Create a Blog from Scratch Using Ruby on Rails tutorial from sixrevisions.com.
When I run server and create new post I have no visable option to add comment. According to tutorial I should be able to add end edit comments to created posts.
My comments_controller.rb:
class CommentsController < ApplicationController
# GET /comments
# GET /comments.json
def index
#comments = Comment.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #comments }
end
end
# GET /comments/1
# GET /comments/1.json
def show
#comment = Comment.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #comment }
end
end
# GET /comments/new
# GET /comments/new.json
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
end
# POST /comments
# POST /comments.json
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create!(params[:comment])
redirect_to #post
end
# PUT /comments/1
# PUT /comments/1.json
def update
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to #comment, notice: 'Comment was successfully
updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
format.json { head :no_content }
end
end
end
Show.html.erb
<p>
<b>Title:</b>
<%=h #post.title %>
</p>
<p>
<b>Body:</b>
<%=h #post.body %>
</p>
<h2>Comments</h2>
<% #post.comments.each do |c| %>
<p>
<b><%=h c.name %> said:</b><br />
<%= time_ago_in_words(c.created_at) %> ago
</p>
<p>
<%=h c.body %>
</p>
<% end %>
<% form_for [#post, Comment.new] do |f| %>
<p>
<%= f.label :name, "Author" %><br />
<%= f.text_field :name %><br />
<%= f.label :body, "Comment Description" %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Add Comment" %>
</p>
<% end %>
Rake routes
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
/:controller/:action/:id(.:format) :controller#:action
/:controller/:action/:id.:format :controller#:action
root / posts#index
Thanks for help & intrest!
Your code looks fine.
Go to http://localhost:3000/posts/new and create a post. This post will have a certain id, presumably 1, if it is your first post.
Then, go to http://localhost:3000/posts/1/comments - there you will see all comments (presumably none), and also a link to create a new comment. If there is no link, go to - you guessed it - http://localhost:3000/posts/1/comments/new. This is just what your routes tell you.
Looks like you're using scaffolding here. I don't know the tutorial, but look into
Rails routing
Scaffolding
create a new link with
<%= link_to('new comment',new_post_path) %>
in your view template

Resources