I am somewhat new to Rails, and I am learning off of a tutorial online. The guy in the videos talked about how you have to have an if statement to decide if the save worked or not.
This is my code:
def create
#quiz = Quiz.new(quiz_params)
if #quiz.save
flash[:notice] = "Your quiz has been created."
redirect_to action: 'index'
else
render('new')
end
end
The quiz_params was defined as such:
params.require(:quiz).permit(:title, :summary, :visible)
For some reason, it refuses to redirect to the index function, deciding to stay on the same page while the URL changes from localhost:3000/quizzes/new to localhost:3000/quizzes.
The guy who taught the tutorial had this code.
def create
#subject = Subject.new(subject_params)
if #subject.save
flash[:notice] = "Subject created succesfully."
redirect_to(subjects_path)
else
render('new')
end
end
The subject_params went as such:
params.require(:subject).permit(:name, :position, :visible)
Other than the wording in the quotes and the name of the model and variables, I am not sure what the difference is. I am being as consistent as I can, so there shouldn't be any difference.
Sorry if the formatting is bad.
You can run rake routes on your command prompt then they see what is the index_path if got to redirect to the home page then write
redirect_to root_path #=> Or root_url
Or if your controller is QuizzesController then your index path is quizzes_path
redirect_to quizzes_path #=> Use instead of redirect_to action: 'index'
Or if you have articles/index then
redirect_to articles_path
Hope to help
Your validation fails and it renders 'new' view. while action remains to create.
If you will see rake routes this route corresponds to localhost:3000/quizzes to create action.
You can refer this answer for details.
you can use byebug to debug the request and see if the code is calling redirect_to or not. it could be an ajax form as #fool said. check the form object in the view if it has remote: true attribute, delete it and try again.
Change below line in controller:
redirect_to action: 'index'
with
redirect_to "/quizzes"
So the code be like:
def create
#quiz = Quiz.new(quiz_params)
if #quiz.save
redirect_to "/quizzes", notice: "Your quiz has been created."
else
render 'new'
end
end
You should tell us Rails and Ruby version. Anyway I am using Rails 5+ and I think the syntax
Render('new')
Is old or deprecated. What I do usually is this.
def create
plan = Plan.new plan_params
plan.delivered = 0
plan.user_id = params['u_id']
if plan.save
flash[:OK] = 'Il nuovo piano e\' stato salvato con successo!'
else
flash[:err] = 'Siamo spiacenti ma non siamo riusciti a registrare il tuo piano, ricontrolla i dati inseriti!'
flash[:errors] = plan.errors.messages
end
redirect_to plans_users_path(User.find(params['u_id']))
end
So my advice is try to use named paths instead of strings.
Related
I've been trying to fix this for a while but haven't gotten anywhere yet. Would appreciate if someone could let me know how how this can be done, or if there is any way i can use the render method to do this instead (currently preserves errors but redirects to wrong path as mentioned below...)
I have a custom route for form which I am trying to redirect back when there are validation errors:
get "clubs/sign_up/:plan_id", to: "clubs#new", as: :new_membership
below is what I have so far in my controller along along with some comments regarding other steps I have tried
clubs_controller.rb
def create
#membership = Membership.new(membership_params)
if #membership.save
redirect_to root_path
else
flash[:error] = "Please check form errors:"
redirect_to new_membership_path(session[:membership_plan_id]) #errors lost
# render action: 'new', plan_id: 'silver' # <<<Preserves errors but breaks path, renders: localhost:3000/clubs instead of .../clubs/sign_up/:plan_id
# session[:membership_errors] = #membership.errors #<<< Doesn't wotk either, getting a cookie overflow error when trying to pass errors to #new
return
end
end
def new
session[:membership_plan_id] = params[:plan_id]
#membership = Membership.new
end
Assuming plan_I'd is part of your model..
Change your render line to:
render :new
Change the rest to:
def new
session[:membership_plan_id] = params[:plan_id]
#membership = Membership.new plan_id: params[:plan_id]
end
def create
#membership = Membership.new(membership_params)
if #membership.save
redirect_to root_path
else
flash[:error] = #membership.errors.full_messages.to_sentence
render :new
end
end
And add a hidden field for plan_id in your form. The reason render goes wrong is that it does not have the param available, trying to add it to the render operation does not work hence your issue
You need to render instead of redirecting. Use the ||= operator to help here.. It's all just ruby, so something like
(..snip..)
else
flash[:error] = "Problem with form"
new
end
end
def new
session[:membership_plan_id] = params[:plan_id]
#membership ||= Membership.new
render 'new'
end
I have a rails app that tweets out a show page url every time a post is made (called sub_opp in my app).
So when something gets posted a tweet goes out that includes a link like www.app.com/sub_opp/1
These posts can be canceled by the user. I'm trying to do a before action on show that says if it's blank, redirect to home and flash a notice but it seems that the id not found beats it to the punch. Here is my before_action.
def validate_opp_open
sub_opp = SubOpp.find(params[:id])
if sub_opp.blank?
redirect_to sub_opps_url, notice: 'Sorry. This opportunity is no longer available.'
end
end
It gets hung up on the sub_opp = SubOpp.find(params[:id]) line saying it cannot find it, which makes sense. Is there any way around this?
HERE IS THE ANSWER
def validate_opp_open
sub_opp = SubOpp.find_by(id: params[:id])
if sub_opp.blank?
redirect_to sub_opps_url, notice: 'Sorry. This opportunity is no longer available.'
end
end
Change:
sub_opp = SubOpp.find(params[:id])
To:
sub_opp = SubOpp.find_by(id: params[:id])
ActiveRecord provides a facility to check if a record exists:
SubOpp.exists?(params[:id])
The problem is find causes an exception if it doesn't succeed. You can either catch the exception with rescue or use
sub_opp = SubOpp.where(:id => params[:id]).first
This will produce nil when a record is not found. This is portable between Rails 3 and 4. #BroiSatse's solution is more elegant, but it will only work on Rails 4. In Rails 3, you must say
sub_opp = SubOpp.find_by_id(params[:id])
The rescue method will be something like:
def validate_opp_open
sub_opp = SubOpp.find(params[:id])
rescue ActiveRecord::RecordNotFound => e
redirect_to sub_opps_url, notice: 'Sorry. This opportunity is no longer available.'
end
def validate_opp_open
unless sub_opp = SubOpp.find(params[:id])
redirect_to sub_opps_url, notice: 'Sorry. This opportunity is no longer available.'
end
end
I have a basic post / comment setup. Here, I call them pins and replies, but the same format applies, respectively.
My replies (comments) are nested under pins (posts). When I submit a reply with an error I redirect back to the pin, but any data entered on the form is lost. I'd like to preserve this.
replies_controller.rb
def create
#pin = Pin.find(params[:pin_id])
#reply = #pin.replies.build(params[:reply].permit(:reply))
#reply.user_id = current_user.id
#reply.save
if #reply.save
flash[:success] = "Reply successfully created"
redirect_to pin_path(#pin)
else
if #reply.errors.any?
flash[:warning] = "#{#reply.errors.count} Problems found: #{#reply.errors.full_messages.to_sentence}"
end
redirect_to pin_path(#pin)
end
end
Because it does a redirect, I think this is what is wiping the form. How can I handle the error so that it renders the view of the pin (post) I just came from, instead of redirecting?
Thanks a heap!
Michael.
Do not redirect, instead:
render 'pins/new'
Use render instead of redirect
def create
#pin = Pin.find(params[:pin_id])
#reply = #pin.replies.build(params[:reply].permit(:reply))
#reply.user_id = current_user.id
#reply.save
if #reply.save
flash[:success] = "Reply successfully created"
redirect_to pin_path(#pin)
else
if #reply.errors.any?
flash[:warning] = "#{#reply.errors.count} Problems found: #{#reply.errors.full_messages.to_sentence}"
end
render :template => "pins/show"
end
end
I am using rails 3.0.7. In the controller I have:
def create
#subscription = Subscription\
.new_from_nested_attributes_parameters(params[:subscription])
if #subscription.save
flash[:notice] = 'The Subscription was successfully created.'
end
respond_with #subscription
end
and in the view:
<%="Notice:#{flash[:notice]}"%>
Doesn't print anything despite that the object is being properly saved.
Do you have an idea on how should I fix this?
I discovered the problem.
flash[:notice]="...." is properly working on the create action, redirecting to the show action.
What I forgot was that my 'show' consists on a redirect to edit.
I fixed this by implementing the show action like this:
def show
redirect_to edit_subscription_path(#subscription),flash
end
From Rails 3.1 on, this should be accomplished with:
def show
flash.keep
redirect_to edit_subscription_path(#subscription)
end
In Rails 3.2, the following will work and appears to keep the flash intact:
respond_with #subscription, :location => edit_subscription_path(#subscription)
You can skip the show page:
Instead of:
respond_with #subscription
Put:
respond_with #subscription, edit_subscription_path(#subscription)
I have been trying to get to grips with jQuery and been following a railscast on adding an Ajax add review form, which works fine but I would now like to add into it the ability for a review to belong to a user as well as a venue.
Reviews controller
def create
#review = Review.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
views\reviews\create.js.erb
$("#new_review").before('<div id="flash_notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#reviews_count").html("<%= pluralize(#review.venue.reviews.count, 'Review') %>");
$("#reviews").append("<%= escape_javascript(render(:partial => #review)) %>");
$("#new_review")[0].reset();
I have tried changing the controller to:
def create
#review = #current_user.reviews.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
but it just wont submit, with no errors.
I think I have the models set correctly with belongs_to and has_many, I think this is a controller issue I'll add other code bits if needed.
Development log
NoMethodError (undefined method `reviews' for nil:NilClass):
app/controllers/reviews_controller.rb:14:in `create'
Thanks for any help!
It appears that your error is residing with #current_user. According to your development log, #current_user is nil when you call #current_user.reviews on it. I would say track down where this #current_user instance variable is being set and find out why it is nil. Now, what kind of authentication are you using? Most authentication plugins, especially those used by Ryan Bates of the Railscasts you mentioned, use a local variable, say just current_user, as the means to access the currently signed in user. I know I do in all my code.
So, rewrite the line as
#review = current_user.reviews.create!(params[:review])
and see if that works. If it doesn't, change it back and then track down where this #current_user is being set. Chances are good it is being set in a before_filter :method_name at the beginning of your controller.
Calling create! (with exclamation mark) will throw an exception and thus abort your create action if saving fails. Check your log/development.log for these exceptions.
Use build instead of create and lose the exclamation mark.
def create
#review = #current_user.reviews.build(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end