I'm trying to force a flash method out of my model so I can display something nicer than the standard rails error.
I have this method in my model, invitation.rb:
def recipient_is_not_registered
if User.find_by_email(recipient_email)
false
else
true
end
end
I call it with a before_create :recipient_is_not_registered callback and it returns false if the recipient_email has already been registered in the database as a User. This should trigger the if #invitation.save as false, which goes down the else branch, displaying the flash message.
In my invitations_controller.rb I have:
def create
#invitation = Invitation.new(invitation_params)
#invitation.sender = current_user
if #invitation.save
redirect_to root_url, notice: 'Invitation was successfully created.'
else
flash[:notice] = "The email address #{recipient_email} has already been registered."
end
end
This gives me the aforementioned error: undefined local variable or method ``recipient_email'
I have tried various iterations of Invitation.recipient_email to no avail.
There are 2 questions.
Resolve the NameError.
Discover why the flash isn't being displayed.
You can try this:
def create
#invitation = Invitation.new(invitation_params)
#invitation.sender = current_user
if #invitation.save
redirect_to root_url, notice: 'Invitation was successfully created.'
else
flash[:notice] = "The email address #{#invitation.recipient_email} has already been registered."
end
end
I hope this help you.
Based on the information you provided, looks like recipient_email is an attribute of Invitation, which is going to be available within the Invitation only.
Try the following:
def create
#invitation = Invitation.new(invitation_params)
#invitation.sender = current_user
if #invitation.save
redirect_to root_url, notice: 'Invitation was successfully created.'
else
flash[:notice] = "The email address #{#invitation.recipient_email} has already been registered."
end
end
Related
Which one is right to use? flash[:notice] = 'some msg' or :notice = 'some msg'?
I have met both options, but there is no explanations about difference. So I confused which one is right to use. Maybe it's the same?
If you have a controller with an action, such as the following:
def create
#activity = Activity.new activity_params
if #activity.save
flash[:notice] = 'Activity was successfully created!'
redirect_to activity_path(#activity)
else
render :new
end
end
Then you can use flash[:notice] and set the flash hash's notice to Activity was successfully created!.
However, you are correct, when using redirect_to you can pass :notice as an option, as such:
def destroy
if #activity.destroy
redirect_to activities_path, notice: 'Activity was successfully destroy!'
else
flash.now[:notice] = 'Activity was not destroyed.'
end
end
If you check the ActionController::Redirecting module you will see that notice can be passed as an option.
Fundamentally, these two things do the same thing. They are just being set differently.
Hope this helps!
Im doing some testing on my app.
I have a form that accepts a city(autocompleted by city name), and some dates.
Because I have a autocomplete feature, I have to get the city_id by looking up the city by its display name.
def trip_params
params.require(:trip).permit(:start_date, :end_date).merge(:city_id => City.find_by_display(params[:trip][:city_id]).id)
end
The problem is if the user sumbits the form without a city. I get an error:
undefined method `id' for nil:NilClass
Because there was no record found. Whats a better way to structure this so that I can redirect back to 'new' if no city is entered?
create method just in case its helpful.
def create
#trip = current_user.trips.build(trip_params)
if #trip.save
flash[:success] = "Trip to #{#trip.city.name} added."
redirect_to root_path
else
flash.now[:error] = #trip.errors.full_messages
render 'new'
end
end
def create
if params[:trip][:city_id].blank?
flash[:error] = "some warning about the city"
render new
else
#trip = current_user.trips.build(trip_params)
if #trip.save
flash[:success] = "Trip to #{#trip.city.name} added."
redirect_to root_path
else
flash.now[:error] = #trip.errors.full_messages
render 'new'
end
end
end
or
def trip_params
if !params[:trip][:city_id].blank?
params.require(:trip).permit(:start_date, :end_date).merge(:city_id => City.find_by_display(params[:trip][:city_id]).id)
end
end
def create
#user = User.create(user_params)
if #user.valid?
charge = StripeWrapper::Charge.create(amount: 999, card: params[:stripeToken], description: "Sign up charge for #{#user.email}" )
if charge.successful?
#user.save
User.inviter_and_invited_follow_each_other(#user)
AppMailer.delay.welcome(current_user)
session[:user_id] = #user.id
flash[:notice] = "You have successfully registered and will be logged in."
redirect_to root_path
else
flash[:notice] = charge.error_message
render :new
end
else
render :new
end
end
User saves even when charge.successful? returns false. Nothing else happens as in no email is sent, session[:user_id] isn't set nor is it redirected to root_path. Else block executes and renders :new and displays a flash notice saying card is declined.
I am trying to avoid the user creation if charge.successful? returns false. Any idea on how to go about this?
The create method is basically a combination of doing #user = User.new followed by #user.save.
So you can just use .new instead of .create. That way, it'll only be persisted to the database when you call .save:
#user = User.new(user_params)
I'm developing an application with optional sign up. I want to allow users, with and without accounts, to be able to add links. How could I assign a user's session[user_id] to the user_id column of Link if they're signed in when creating a link?
Current code: user_id remains nil in either case
def create
#link = Link.new(params[:link])
if #link.save
flash[:notice] = "The link was successfully added"
redirect_to :action => :hot
else
redirect_to :action => :new
end
end
I'm imagining something like this..
def create
if session[:user_id]
##link equals new link params with user_id = session[:user_id]
else
#link = Link.new(params[:link])
end
if #link.save
flash[:notice] = "The link was successfully added"
redirect_to :action => :hot
else
redirect_to :action => :new
end
end
def create
#link = Link.new params[:link]
#link.user_id = session[:user_id] if session[:user_id]
if #link.save
redirect_to { action: 'hot' }, notice: 'The link was successfully added'
else
render :new
end
end
The link will be saved with params[:link] even if the user isn't logged-in.
Be cautious to use render, not redirect_to, when a validation fails (see if you want http://guides.rubyonrails.org/action_controller_overview.html)
I'm running this function, and I KNOW that it gets called because the redirect_to is working. But for some reason, #user isn't! If it helps, #user is devise based.
def make_feed_preference
#user = current_user
##user.feed_preference = params[:preference]
#user.feed_preference = "time"
#user.name = "Shoo Nabarrr"
#user.karma = 666
#user.save
redirect_to '/posts'
end
I fixed it myself. I had to create a new class attached to users in order to get it to work. Lol.
Do you have any validations on this user? They are probably blocking this save. The redirect_to will be called regardless of whether or not the save passes or fails.
I would recommend doing it like this instead:
if #user.save
redirect_to '/posts'
else
render :feed_preference
end
Where :feed_preference is the form where users enter their feed preferences.
There are cases where I want to be sure to update a flag or other field on a record even if the record has validation problems. (However, I would never do that with unvalidated user input.) You can do that thusly:
def make_feed_preference
case params[:preference]
when 'time', 'trending_value', 'followers'
current_user.update_attribute 'feed_preference', params[:preference]
flash[:notice] = 'Your feed preference has been updated.'
else
flash[:notice] = 'Unknown feed preference.'
end
redirect_to '/posts'
end