I did a date validation in model which should display a message on page, but for some reason it isn't. I need this message to be shown in notice on error. Currently I just see the message in controller (Order not registered) but I need to see the reason (Delivery date should be from now). How can I do that?
model
def delivery_date_from_now_only
if self.delivery_date.present? && self.delivery_date <= Date.today
self.errors.add(:delivery_date, messsage: 'Delivery date should be from now')
end
end
controller
def create
#order = Order.new(order_params)
#order.user = current_user
if #order.save
flash[:notice] = 'Order registered successfully'
return redirect_to #order
end
#warehouses = Warehouse.all.order(:name)
#suppliers = Supplier.all.order(:brand_name)
#users = User.all.order(:name)
flash.now[:alert] = 'Order not registered'
render :new, status: 422
end
if you call #order.valid? it will validate your model an also populate errors for that object. that means #order.errors.messages will be a hash with { :delivery_date => ["Delivery date should be from now"]} etc (other errors will be in there as well) which u can use to do some flashes.
Related
Hello I have an app where a user is invited as an attendee
In the attendee controller, when the attendee is created the user is created but not sent an invite to the system
attendees_controller.rb
def create
#attendee = Attendee.new(attendee_params)
#user = User.invite!({email: "#{#attendee.email}"}, current_user) do |u|
u.skip_invitation = true
end
#attendee.user_id = #user.id
respond_to do |format|
if #attendee.save
format.html { redirect_to meeting_url(#attendee.meeting), notice: "Attendee was successfully created." }
format.json { render :show, status: :created, location: #attendee }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #attendee.errors, status: :unprocessable_entity }
end
end
end
in the same controller i then have a send_invite
def send_invite
#attendee = Attendee.find(params[:attendee_id])
User.where(id: #attendee.user_id).deliver_invitation
redirect_to meeting_url(#attendee.meeting)
end
when i hit it via a button I get
NoMethodError in AttendeesController#send_invite
undefined method `deliver_invitation' for #<ActiveRecord::Relation
[devise_invitable][1] clearly states
If you want to create the invitation but not send it, you can set skip_invitation to true.
user = User.invite!(email: 'new_user#example.com', name: 'John Doe') do |u|
u.skip_invitation = true
end
# => the record will be created, but the invitation email will not be sent
When generating the accept_user_invitation_url yourself, you must use the raw_invitation_token. This value is temporarily available when you invite a user and will be decrypted when received.
accept_user_invitation_url(invitation_token: user.raw_invitation_token)
When skip_invitation is used, you must also then set the invitation_sent_at field when the user is sent their token. Failure to do so will yield “Invalid invitation token” error when the user attempts to accept the invite. You can set the column, or call deliver_invitation to send the invitation and set the column:
user.deliver_invitation
What am I missing?
[1]: https://github.com/scambra/devise_invitable#send-an-invitation-
I guess .deliver_invitation is an instance method on the User Model. (through devise_invitable).
In that case you would probably want something like this:
User.where(id: #attendee.user_id).each do |user|
user.deliver_invitation
end
Assuming deliver_invitation is an instance method of the User model, you can modify your send_invite method like below:
def send_invite
#attendee = Attendee.find(params[:attendee_id])
user = User.find(#attendee.user_id)
user.deliver_invitation
redirect_to meeting_url(#attendee.meeting)
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
I have problem with validation in my project. I need to validate datetime when saving reservation.
It showing message "This date is reserved." but always create new reservation :(
It can be 3 identical datetime values and not more. Where I have problem in my code?
(I am learning RoR, so, please, be patient. :)
def create
#reservation = Reservation.create!(reservation_params)
#check_count = Reservation.select(:date).where('date = ?', #reservation.date).count
if #check_count <= 3
if #reservation.save!
ReservationMailer.new_service(#reservation).deliver
flash[:success] = "Successfully created reservation."
redirect_to root_path
else
render 'new'
end
else
flash[:error] = "This date is reserved."
render 'new'
end
end
when you do
#reservation = Reservation.create!(reservation_params)
it will create the object and save it before your condition is checked. you should do
#reservation = Reservation.new(reservation_params)
this way it will only initialise it and not save unless your condition is met ie #check_count <= 3
and then when you do .save on it. it will be saved.
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
I have an app where I know
def new
respond_to do |format|
format.html { new_or_edit }
format.js {
#category = Category.new
}
end
end
is being called when I click a link.
This leads to new_or_edit being called (defined in the same file).
def new_or_edit
#categories = Category.find(:all)
#category = Category.find(params[:id])
#category.attributes = params[:category]
if request.post?
respond_to do |format|
format.html { save_category }
format.js do
#category.save
#article = Article.new
#article.categories << #category
return render(:partial => 'admin/content/categories')
end
end
return
end
render 'new'
end
After some tests, I find that the each execution stops at
#category = Category.find(params[:id])
with the error "Couldn't find Category without an ID". Params doesn't have an :id hash when I printed it out. Is this because I have to save it into the database before the default :id field is created?
What you are doing wrong is trying to unify two inherently different actions: new and edit.
params is a hash of parameters you get from the client.
When you create a new object, params[:id] is left blank since the id attribute of a newly created object is the responsibility of the server, not the client.
When you edit an existing object, params[:id] is not blank since the object already exists in the database and has an id. The meaning of params[:id] here is "Please edit object with id param[:id] using these attributes".
After explaining this, when you create a new object this line:
#category = Category.find(params[:id])
Fails since params[:id] is empty.