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.' }
Related
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
When I go to delete a post I get the error "Couldn't find Post with 'id'=testuser". I think this is a routing error as I believe the id being ran should be that of the Post and not the User? I can't work it out. I can create posts but can't delete or edit for the same reasons.
I can provide more information if needed.
The extracted source in PostController#destroy is where:
def set_post
#work = Work.find(params[:id])
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :registrations => "registrations" }
resources :posts do
end
# Define route URL
root 'pages#index'
# Define routes for Pages
get '/home' => 'pages#home'
get '/user/:id' => 'pages#profile'
get '/new' => 'posts#new'
Pages_controller.rb
class PagesController < ApplicationController
def index
end
def home
end
def profile
if (User.find_by_username(params[:id]))
#username = params[:id]
else
redirect_to root_path, :notice=> "User not found!"
end
#posts = Post.all.where("user_id = ?", User.find_by_username(params[:id]).id)
#newPost = Post.new
end
end
Posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def create
#post = Post.new(post_params)
#post.user_id = current_user.id #assign post to the user who created it
respond_to do |f|
if (#post.save)
f.html { redirect_to "", notice: "Post created!" }
else
f.html { redirect_to "", notice: "Error: Post Not Saved" }
end
end
end
def show
end
def edit
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Your 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 root_path, notice: 'Post was successfully deleted.' }
format.json { head :no_content }
end
end
private
def set_post
#post = Post.find(params[:id])
end
def post_params #allows certain data to be passed via form
params.require(:post).permit(:user_id, :title, :description, :image)
end
end
Profile.html.erb
...
<%= link_to('Delete', post_path, :method => :delete) %>
...
Terminal
Prefix Verb URI Pattern Controller#Action
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) registrations#cancel
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
PATCH /users(.:format) registrations#update
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#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
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
root GET / pages#index
home GET /home(.:format) pages#home
GET /user/:id(.:format) pages#profile
connect GET /connect(.:format) pages#connect
help GET /help(.:format) pages#help
messages GET /messages(.:format) pages#messages
new GET /new(.:format) posts#new
You did not pass id or instance in link of delete
<%= link_to('Delete', post_path, :method => :delete) %>
Should be pass a post instance on the delete link so that in find it find the post
<%= link_to('Delete', post_path(post), :method => :delete) %>
or
<%= link_to('Delete', post_path(post.id), :method => :delete) %>
In my Rails 4 app, there are four models:
class User < ActiveRecord::Base
has_many :administrations
has_many :calendars, through: :administrations
end
class Calendar < ActiveRecord::Base
has_many :administrations
has_many :users, through: :administrations
has_many: :posts
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
class Post < ActiveRecord::Base
belongs_to :calendar
end
With this routing:
Rails.application.routes.draw do
root to: 'pages#home'
devise_for :users, :path => 'account'
resources :calendars do
resources :posts, shallow: true
end
end
Which gives these routes:
Prefix Verb URI Pattern Controller#Action
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
root GET / pages#home
new_user_session GET /account/sign_in(.:format) devise/sessions#new
user_session POST /account/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /account/sign_out(.:format) devise/sessions#destroy
user_password POST /account/password(.:format) devise/passwords#create
new_user_password GET /account/password/new(.:format) devise/passwords#new
edit_user_password GET /account/password/edit(.:format) devise/passwords#edit
PATCH /account/password(.:format) devise/passwords#update
PUT /account/password(.:format) devise/passwords#update
cancel_user_registration GET /account/cancel(.:format) devise/registrations#cancel
user_registration POST /account(.:format) devise/registrations#create
new_user_registration GET /account/sign_up(.:format) devise/registrations#new
edit_user_registration GET /account/edit(.:format) devise/registrations#edit
PATCH /account(.:format) devise/registrations#update
PUT /account(.:format) devise/registrations#update
DELETE /account(.:format) devise/registrations#destroy
user_confirmation POST /account/confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /account/confirmation/new(.:format) devise/confirmations#new
GET /account/confirmation(.:format) devise/confirmations#show
user_unlock POST /account/unlock(.:format) devise/unlocks#create
new_user_unlock GET /account/unlock/new(.:format) devise/unlocks#new
GET /account/unlock(.:format) devise/unlocks#show
calendar_posts GET /calendars/:calendar_id/posts(.:format) posts#index
POST /calendars/:calendar_id/posts(.:format) posts#create
new_calendar_post GET /calendars/:calendar_id/posts/new(.:format) posts#new
GET /posts/:id/edit(.:format) posts#edit
GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
calendars GET /calendars(.:format) calendars#index
POST /calendars(.:format) calendars#create
new_calendar GET /calendars/new(.:format) calendars#new
edit_calendar GET /calendars/:id/edit(.:format) calendars#edit
calendar GET /calendars/:id(.:format) calendars#show
PATCH /calendars/:id(.:format) calendars#update
PUT /calendars/:id(.:format) calendars#update
DELETE /calendars/:id(.:format) calendars#destroy
And finally, here is the content of 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
# 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
#calendar = Calendar.find(params[:calendar_id])
#post = #calendar.posts.create(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to calendar_path(#calendar), 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 calendar_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
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#calendar = Calendar.find(params[:calendar_id])
#post.destroy
respond_to do |format|
format.html { redirect_to calendar_path(#calendar), 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(:date, :time, :subject, :format, :copy, :media)
end
end
I keep running into a similar error.
Issue #1: when I try to delete a post from the show.html.erb calendar view:
<h2><%= #calendar.name %> Calendar</h2>
<h3>Posts</h3>
<% if #calendar.posts.any? %>
<table>
<tr>
<th>Date</th>
<th>Time</th>
<th>Subject</th>
<th>Format</th>
<th>Copy</th>
<th>Media</th>
</tr>
<% #calendar.posts.each do |post| %>
<tr>
<td><%= post.date %></td>
<td><%= post.time %></td>
<td><%= post.subject %></td>
<td><%= post.format %></td>
<td><%= post.copy %></td>
<td><%= post.media %></td>
<td><%= link_to 'View', post %></td>
<td><%= link_to 'Update', edit_post_path(post) %></td>
<td><%= link_to 'Delete', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
</table>
<% end %>
...
I get:
ActiveRecord::RecordNotFound in PostsController#destroy
Couldn't find Calendar with 'id'=
Issue #2: when I try to update a post from the edit.html.erb post view:
<h1>Editing Post</h1>
<%= render 'form' %>
<%= link_to 'Show', #post %> |
<%= link_to 'Back', posts_path %>
I get:
ActiveRecord::RecordNotFound in PostsController#update
Couldn't find Calendar with 'id'=
Issue #3: when I try to go back to the show.html.erb calendar view from the show.html.erb post view:
<div>
<p>Date</p>
<%= #post.date %>
</div>
<div>
<p>Time</p>
<%= #post.time %>
</div>
<div>
<p>Subject</p>
<%= #post.subject %>
</div>
<div>
<p>Format</p>
<%= #post.format %>
</div>
<div>
<p>Copy</p>
<%= #post.copy %>
</div>
<div>
<p>Media</p>
<%= #post.media %>
</div>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Back', posts_path %>
I get:
ActiveRecord::RecordNotFound in PostsController#show
Couldn't find Calendar with 'id'=
If my interpretation of the errors is correct, every time, the problem seems to be that I cannot retrieve the id of the calendar the post belongs to.
In other words, I cannot retrieve the parent (calendar) id from the child (post) controller.
I believe this is a problem related to my nested shallow resources and the way my links are built in the views.
I can't figure out how to make these links work.
If you could provide me with the solution — and most importantly the reasoning — for one of the three situations described above, I would most definitely be able to come up with the solution for the other two.
Any idea?
I found a solution to each one of my three issues.
Issue #1: I replaced:
format.html { redirect_to calendar_path(#calendar), notice: 'Post was successfully destroyed.' }
with:
format.html { redirect_to calendar_path(#post.calendar_id), notice: 'Post was successfully destroyed.' }
in posts_controller.rb.
Issue #2: I replaced:
<%= link_to 'Back', posts_path %>
with:
<%= link_to 'Back', calendar_path(#post.calendar_id) %>
in the edit.html.erb posts view.
Issue #3: I replaced:
<%= link_to 'Back', posts_path %>
with:
calendar_path(#post.calendar_id)
in the show.html.erb posts view
I'm trying to associate "Notes" with "Account one the same page (show.html.erb) once the note is created. However, once I create the note for the associated account I get undefined local variable or method `accounts' for NotesController:0x0000000545e1d8"
Notes were being created fine up until the point of association.
with #account = accounts.find(params[:account_id]) highlighted on like 65.
**Parameters:** (on debug page)
{"utf8"=>"✓",
"authenticity_token"=>"gm6gJ3mYDDVmDHnsB2JqhOtOY1Lc9n3P7Yuq9gpqdo4=",
"note"=>{"comment"=>"1221211212"},
"commit"=>"Create Note",
"account_id"=>"1"}
Running Rails 4.1.8 and
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]
note_colltroler.rb
class NotesController < ApplicationController
before_action :set_note, only: [:edit, :update, :destroy]
before_action :set_account
before_action :authenticate_user!
before_action :check_user, only: [:edit, :update, :destroy]
# GET /notes/new
def new
#note = note.new
end
# GET /notes/1/edit
def edit
end
# POST /notes
# POST /notes.json
def create
#note = note.new(note_params)
#note.user_id = current_user.id
#note.account_id = #account.id
respond_to do |format|
if #note.save
format.html { redirect_to #account, notice: 'note was successfully created.' }
format.json { render :show, status: :created, location: #note }
else
format.html { render :new }
format.json { render json: #note.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /notes/1
# PATCH/PUT /notes/1.json
def update
respond_to do |format|
if #note.update(note_params)
format.html { redirect_to account_path(#account), notice: 'note was successfully updated.' }
format.json { render :show, status: :ok, location: #note }
else
format.html { render :edit }
format.json { render json: #note.errors, status: :unprocessable_entity }
end
end
end
# DELETE /notes/1
# DELETE /notes/1.json
def destroy
#note.destroy
respond_to do |format|
format.html { redirect_to account_path(#account), notice: 'note was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_note
#note = note.find(params[:id])
end
def set_account
#account = accounts.find(params[:account_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def note_params
params.require(:note).permit(:comment)
end
end
note.rb
class Note < ActiveRecord::Base
belongs_to :user
belongs_to :account
end
account.rb
class Account < ActiveRecord::Base
belongs_to :program
has_many :notes
end
Rake Routes
Prefix Verb URI Pattern Controller#Action
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
account_notes POST /accounts/:account_id/notes(.:format) notes#create
new_account_note GET /accounts/:account_id/notes/new(.:format) notes#new
edit_account_note GET /accounts/:account_id/notes/:id/edit(.:format) notes#edit
account_note PATCH /accounts/:account_id/notes/:id(.:format) notes#update
PUT /accounts/:account_id/notes/:id(.:format) notes#update
DELETE /accounts/:account_id/notes/:id(.:format) notes#destroy
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
programs GET /programs(.:format) programs#index
POST /programs(.:format) programs#create
new_program GET /programs/new(.:format) programs#new
edit_program GET /programs/:id/edit(.:format) programs#edit
program GET /programs/:id(.:format) programs#show
PATCH /programs/:id(.:format) programs#update
PUT /programs/:id(.:format) programs#update
DELETE /programs/:id(.:format) programs#destroy
pages_index GET /pages/index(.:format) pages#index
root GET / pages#index
For Notes show.html.erb
<div class="row">
<div class="col-md-3">
<p>
<strong>First name:</strong>
<%= #account.first_name %>
</p>
<p>
<strong>Last name:</strong>
<%= #account.last_name %>
</p>
<p>
<strong>Program:</strong>
<%= #account.program.program %>
</p>
<p>
<strong>Address:</strong>
<%= #account.address %>
</p>
<p>
<strong>Phone:</strong>
<%= #account.phone %>
</p>
<p>
<strong>Created:</strong>
<%= #account.created_at %>
</p>
<%= link_to "Write a Note", new_account_note_path(#account), class: "btn btn-primary" %>
</div>
<div class="col-md-9">
<% #notes.each do |note| %>
<p><%= note.comment %></p>
<% end %>
<%= link_to 'Edit', edit_account_path(#account), class: "btn btn-link" %> |
<%= link_to 'Back', account_path, class: "btn btn-link" %>
</div>
</div>
Instead of
#account = accounts.find(params[:account_id])
try
#account = Account.find(params[:account_id])
Learn more about .find and other query methods here. Most of them are called on an
Side Note:
As #apneadiving pointed out, you generally want to use some sort of authorisation. I don't think you want users to be able to edit accounts of other users. With your current implementation this is possible by simply experimenting in with the account and note ids in the url (e.g. by getting /accounts/1/notes/2/edit any user can edit note 2 of account 1).
Consider scoping records for the current user. One approach is described here.
in
def set_account
#account = accounts.find(params[:account_id])
end
accounts is not defined
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