I have a model called Article in my rails 4 app.
I want to add a static page called foldaway.html.erb to my views/articles folder.
I have added that view page, and updated my articles controller with:
def foldway
end
I have also tried to exclude foldaway from the set_article method:
before_action :set_article, except: [:foldway], only: [:show, :edit, :update, :destroy ]
In my routes file I have added:
get '/foldway' => 'articles#foldway'
When I save all this and try to test if the page renders, I get an error that says:
Couldn't find Article with 'id'=foldway
Why is it trying to set the article id when I have excepted it from the set_article method in my rails controller. I just want it to render a static page.
How do I add this to my file?
My complete article controller is:
class ArticlesController < ApplicationController
before_action :set_article, except: [:foldway], only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show ]
layout "article"
respond_to :html, :json
# GET /articles
# GET /articles.json
def index
#articles = policy_scope(Article)
# query = params[:query].presence || "*"
# #articles = Article.search(query)
end
# def index
# if params[:query].present?
# #books = Book.search(params[:query], page: params[:page])
# else
# #books = Book.all.page params[:page]
# end
# end
# GET /articles/1
# GET /articles/1.json
def show
end
def foldway
end
# GET /articles/new
def new
#article = Article.new
#article.comments.build
end
# GET /articles/1/edit
def edit
authorize #article
end
# POST /articles
# POST /articles.json
def create
# before_action :authenticate_user!
# authorize #article
#article = current_user.articles.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to(#article) }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /articles/1
# PATCH/PUT /articles/1.json
def update
# before_action :authenticate_user!
authorize #article
respond_to do |format|
# if #article.update(article_params)
# format.json { render :show, status: :ok, location: #article }
# else
# format.html { render :edit }
# format.json { render json: #article.errors, status: :unprocessable_entity }
# end
# end
if #article.update(article_params)
format.html { redirect_to(#article) }
format.json { render :show, status: :ok, location: #article }
else
format.json { render json: #article.errors, status: :unprocessable_entity }
end
format.html { render :edit }
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
before_action :authenticate_user!
authorize #article
#article.destroy
respond_to do |format|
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
#article = Article.find(params[:id])
authorize #article
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:body, :title, :image, :tag_list,
comment_attributes: [:opinion])
end
end
The problem is from your routes file.
I advise you tu put this inside your routes.rb file :
get 'articles/foldway' => 'articles#foldway', as: :foldway
match '/foldway', to: 'articles#foldway', via: :get
and for your articles controller you just have to put :
before_action :set_article, only: [:show, :edit, :update, :destroy ]
Related
I have a model named Group which has_many Posts and each Post has_many Comments. I can navigate to a group, create a post and then create a comment under that post. My issue is when I try and delete a comment I receive the below error about the redirect (the comment is deleted the redirect just doesn't happen).
undefined method `id' for nil:NilClass
this is the line in my destry action it does not like, which is weird because my update action has the same redirect and that works fine.
format.html { redirect_to group_post_url(group_id: #group.id, id: #post), notice: 'Comment was successfully destroyed.' }
I tried adding [:destroy] onto the set_post before_action thinking that it might need that but no luck.
here's some of my routes
group_posts GET /groups/:group_id/posts(.:format) posts#index
POST /groups/:group_id/posts(.:format) posts#create
new_group_post GET /groups/:group_id/posts/new(.:format) posts#new
edit_group_post GET /groups/:group_id/posts/:id/edit(.:format) posts#edit
group_post GET /groups/:group_id/posts/:id(.:format) posts#show
PATCH /groups/:group_id/posts/:id(.:format) posts#update
PUT /groups/:group_id/posts/:id(.:format) posts#update
DELETE /groups/:group_id/posts/:id(.:format) posts#destroy
groups GET /groups(.:format) groups#index
POST /groups(.:format) groups#create
here's my comments_controller.rb
class CommentsController < ApplicationController
before_action :set_group, only: [:index, :show, :new, :edit, :create, :update]
before_action :set_post, only: [:index, :show, :new, :edit, :create, :update]
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /posts/:post_id/comments
def index
#comments = #post.comments.order(created_at: :desc)
end
def show
end
# GET /posts/:post_id/comments/new
def new
#comment = #post.comments.new
end
# # GET /posts/:post_id/comments/edit
# def edit
# end
# POST /posts/:post_id/comments
def create
# inserts current_user into the comments foriegn key for user_id.
#comment = #post.comments.new(comment_params.merge(user_id: current_user.id))
respond_to do |format|
if #comment.save
format.html { redirect_to group_post_url(group_id: #group.id, id: #post), notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/:post_id/comments/:id
def update
respond_to do |format|
if #post.comments.update(comment_params)
format.html { redirect_to group_post_url(group_id: #group.id, id: #post), notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: #comment }
else
format.html { render :edit }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/:post_id/comments/:id
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to group_post_url(group_id: #group.id, id: #post), notice: 'Comment was successfully destroyed.' }
format.json { head :no_content }
end
end
###################
# private methods
###################
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
def set_post
#post = Post.find(params[:post_id])
end
def set_group
#group = Group.find(params[:group_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:content, :post_id, :user_id)
end
end
If you'd like to reference the #group instance variable, you should add :destroy to the before_action set_group callback:
before_action :set_group, only: [:index, :show, :new, :edit, :create, :update, :destroy]
You should also add :destroy to the before_action set_post callback as well
I have been using Rails scaffolds to build a Rails 4 app.
My current problem is set out below - which arrives when I try and render the articles new page in my app:
ActionController::UnknownFormat
It's referring to the create action in the articles controller (it extracts this error location):
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.json { render :show, status: :created, location: #article }
else
I have an articles controller with:
class ArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
# respond_to :html
# GET /articles
# GET /articles.json
def index
#articles = Article.all
end
# GET /articles/1
# GET /articles/1.json
def show
end
# GET /articles/new
def new
#article = Article.new
end
# GET /articles/1/edit
def edit
end
# POST /articles
# POST /articles.json
def create
# before_action :authenticate_user!
# authorize #article
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /articles/1
# PATCH/PUT /articles/1.json
def update
before_action :authenticate_user!
authorize #article
respond_to do |format|
if #article.update(article_params)
format.json { render :show, status: :ok, location: #article }
else
format.html { render :edit }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
before_action :authenticate_user!
authorize #article
#article.destroy
respond_to do |format|
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
#article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params[:article].permit(:body, :title, :image,
comment_attributes: [:opinion])
end
end
I have respond with html in the top line of the controller. I don't know why or what this does. I have read others problems which say you need to give it something to respond to, or use the responder gem. I don't want anything extraordinary - I just want the page to render.
Can anyone see what's wrong here?
It seems like you need a format.html so you can add this:
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to(#article,
:notice => 'Article was successfully created.') }
format.json { render :show, status: :created, location: #article }
else
format.json { render :show, status: :created, location: #article }
end
end
I hope this help you.
If you aren't trying to do anything extraordinary, here's how I would clean up this controller:
class ArticlesController < ApplicationController
before_action :set_article, except: [:new, :create, :index]
def index
#articles = Article.all
end
def show
end
def new
#article = Article.new
end
def edit
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render :new
end
end
def update
if #article.update_attributes(article_params)
redirect_to #article
else
render :edit
end
end
def destroy
if #article.destroy
redirect_to articles_path
else
redirect_to #article
end
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params[:article].permit(:body, :title, :image,
comment_attributes: [:opinion])
end
end
Note that I stripped out your authorization, so add it back in when everything is working.
I have added the elastic search gem and added a search button on the navbar however, when i want the user to search for posts it asks me to login or sign up. I want the user to be able to view the index page of the post and i added a before_filter in the posts_controller file but i don't know why it keeps asking me to sign up or log in. Here's my code:
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , except: [:index,:show]
before_filter :check_user, only: [:edit,:update,:destroy]
# GET /posts
# GET /posts.json
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.all
end
end
# GET /posts/1
# GET /posts/1.json
def show
#reviews = Review.where(post_id: #post.id)
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
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 root_url, 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,:image,:all_tags)
end
def check_user
if current_user.id != #post.user_id
redirect_to root_path , alert: "Sorry this Post belongs to someone else"
end
end
end
You can use
skip_before_filter :authenticate_user! , :only => [:index,:show]
in your controller for skipping the before_filter for those actions.
I was able to solve the issue by adding the search method to the before_action post authentication. Here's the code:
before_action :authenticate_user! , except: [:index,:show,:search]
im trying to have a put a voting system (likes and dislikes) using the Ruby gem "act_as_votable" but i want to use that in my reviews model. keep in mind that the Reviews are nested inside the Post Model in my app. i tried to add that in my routes.rb file but its not working. does anyone know how to add a voting system for a nested model ? here's my code
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :posts do
resources :reviews , except: [:show,:index]
member do
get "like" , to: "reviews#upvote"
get "dislike" , to: "reviews#downvote"
end
end
get 'pages/help'
get 'pages/blog'
get 'pages/contact'
get 'pages/tour'
resources :posts
root 'posts#index'
end
reviewsController.rb
class ReviewsController < ApplicationController
before_action :set_review, only: [ :edit, :update, :destroy, :upvote,:downvote]
before_action :set_post
before_action :authenticate_user!
respond_to :html
def new
#review = Review.new
respond_with(#review)
end
def edit
#review = Review.find(params[:id])
#post = Post.find(params[:post_id])
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.post_id = #post.id
#review.save
redirect_to post_path(#post)
end
def update
#review.update(review_params)
respond_with(#review)
end
def destroy
#review.destroy
respond_with(#review)
end
def upvote
#review.upvote_bu current_user
redirect_to :back
end
def downvote
#review.downvote_bu current_user
redirect_to :back
end
private
def set_review
#review = Review.find(params[:id])
end
def set_post
unless #post = Post.where(id: params[:post_id]).first
redirect_to posts_path, flash: {alert: "Post doesn't exists"}
end
end
def review_params
params.require(:review).permit(:comment)
end
end
PostsController.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , only: [:edit,:update,:destroy,:new]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
#reviews = Review.where(post_id: #post.id)
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
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 root_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
#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)
end
end
Disclaimer: I'm very new to Ruby on Rails.
Here is the error I am getting when attempting to generate a feed:
undefined method `title' for nil:NilClass
Extracted source (around line #2):
atom_feed do |feed|
feed.title "Who bought #{#product.title}"
feed.updated #latest_order.try(:updated_at)
Application trace:
app/views/products/who_bought.atom.builder:2:in `block in _app_views_products_who_bought_atom_builder__3166274680323093135_70240865825480'
app/views/products/who_bought.atom.builder:1:in `_app_views_products_who_bought_atom_builder__3166274680323093135_70240865825480'
This is my first time working with atom_feed - so I am really not sure what to look for here. What I have appears to be straight from the book "Agile Web Development with Rails 4" Am I missing something?
Should be:
CODING :
before_action :
set_product, only: [:show, :edit, :update, :destroy, :who_bought]
The problem was in a script I did not list - inside the products controller:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
def who_bought
#product = Product.find(params[:id])
#latest_order = #product.orders.order(:updated_at).last
if stale?(#latest_order)
respond_to do |format|
format.atom
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :image_url, :price)
end
end
The who_bought method, was listed under the private methods and I had also forgotten the '#' symbol in #latest_order
Your #product variable is nil. Did you defined it? Does the particular product exist?
Try to output it into console: logger.info #product.inspect