How to avoid saving after create? Rails - ruby-on-rails

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)

Related

In rails, does "if #user.save" actually save the object, or is it just a check?

Newbie question! In many controller methods, I see something like
#user.doSomething
if #user.save
#flash or redirect something
else
#flash or redirect something
In this case, is it checking whether the object has been saved, or does this save the object, then checks whether it worked?
if #user.save
This will save the object if it's valid and return
true if the #user is saved successfully
false if the #user is not saved
See the example below
#user = User.new
#user.save
#=> false
#user = User.new(email: 'foo#bar.com', password: 'foobar123')
#user.save
#=> true
You can also do something like:
def edit
#user = User.find(params[:id])
#user.assign_attributes(params[:user])
if #user.valid?
#user.save!
redirect
else
render
end
end
This will save the user if it is valid, but if it cannot be saved due to some other reason an exception is raised.

undefined local variable or method `recipient_email'

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

using redirect and if multiple times

My question is actually fairly simple, how do I make a create action which checks if a user is logged in, and if she/he is then redirect to the dashboard instead of rendering the index page where they've got links and stuff to go to and sign up. Also why is the code below not working.
class UsersController < ApplicationController
def new
#user = User.new
end
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
end
Your code isn't doing what you expect because the if statements are actually nested (you want elsif with this same structure -- or see my suggested fix below). Here's what your code, when properly formatted, actually looks like:
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
Logically, you will never get down into the second if statement, because current_user must be nil to enter the first. Try something like this instead:
def create
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
else
redirect_to dplace_index_path
end
end
I rearranged the code, but it should logically do what you want now. I put the "happy path" first (the current_user exists), and moved the redirect into the else statement.
General user authentication:
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to dashboard_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
Try:
def create
if current_user.blank? # .blank? will check both blank and nil
# logic when user is not logged in
redirect_to index_path
else
# logic when user is logged in
redirect_to dashboard_path
end
end
def create
redirect_to dplace_index_path unless current_user
# no need to check current_user again
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end

Rails: attributes not being saved even though I called #user.save

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

Authlogic with OAuth and OpenID - DoubleRenderError

I have authlogic and openid working correctly, and am trying to integrate oauth for twitter authentication. I do not want both a register and sign on button, so I have followed this example: Implicit user creation with Authlogic and Authlogic OAuth plugin
I get the DoubleRenderError on initial registration and subsequent log in, but refreshing the page lets the action complete successfully.
My users_controller create:
def create
#user = User.new(params[:user])
#user.save do |result| # LINE A
if result
flash[:notice] = "Account registered!"
redirect_to account_url
else
unless #user.oauth_token.nil?
#user = User.find_by_oauth_token(#user.oauth_token)
unless #user.nil?
UserSession.create(#user)
flash.now[:message] = "Welcome back!"
redirect_to account_url
else
redirect_back_or_default root_path
end
else
redirect_back_or_default root_path
end
end
end
end
And my user_sessions_controller create:
def create
#user_session = UserSession.new(params[:user_session])
#user_session.save do |result|
if result
flash[:notice] = "Login successful!"
redirect_back_or_default account_url
else
render :action => :new
end
end
end
Is there a way to resolve this? Thanks
After repeated failures, the following appears to work for normal authlogic username/password, OAuth with Twitter, and OpenID for at least google and yahoo, which is all I was interested in
def create
#user = User.new(params[:user])
#user.save do |result| # LINE A
if result
flash[:notice] = "Account registered!"
redirect_to account_url and return
else
if #user.oauth_token
#user = User.find_by_oauth_token(#user.oauth_token)
UserSession.create(#user)
flash.now[:message] = "Welcome back!"
redirect_to account_url and return
else
flash[:notice] = "Something went awry. Perhaps the name or email is already in use."
redirect_to register_path and return
end
end
end
end
Additionally, i added 'and return' into the update block in my users controller after both success and failure redirects/renders

Resources