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
Related
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
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
In the code below, I am trying to set the popup variable for the Company object, but where it currently is located, it is not getting set when the user hits the submit button on the page where a company object is created.
When I put the line in question before the if statement, the popup variable gets set, but because the object hasn't been saved yet, the #company.id has been set yet, so that part of the popup string I am trying to create isn't set properly.
Any ideas how to get my popup variable to be set properly?
def create
#company = Company.new(company_params)
if #company.save
redirect_to map_path
flash[:success] = "Company Successfully Added"
#company.popup = "<h3><a href='companies/#{#company.id}'>#{#company.name}</a></h3>"
else
render 'new'
end
end
If popup is a company attribute and if you need to save it, just use 'before_save':
def create
#company = Company.new(company_params)
if #company.save
redirect_to map_path
flash[:success] = "Company Successfully Added"
else
render 'new'
end
end
Model:
before_save :set_popup_value
private
def set_popup_value
popup = "<h3><a href='companies/#{self.id}'>#{self.name}</a></h3>"
#self.update_attributes(:popup => popup)
self.update_column(:popup => popup)
end
else, if you want 'popup' just to display it and not to save in a database, then you must use attr_accessor.
Model:
class Company < ActiveRecord::Base
attr_accessor :popup
end
Controller:
def create
#company = Company.new(company_params)
if #company.save
#company.popup = "<h3><a href='companies/#{#company.id}'>#{#company.name}</a></h3>"
redirect_to map_path
flash[:success] = "Company Successfully Added"
else
render 'new'
end
end
Hope it helps :)
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'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)