Rails controller method executes code in both the "if" and "else" statement - ruby-on-rails

I have a friendship model that allows users to become friends in my Rails app. It stores the following data:
friendship_id (int), sender_id (int), receiver_id (int), sent_at (datetime), accepted (boolean), accepted_at (datetime)
The following controller method is for adding friends
def addfriend
if user_signed_in?
#sender = params[:sender]
#receiver = params[:receiver]
if Friendship.find_by(sender_id: #sender, receiver_id: #receiver).nil? &&
Friendship.find_by(sender_id: #receiver, receiver_id: #sender).nil?
#friend = Friendship.create(friendship_id: 0, sender_id: #sender, receiver_id: #receiver, sent_at: DateTime.now, accepted: false)
if #friend.save
flash[:success] = "Friend request sent"
redirect_to root_path
else
flash[:error] = "Oops, something went wrong."
redirect_to root_path
end
else
flash[:notice] = "Already friends with this person or friendship pending acceptance."
redirect_to root_path
end
end
end
What happens is the friend request gets sent, it will be there in the database and when I switch to the other user the request will be there, but the notification that pops up after the request was sent and the page reloads says "Already friends with this person or friendship pending acceptance." As if the request wasn't actually sent, even though it was. This even happens when all Friendships have been deleted in the database.
Any thoughts as to why this is happening? I want it to say "Friend request sent" when it does get sent, rather than what it is saying now.

redirect_to doesn't return from the method and continues the execution.
You need to do:
redirect_to root_path and return
or:
return redirect_to root_path

Try this
redirect_to :controller =>… , :action=>….
for example
def update
#tip = current_user.tips.find(params[:id])
#tip.attributes = params[:tip]
#tip.category_ids = params[:categories]
#tip.tag_with(params[:tags]) if params[:tags]
if #tip.save
flash[:notice] = 'Tip was successfully updated.'
redirect_to :controller=>'tips', :action => 'show', :id => #tip.permalink
else
render :action => 'edit'
end
end

Related

Booking Process Issues - Stripe and Rails

OK, I have been trying to find the issue for the past 2 hours.. For some reason my bookings don't come through, not even notifications appear on the page.
When I click BOOK NOW, the page reloads and doesn't give me any errors, so not sure what am I doing wrong.
I'm adding the stripe to the booking path step by step. The BOOK NOW button was working fine on its own before, but now that I aded the card charges to it - it doesn't.
Any help is very welcome! Happy to provide additional information, if needed.
Thank you
Reservations Controller
def create
room = Room.find(params[:room_id])
if current_user.stripe_id.blank?
flash[:alert] = "Please update your payment method."
return redirect_to payment_method_path
#reservation = current_user.reservations.build
#reservation.room = room
#reservation.price = room.price
#reservation.total = room.price * days
if #reservation.Waiting!
if room.Request?
flash[:notice] = "Request sent succesfully"
else
charge(room, #reservation)
end
else
flash[:alert] = "Cannot make a reservation"
end
end
redirect_to room
end
def your_trips
#rooms = current_user.rooms
end
def aprove
charge(#reservation, room, #reservation)
redirect_to your_trips_path
end
def decline
#reservation.Declined!
redirect_to your_trips_path
end
Reservations Controller - private
private
def set_reservation
#reservation = Reservation.find(params[:id])
end
def charge(room, reservation)
if !reservation.user.stripe_id.blank?
customer = Stripe::Customer.retrieve(reservation.user.stripe_id)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => reservation.price,
:description => room.overview,
:currency => "usd"
)
if charge
reservation.Approved!
flash[:notice] = "Reservation created successfully!"
else
reservation.Declined!
flash[:alert] = "Cannot charge with this payment method!"
end
end
rescue Stripe::CardError => e
reservation.declined!
flash[:alert] = e.message
end
After checking current_user.stripe_id.blank? it looks like you are unintentionally returning all requests.
I would try this:
if current_user.stripe_id.blank?
flash[:alert] = "Please update your payment method."
redirect_to payment_method_path and return
end
If your model code depends on the record being saved before calling Waiting!, keep in mind that #reservation = current_user.reservations.build does not save the record.
The rescue block in your charge method also appears to be out of scope. That could be refactored into a begin-rescue-end block within the first if.
And if you aren't seeing notifications on the page, make sure your layout displays :notice and :alert somewhere.

Fixing a Double Render Error when creating more than one object with one request

Right now I have a controller action that takes in an array. It iterates through the array and should make a new object of each element in the array. But when I attempt this now I get a double render error? Anyone know how I can fix this?
Controller
def create
params[:emails].each do |email|
# Ignore if the user is already on the account.
if current_account.users.exists?(email: email) || current_account.invitations.exists?(email: email)
flash[:alert] = "#{email} is already on the team"
redirect_to account_users_path
return
end
invitation = Invitation.new({
account: current_account,
inviter: current_user,
email: email,
})
if invitation.save
Notifier.invite(invitation).deliver_later
else
flash[:alert] = "Email is invalid"
end
redirect_to account_users_path
end
end
As you can see I iterate over the emails and try to make a new object out of each. But right now I get this error.
AbstractController::DoubleRenderError in Accounts::InvitationsController#create
Move the redirect_to call outside the loop:
def create
params[:emails].each do |email|
# Ignore if the user is already on the account.
if current_account.users.exists?(email: email) || current_account.invitations.exists?(email: email)
flash[:alert] = "#{email} is already on the team"
redirect_to account_users_path
return
end
invitation = Invitation.new({
account: current_account,
inviter: current_user,
email: email,
})
if invitation.save
Notifier.invite(invitation).deliver_later
else
flash[:alert] = "Email is invalid"
end
end
redirect_to account_users_path
end

using merge in strong params, NilClass error

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

Rails Controller Def Create Redirect to URL upon Save

def create
#purchase = Purchase.new(params[:purchase])
if session[:purchase_id] != #purchase.save
redirect_to(#purchase, :notice => "Thank you. You good lookin person you.")
end
end
I'm trying to either
A - Redirect to a URL, or other controllers path, or
B - refresh the form they ordered from (the new_purchases_path) and flash :notice the user that their purchase was successful. When I try to add a Url (that would be a thank you message page) i get syntax errors. This code redirects the user to the index list (which is inaccesible to them)
If I take out the def create, it by default flashes a notice and shows them their completed form. I'm using simple_form and I'm not sure how to override those defaults. Any suggestions on at least redirecting to a url?
Examples:
A - Redirect to a URL, or other controllers path
redirect_to :action => "show", :id => 5
redirect_to "http://www.rubyonrails.org"
redirect_to new_purchases_path
redirect_to purchases_url
redirect_to :back
B - refresh the form they ordered from (the new_purchases_path)
render :action => "new"
Edit:
Here a general example with flash messages:
if #foo.save
redirect_to foos_path, :notice => "Foo saved"
else
flash[:notice] = "Some errors occured"
render :action => "new"
end
here is an example of a create method i made today
def create
#book = Book.new(params[:book])
if #book.save
redirect_to searchbook_path, notice: 'Book was successfully saved'
else
render :action => 'results'
end
end
So in your case you could maybe try this
def create
#purchase = Purchase.new(params[:purchase])
if #purchase.save
redirect_to purchase_path, :notice 'Thanks for your purchase'
else
render :action => 'new'
end
end
This is assuming that you have a purchase and new path... Though it would help if you could let us know what errors you are getting

Rails Optional Sign Up - Changing Params Before Saving

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)

Resources