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.
Related
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.
I am using Rails 5 and I am trying to use this redirect_back method.
However, my issue is that I am using it for a Comment#Create which can be called for both a Question & Answer object. So depending on which it is, I want it to redirect back to that respective object (which have two different routing paths ofcourse).
So, what I have done is created a concern, added a custom method and then attempted to call that method in the redirect_back call but it doesn't seem to be working.
The concern looks like this:
module CommentRedirect
extend ActiveSupport::Concern
def question_or_answer(comment)
if comment.commentable_type.eql? "Question"
question_path(comment.commentable)
elsif comment.commentable_type.eql "Answer"
question_path(comment.commentable.question)
end
end
end
Then my Comment#Create looks like this:
format.html { redirect_back(fallback_location: question_or_answer(#comment)), notice: 'Comment was successfully created.' }
The error I get is this:
SyntaxError at /comments
syntax error, unexpected ',', expecting '}'
... question_or_answer(#comment)), notice: 'Comment was success...
...
Given that this is the redirect_back code in Rails:
def redirect_back(fallback_location:, **args)
if referer = request.headers["Referer"]
redirect_to referer, **args
else
redirect_to fallback_location, **args
end
end
Can I use the helper method in the way I am attempting?
If not, how else can I achieve what I want to do?
Edit 1
This is the entire Comment#Create method:
def create
#comment = Comment.new(comment_params)
#comment.user = current_user
respond_to do |format|
if #comment.save
format.html { redirect_back(fallback_location: question_or_answer(#comment)), 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
I didn't notice right away either, but your line is not valid syntax:
format.html { redirect_back(fallback_location: question_or_answer(#comment)), notice: 'Comment was successfully created.' }
It should be this:
format.html { redirect_back(fallback_location: question_or_answer(#comment), notice: 'Comment was successfully created.') }
I am using this 3rd party controller:
class LibController
def update
# 29 lines of code
respond_with resource
end
end
I want to do something other than the respond_with at the end. But I don't want to just copy/paste all 29 lines into MyController.update. Unfortunately I can't figure out a way to render or redirect anywhere else:
class MyController < LibController
def update
super
redirect_to somewhere_else
end
end
I get a DoubleRenderError: Render and/or redirect were called multiple times in this action. I assume this is because respond_with calls render immediately. Is there a way to block/prevent that?
Thanks!
I think you are doing a twice redirection.
Try to remove one redirection on your update method.
Check sample code below that shows equivalent response when using respond_with.
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
Which is exactly the same as:
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, status: :created, location: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user.errors, status: :unprocessable_entity }
end
end
end
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.
What's the difference between respond_to and respond_with ?
What do they do?
Can anyone post example with the screenshot of output?
Thanks.
There is a pretty complete answer here. Essentially respond_with does the same thing as respond_to but makes your code a bit cleaner. It is only available in rails 3 I think
Both respond_to and respond_with does the same work, but respond_with tends to make code a bit simple,
Here in this example,
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
The same code using respond_with ,
def create
#task = Task.new(task_params)
flash[:notice] = "Task was successfully created." if #task.save
respond_with(#task)
end
also you need to mention the formats in your controller as:
respond_to :html,:json,:xml
When we pass #taskto respond_with, it will actually check if the object is valid? first. If the object is not valid, then it will call render :new when in a create or render :edit when in an update.
If the object is valid, it will automatically redirect to the show action for that object.
Maybe you would rather redirect to the index after successful creation. You can override the redirect by adding the :location option to respond_with:
def create
#task = Task.new(task_params)
flash[:notice] = #task.save ? "Your task was created." : "Task failed to save."
respond_with #task, location: task_path
end
For more information visit this Blog