currently doing an tutorial and ran into an issue with redirect.
Rails prints out the following message:
undefined method ` redirect_to' for #<PortfoliosController:0x00007fc6ec31b108> Did you mean? redirect_to
PortfolioController:
class PortfoliosController < ApplicationController
def index
#portfolio_items = Portfolio.all
end
def new
#portoflio_item = Portfolio.new
end
def create
#portfolio_item = Portfolio.new(params.require(:portfolio).permit(:title, :subtitle, :body))
respond_to do |format|
if #portfolio_item.save
format.html { redirect_to portfolios_path, notice: 'Portfolio was successfully created.' }
else
format.html { render :index }
end
end
end
def edit
#portfolio_item = Portfolio.find(params[:id])
end
def update
#portfolio_item = Portfolio.find(params[:id])
respond_to do |format|
if #portfolio_item.update(params.require(:portfolio).permit(:title, :subtitle, :body))
format.html { redirect_to portfolios_path, notice: 'Portfolio item successfully updated!'}
else
format.html { render :edit }
end
end
end
end
As you can see, i use redirect_to also in the def create without any problems, but def update says redirect_to is undefined?
Any ideas?
Thanks in advance!
As you've typed redirect_to, that's almost correct, and also Rails is telling you probably you mean redirect_to, then the problem is like in most of the cases, when opening curly braces, accidentally a non-breaking space is added. Unless you're using an editor that handles non-visible characters then you can realize of this, otherwise the error will be there until Rails throws the error.
Just delete the space between the { and respond_to.
For Atom see atom-highlight-bad-chars.
For Sublime see Dealing with Alt+Space (non-breakable space) in Sublime Text.
Related
I have a hard time understanding this code:
def create
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
else
format.html { render :new }
end
end
end
What actually bothers me is the line #article = Article.new(article_params).
It has the key-value pairs from the according web-formular. I have printed it to the console.
But where does article_params come from?
It hasn't been declared somewhere.
By Rails conventions, the <entity>_params is a method declared in the private section of the controller that returns filtered parameters send with the request.
I am trying to redirect_to category_products after #product.destroy, which I cannot get the :category_id. I don't know how to redirect without the :category_id back to product#index. Below is my products_controller.rb, rake routes, and error message - anyone know a quick fix?
products_controller.rb (destroy)
def destroy
#category = Category.find(params[:category_id])
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to category_products_path(#category), notice: 'Pro$
format.json { head :no_content }
end
end
rake routes:
category_products GET /categories/:category_id/products(.:format) products#index
error: "Couldn't find Category without an ID"
If you look at your params, you'll see there is no params[:category_id] because you're using shallow nesting.
Try something more like:
def destroy
#product = Product.find(params[:id])
#category = #product.category
#product.destroy
respond_to do |format|
format.html { redirect_to category_products_path(#category), notice: 'Pro$
format.json { head :no_content }
end
end
This, naturally, assumes that Product belongs_to :category.
(I'm ignoring that trailing $ because there seems to be something off about your editor or copy-and-paste.)
I have a rails controller where every action has the same respond_to block for every action, eg:
def some_action
respond_to do |format|
format.html { redirect_to :back }
format.js { render layout: false }
end
end
Is there a way that I can set this as the default response for all actions? I know that I can use
respond_to :html, :js
at the top of the controller, but can this be used to set the specific responses for each format?
Going though respond_with and respond_to documentation and source code. You can either
Use respond_to
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(#user) }
format.xml { render xml: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user }
end
end
end
OR respond_with
respond_to :html, :xml
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
A work around is to create your own custom respond method, or manually check for the mime type as follows:
****NOTE: this is a really bad practice, I recommend sticking to conventions.
def some_action
render json: {"a" => "s"} if request.format.json?
render :some_action if request.format.html?
end
If you want all actions to respond exactly the same, move the respond_to block into a method.
def some_action
# do things
respond
end
def another_action
# do more things
respond
end
def special_action
# do special things
respond
end
private
def respond
respond_to do |format|
format.html { redirect_to :back }
format.js { render layout: false }
end
end
This will DRY up your controller, which I assume was the question.
I have the following code:
def edit
#post = Post.find(params[:id])
if !current_user.posts.include?(#post)
permission_denied
end
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #post }
end
end
def permission_denied
flash[:notice] = 'Sorry, you are not authorized to access that page.'
redirect_to root_url
end
How could adapt this code, so it doesn't show me the "Render and/or redirect were called multiple times in this action" . I have tried adding "and return" to redirect_to root_url and return, but I keep getting the same error.
You should return from the edit action:
def edit
#post = Post.find(params[:id])
return permission_denied if !current_user.posts.include?(#post)
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #post }
end
end
In the Update action of Rails controllers usually there is code that looks like this:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
render :edit
end
end
In the else case, this will render the edit template. But what if I wanted to use a respond_to, exactly the same way that I have in the edit action, as:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
So, if the Update fails, be sure you are returning a json or html depending on the requested format. Does that makes sense? If so, how would you avoid the error: "Render and/or redirect were called multiple times in this action"
Makes sense to me. The answer should be simple, just return after redirect_to.
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
return
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
Not sure exactly how you're rendering multiple times, but assuming you are, a well-placed return should tell RAILS to stop processing any further renders after redirecting. If that's all true, it's likely that there's an after_filter interfering from somewhere.