undefined method `persisted?' for true:TrueClass - ruby-on-rails

Im getting this error and im not sure why. There are similar problems like this that couldnt solve my case.
could be from user = User.where(:email => auth.info.email).first
could be from where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
or even on the persisted? part in the omniauth_controller
What could be the possible options or solutions to this error?? thank you!! ^^
Omniauth_controller: where persisted? error takes place at.
def facebook
puts "1111111111 yayayay"
# raise request.env["omniauth.params"].inspect
user = User.from_omniauth((request.env["omniauth.auth"]), (request.env["omniauth.params"]), (request.remote_ip))
if user.persisted?
puts "3333333 okayay"
sign_in_and_redirect #user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
puts "wtf wtf wtf wtf wtf"
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
User Model where i create stripe verification and facebook omniauth.
#gathering the info from social media when making an account.
def self.from_omniauth(auth, auth_params, request)
anonymous_username = "NewUser#{User.last.id + 100}"
generated_password = Devise.friendly_token[0,20]
user = User.where(:email => auth.info.email).first
puts "auth params are #{auth_params}"
puts "user type is #{auth_params["user_type"]}"
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.confirmed_at = Time.now
user.fullname = auth.info.name
user.provider = auth.provider
user.user_type = auth_params["user_type"]
user.uid = auth.uid
user.username = anonymous_username
user.email = auth.info.email
if auth.info.image.present?
avatar_url = process_uri(auth.info.image)
user.avatar = URI.parse(avatar_url)
end
user.password = generated_password
user.save
user
end
#reviser account creation
user = User.where(:email => auth.info.email).first
puts "before the if #{user} and #{user.user_type}"
if user.user_type == 'reviser'
puts 'this is reviser starting to create account'
require "stripe"
email = auth.info.email
begin
Stripe.api_key = ENV['STRIPE_SECRET_KEY']
account = Stripe::Account.create(
{
:country => 'US',
:managed => true,
:tos_acceptance => {
:date => Time.now.to_i,
:ip => request
},
:transfer_schedule => {
:interval => 'manual'
},
:email => email,
:legal_entity => {
:type => 'individual'
}
}
)
verification = Verification.create!(
user_id: user.id,
country: 'US',
email: email,
terms_of_service: true
)
puts "success!1: #{account.id}"
puts "success!4: #{account.keys.secret}"
puts "success!5: #{account.keys.publishable}"
verification.update_attributes account_id: account.id
rescue Stripe::InvalidRequestError => e
if e.message == "An account with this email already exists."
redirect_to stripe_path, alert: "An account with this email already exists."
else
puts "#{e.message}"
flash[:error]= e.message
end
rescue Stripe::AuthenticationError => e
redirect_to stripe_path, alert: "oops! Please let us know about this error! Please Try Again Later!"
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
rescue Stripe::APIConnectionError => e
redirect_to stripe_path, alert: "oops! Something went wrong! Please Try Again!"
# Network communication with Stripe failed
rescue Stripe::StripeError => e
redirect_to stripe_path, alert: "oops! Something went wrong! Please Try Again!"
# Display a very generic error to the user, and maybe send
# yourself an email
end
end
end
end

Your method from_omniauth is returning true because of the line user.save. Return a user at the end like:
def self.from_omniauth(auth, auth_params, request)
anonymous_username = "NewUser#{User.last.id + 100}"
generated_password = Devise.friendly_token[0,20]
user = User.where(:email => auth.info.email).first
puts "auth params are #{auth_params}"
puts "user type is #{auth_params["user_type"]}"
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.confirmed_at = Time.now
user.fullname = auth.info.name
user.provider = auth.provider
user.user_type = auth_params["user_type"]
user.uid = auth.uid
user.username = anonymous_username
user.email = auth.info.email
if auth.info.image.present?
avatar_url = process_uri(auth.info.image)
user.avatar = URI.parse(avatar_url)
end
user.password = generated_password
user.save
end
#reviser account creation
user = User.where(:email => auth.info.email).first
puts "before the if #{user} and #{user.user_type}"
if user.user_type == 'reviser'
puts 'this is reviser starting to create account'
require "stripe"
email = auth.info.email
begin
Stripe.api_key = ENV['STRIPE_SECRET_KEY']
account = Stripe::Account.create(
{
:country => 'US',
:managed => true,
:tos_acceptance => {
:date => Time.now.to_i,
:ip => request
},
:transfer_schedule => {
:interval => 'manual'
},
:email => email,
:legal_entity => {
:type => 'individual'
}
}
)
verification = Verification.create!(
user_id: user.id,
country: 'US',
email: email,
terms_of_service: true
)
puts "success!1: #{account.id}"
puts "success!4: #{account.keys.secret}"
puts "success!5: #{account.keys.publishable}"
verification.update_attributes account_id: account.id
rescue Stripe::InvalidRequestError => e
if e.message == "An account with this email already exists."
redirect_to stripe_path, alert: "An account with this email already exists."
else
puts "#{e.message}"
flash[:error]= e.message
end
rescue Stripe::AuthenticationError => e
redirect_to stripe_path, alert: "oops! Please let us know about this error! Please Try Again Later!"
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
rescue Stripe::APIConnectionError => e
redirect_to stripe_path, alert: "oops! Something went wrong! Please Try Again!"
# Network communication with Stripe failed
rescue Stripe::StripeError => e
redirect_to stripe_path, alert: "oops! Something went wrong! Please Try Again!"
# Display a very generic error to the user, and maybe send
# yourself an email
end
end
user
end
end

Related

How to find user by email and if not, redirect him to register page

I use Omniauth and Omniauth-facebook gems and I want to click on button, if user is found, then sign him in. If not, redirect him to register page.
So far I use just classic login/register:
user.rb:
def self.from_omniauth(auth, role)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
if user
return user
else
registered_user = User.where(:email => auth.info.email).first
if registered_user
registered_user.provider = auth.provider
return registered_user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
if (role == "1")
user.add_role :sportsman
elsif (role == "2")
user.add_role :donor
end
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
end
end
omniauth_callbacks_controller.rb:
def facebook
role = cookies[:role]
# signin = cookies[:signin]
user = User.from_omniauth(request.env["omniauth.auth"], role)
if user.persisted?
flash.notice = "Signed by Facebooku"
sign_in_and_redirect user
else
flash.notice = "Error, try again."
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
This code works, but if user is not registered, it will register him. But I sign roles when user register himself.
Thanks for help.
Because you are already saving the user attributes into the session with
session["devise.user_attributes"] = user.attributes
Then the following should already work:
def self.from_omniauth(auth, role)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
if user
return user
else
# NOTE: because you're searching "email" and not both "email" + "provider", then I assume
# that you want users to have only one shared account between all providers (i.e. if they also sign-in in Google with the exact email as his email in Facebook)
registered_user = User.where(:email => auth.info.email).first
if registered_user
# NOTE: this line doesn't do anything because registered_user is not being "saved"
registered_user.provider = auth.provider
return registered_user
else
# build a new User object (don't save yet!)
return User.new.tap do |u|
u.provider = auth.provider
u.email = auth.info.email
u.uid = uid: auth.uid
u.password = Devise.friendly_token[0,20]
# because I assume you're using "rolify" gem, don't add the roles yet here, because I don't think you can store the "roles" into the session
# add the roles logic in whatever controller you have for user registration
end
end
end
end
Then override new_with_session in your user model. new_with_session is automatically called by Devise in registrations#new. We need to set the
user attributes that we previously stored in session inside omniauth_callbacks#facebook
class User < ApplicationRecord
def self.new_with_session(params, session)
super.tap do |user|
if user_attributes = session['devise.user_attributes']
user.assign(user_attributes)
end
end
end
end
So I used simple params to get where the user come from:
<script type="text/javascript">
document.cookie = "login=0"
</script>
This code is in views/devise/registrations/new.html.erb (and in views/devise/sessions/new.html.erb) and it is a JavaScript. It tells me if user went from login page (sessions folder - login=1) or from registration page (registrations folder - login=0). Then I use this code to determinate if user is from login page AND if he is not registered yet. If both conditions are true, then he is redirected to register page. It is so simple that I am embarrassed...
def facebook
hash = request.env["omniauth.auth"]
info = hash.info
email = info["email"]
user = User.find_by_email(email)
login = cookies[:login]
if (user == nil && login == "1")
redirect_to new_user_registration_path
else
role = cookies[:role]
user = User.from_omniauth(request.env["omniauth.auth"], role)
if user.persisted?
flash.notice = "Logged in by Facebook"
sign_in_and_redirect user
else
flash.notice = "Error, try again."
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
end

Rails, Omniauth: NoMethodError - undefined method `persisted?'

I am using the omniauth-stripe-connect gem and get the following error when authenticating users:
NoMethodError in Users::OmniauthCallbacksController#stripe_connect
undefined method `persisted?' for nil:NilClass
My Callbacks Controller Action:
def stripe_connect
#user = UserProvider.find_for_stripe_oauth(request.env["omniauth.auth"])
if #user.persisted? # here is the issue !!!
sign_in #user, :event => :authentication
redirect_to root_path
end
end
And my User Method:
def self.find_for_stripe_oauth(auth)
user = UserProvider.where(:provider => auth.provider, :uid => auth.uid).first
unless user.nil?
user.user
else
registered_user = User.where(:email => auth.info.email).first
unless registered_user.nil?
user_provider = UserProvider.new
user_provider.provider = auth.provider
user_provider.uid = auth.uid
user_provider.user_id = registered_user.id
user_provider.save!
registered_user.stripe_access_code = auth.credentials.token
registered_user.stripe_publishable_key = auth.info.stripe_publishable_key
registered_user.stripe_id = auth.extra.raw_info.stripe_user_id
registered_user.skip_confirmation!
registered_user.save!
registered_user
end
end
end
What am I doing wrong?
find_for_stripe_oauth returns nil if registered_user is not exists. In this case unless registered_user.nil? returns false and inner block is not executed.
Move out registered_user, like this:
registered_user = User.where(:email => auth.info.email).first
unless registered_user.nil?
user_provider = UserProvider.new
user_provider.provider = auth.provider
user_provider.uid = auth.uid
user_provider.user_id = registered_user.id
user_provider.save!
registered_user.stripe_access_code = auth.credentials.token
registered_user.stripe_publishable_key = auth.info.stripe_publishable_key
registered_user.stripe_id = auth.extra.raw_info.stripe_user_id
registered_user.skip_confirmation!
registered_user.save!
end
registered_user

Active Merchant paypal recurring payments

I am using Active Merchant gem to handle payments through the site. But now i want to make these payments recurring, on a monthly basis. Is there a way using active merchant or?
subscription_controller.rb
class SubscriptionsController < ApplicationController
def new
#home_page = true
#white = true
#subscription = Subscription.new(token: params[:token])
if !logged_in?
redirect_to signup_url
end
end
def create
#subscription = Subscription.new(subscription_params)
#subscription.remote_ip = request.remote_ip
#subscription.user_id = current_user.id
if #subscription.save
if #subscription.purchase
#subscription.send_thank_you_email
redirect_to thankyou_path
else
raise ActiveRecord::Rollback
flash[:notice] = "It seems something went wrong with the paypal transaction. Please check that your credit card is valid and has credit in it and try again."
redirect_to :back
end
else
flash[:notice] = "Something went wrong with marking your purchase as complete. Please contact support to check it out."
redirect_to :back
end
end
def purchase
response = GATEWAY.setup_purchase(999,
ip: request.remote_ip,
return_url: new_subscription_url,
cancel_return_url: root_url,
currency: "USD",
items: [{name: "Order", description: "Recurring payment for ******", quantity: "1", amount: 999}]
)
redirect_to GATEWAY.redirect_url_for(response.token)
end
def thank_you
#home_page = true
#white = true
end
private
def subscription_params
params.require(:subscription).permit(:token)
end
end
subscription.rb model
def purchase
response = GATEWAY.purchase(999, express_purchase_options)
response.success?
end
def token=(token)
self[:token] = token
if new_record? && !token.blank?
# you can dump details var if you need more info from buyer
details = GATEWAY.details_for(token)
puts details.params["PayerInfo"]["PayerName"].inspect
self.payer_id = details.payer_id
self.first_name = details.params["PayerInfo"]["PayerName"]["FirstName"]
self.last_name = details.params["PayerInfo"]["PayerName"]["LastName"]
end
end
# send thank you email
def send_thank_you_email
UserMailer.thank_you(self).deliver_now
end
private
def express_purchase_options
{
:ip => remote_ip,
:token => token,
:payer_id => payer_id
}
end
production.rb environment
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :production
::GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(
:login => ENV['PAYPAL_LOGIN'],
:password => ENV['PAYPAL_PASSWORD'],
:signature => ENV['PAYPAL_SIGNATURE']
)
end
I think ActiveMerchant used to have something like this:
subscription = PAYPAL_EXPRESS_GATEWAY.recurring(#subscription.price_in_cents, nil,
:description => 'blah',
:start_date => Date.tomorrow,
:period => 'Year',
:frequency => 1,
:amount => price,
:currency => 'USD'
)
See this answer Does ActiveMerchant support Subscription Based transaction
Also see this: https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/paypal_express.rb
https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb

NoMethodError undefined method `persisted?' for nil:NilClass when signing in with Facebook thru Omniauth/Devise?

I am putting the finishing touches on a Rails app, and everything was working fine just yesterday, (most of it still is). But now, when I try to sign in with Facebook I get the error NoMethodError undefined method persisted? for nil:NilClass I haven't changed any code in the omniauth_callbacks_controller, or in the User Model, so I do not understand why this is happening all of the sudden.
Here's the code in omniauth_callbacks_controller
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
#user = User.from_omniauth(env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:twitter, :facebook].each do |provider|
provides_callback_for provider
end
And in User.rb
def self.from_omniauth(auth)
identity = Identity.where(provider: auth.provider, uid: auth.uid).first_or_create do |identity|
if identity.user == nil
user = User.new
user.email = auth.info.email || "#{auth.uid}##{auth.provider}.generated"
user.password = Devise.friendly_token[0,20]
user.provider = auth.provider
if auth.provider == "facebook"
user.name = auth.info.name
user.username = "FacebookUser" + (1 + rand(1000)).to_s
elsif auth.provider == "twitter"
user.name = auth.info.name
user.username = auth.info.nickname
end
end
identity.user = user
end
identity.access_token = auth['credentials']['token']
identity.refresh_token = auth['credentials']['refresh_token']
identity.expires_at = auth['credentials']['expires_at']
identity.timezone = auth['info']['timezone']
identity.save
identity.user
end
I cannot figure out why it WAS working yesterday, but now it's not. Nothing has changed! I'm still accessing it from the same URL, I haven't messed with the API settings on Facebook, or in devise.rb.
the problem is that identity.user is nill. It could happen, because user not valid(not saved in db), in user model did not pass validations.
I think problem can be in user.email = auth.info.email || "#{auth.uid}##{auth.provider}.generated" - wrong email type. You can add something like puts user.errors in block wehe you created user.
Also i don't understand why you need a model - identity. Much easier add field to user model
Here is my code(it's work):
def self.from_omniauth(auth)
email = auth.info.email
user = User.find_by(email: email) if email
user ||= User.create do |user|
user.provider= auth.provider
user.uid= auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name
user.email ||= "#{auth.uid}_#{auth.uid}#email.com"
end
end

How to send email to user after payment is done with paypal

I want to sent email to user after transcation done. now paypal is working fine for me, but user is not getting mail notification after transcation done? how to get email notification for user .
Here is my code
This is my controller code
This is my paypal function
def pay
if #order.update order_params
#order.update_attributes(:invoice_id => rand.to_s[2..11])
if current_user.billing_address.blank?
current_user.create_billing_address(#order.billing_address.dup.attributes)
end
if current_user.shipping_address.blank?
current_user.create_shipping_address(#order.shipping_address.dup.attributes)
end
# #cart.calculate_shipping
if #order.total == 0
return redirect_to checkout_thank_you_path
end
# if !params['payment'].present?
# return redirect_to :back, notice: 'Select Payment Gateway!'
# end
# if params['payment']=='paypal'
#order.order_statuses.create(status_type: 1)
item_details=[]
#order.line_items.each do |item|
item_details << {:name => item.title, :quantity => item.quantity, :amount => item.amount.fractional}
end
logger.info item_details.inspect
response = EXPRESS_GATEWAY.setup_purchase(#cart.total.fractional,
:ip => request.remote_ip,
:currency =>"USD",
:items => item_details,
:order_id => #order.invoice_id,
:return_url => checkout_thank_you_url,
:cancel_return_url => cart_url
)
return redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
# else
# return redirect_to 'https://www.payumoney.com/'
# end
else
flash[:alert] = 'Billing and shipping address fields are required!'
render :addresses
end
end
This is my thank function for paypal
def thank_you
#order = Order.find(session[:order_id])
details = EXPRESS_GATEWAY.details_for(params[:token])
response = EXPRESS_GATEWAY.purchase(#cart.total.fractional, {
ip: request.remote_ip,
token: params[:token],
payer_id: details.payer_id,
items: #order.line_items.map{|l| {name: l.title, quantity: l.quantity, amount: l.amount.fractional}}
})
if response.success?
# logger.info payment_params.inspect
payment_params = {gateway: 'PayPal Express Checkout', transaction_id: response.params['token'], ip: request.remote_ip, amount: response.params['gross_amount']}
#cart.order.created_at = DateTime.now
#cart.order.status = 'Paid'
#cart.order.save
session.delete :order_id
# OrderMailer.order_confirmation(#order).deliver
# OrderMailer.admin_receipt(#order).deliver
else
redirect_to :cart_checkout, alert: 'Something went wrong. Please try again. If the problem persists, please contact us.'
end
#cart = Cart.new current_or_null_user.id, session[:order_id], session[:currency] # Start a new cart
end
Any help is appreciatable

Resources