Rails 3 - undefined method `last_request_at' for Assignment - ruby-on-rails

I use Authlogic for authentication users + Omniauth for social authentication.
After creating new account for user, who signed up with Facebook, I want to set up his role in the system.
user model
def self.create_user_from_facebook(auth_hash)
a = self.create!({
:facebook_uid => auth_hash["uid"],
...,
:crypted_password => "facebook",
:password_salt => "facebook",
:persistence_token => "facebook",
:provider => auth_hash["provider"]
})
puts a.errors.inspect #returns no errors, record is successfully saved
puts a.inspect # returns: last_request_at: "2012-10-01 08:12:51"
Assignment.create(:user_id => user.id, :role_id => 2)
end
And when I try to add new record into assignments table this way, I get the error
undefined method `last_request_at' for #<Assignment:0x0000012a1539e0>
The column last_request_at is in the table users.
How does the column last_request_at from the table users relate with the table assignments? (with only these two columns: role_id, user_id)?
**EDIT** another information:
class UserOauthController < ApplicationController
def create
#current_user = User.find_or_create_from_oauth(auth_hash)
if current_user
UserSession.create(current_user, true)
flash[:success] = 'Successfully logged in.'
redirect_to root_url
else
flash[:warning] = 'Authorization ERROR! Please, try it again.'
redirect_to root_url
end
end
end
class User < ActiveRecord::Base
attr_accessible list of atteibutes
acts_as_authentic do |c|
authlogic set up
end
...validations...
def self.find_or_create_from_oauth(auth_hash)
provider = auth_hash["provider"]
uid = auth_hash["uid"].to_s
case provider
when 'facebook'
if user = self.where('email = ? and provider = ?', auth_hash["info"]["email"], provider).first
return user
elsif user = self.find_by_facebook_uid(uid)
return user
else
return self.create_user_from_facebook(auth_hash)
end
end
def self.create_user_from_facebook(auth_hash)
a = self.create!({
:facebook_uid => auth_hash["uid"],
...,
:crypted_password => "facebook",
:password_salt => "facebook",
:persistence_token => "facebook",
:provider => auth_hash["provider"]
})
puts a.errors.inspect
puts a.inspect
a.assignments.create(:role_id => MEMBER)
end
end
How can I fix it?

Related

Rails Stripe Retrieve ID Error "No such plan"

So my Plan says Stripe::InvalidRequestError at /orders/26/payments
No such plan: The title of my plan.
This code should check if the the plan already exists and if not create it and subscribe the user to it. I thought this worked because it was working for the case where I already had a plan with the same ID and it said "Plan already exists". How can I prevent this Error from happening?
This is my code:
class PaymentsController < ApplicationController
before_action :set_order
def new
end
def create
#user = current_user
customer = Stripe::Customer.create(
source: params[:stripeToken],
email: params[:stripeEmail],
)
# Storing the customer.id in the customer_id field of user
#user.customer_id = customer.id
#plan = Stripe::Plan.retrieve(#order.service.title)
unless #plan
plan = Stripe::Plan.create(
:name => #order.service.title,
:id => #order.service.title,
:interval => "month",
:currency => #order.amount.currency,
:amount => #order.amount_pennies,
)
else
subscription = Stripe::Subscription.create(
:customer => #user.customer_id,
:plan => #order.service.title
)
end
#order.update(payment: plan.to_json, state: 'paid')
redirect_to order_path(#order)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_order_payment_path(#order)
end
private
def set_order
#order = Order.where(state: 'pending').find(params[:order_id])
end
end
The documentation says that if you try to retrieve a plan that does not exist, it will raise an error. So you just need to catch the error:
begin
#plan = Stripe::Plan.retrieve(#order.service.title)
rescue
#plan = Stripe::Plan.create(...)
end
Little bit improved version. It's sad that there is no way to check if plan exists and you have to rely on exception swallowing it. Here is my version, it tries to retrieve the plan, if error is 404, it creates the plan. Otherwise, lets exception to pop up. So it won't swallow all of the exceptions, which is important IMO when you work with finance API.
def retrieve_or_create_plan(id)
begin
Stripe::Plan.retrieve(id)
rescue Stripe::InvalidRequestError => e
if e.response.http_status == 404
Stripe::Plan.create(
name: 'Your plan name',
id: id,
interval: :month,
currency: :usd,
amount: 100
)
else
raise e
end
end
end

How do you get recurring PaypalExpress payments to work with Active Merchant in Rails 4?

I'm using Active Merchant to try to implement recurring payments in the PaypalExpressCheckout module, but I keep on getting this error:
"message"=>"The token is invalid", "error_codes"=>"11502"
The token is being properly returned and set and now I'm speculating the problem maybe because the Active Merchant gem was not written for PaypalExpress to work with recurring payments, but after looking at the documentation there are methods included from the PaypalRecurringApi that can be used in the PaypalExpress module.
This is the relevant code that is causing the problem.
In my paypal_subscriptions_controller.rb:
def create
#subscription = PaypalSubscription.new(subscription_params)
if #subscription.save
if #subscription.subscribe_with_paypal
render "success"
else
render "failure"
end
else
render :new
end
end
private
def subscription_params
params.require(:paypal_subscription).permit(:express_token,:payer_id,:email,:first_name,:last_name,:amount,:plan_id)
end
And the relevant code in my model PaypalSubscription.rb:
def express_token=(token)
write_attribute(:express_token, token)
if new_record? && !token.blank?
details = EXPRESS_GATEWAY.details_for(token)
self.email = details.params["email"]
self.payer_id = details.payer_id
self.profile_id = details.params["profile_id"]
self.first_name = details.params["first_name"]
self.last_name = details.params["last_name"]
self.amount = details.params["amount"]
end
end
def subscribe_with_paypal
response = process_purchase
Rails.logger.info response.inspect
response.success?
end
def process_purchase
EXPRESS_GATEWAY.recurring(amount, nil,{
:ip => ip_address,
:token => express_token,
:payer_id => payer_id,
:period => "Month",
:frequency => 3,
:start_date => Time.now,
:description => "Checking recurring auto-renewal"
})
end
If anyone could help me on this on that'd be great! Thanks

User Registration with Devise and Paypal

I want to integrate Paypal within the Devise user registration process. What I want is to have a standard rails form based on the devise resource, that also has custom fields belonging to the user's model.
When a user fills in those fields and clicks on signup, it will be redirected to Paypal, when he clears from paypal and returns to our site then the user data must be created.
For the scenario where the user fill's out the paypal form but doesn't come back to our site, we have to keep record of user before redirecting to Paypal.
For this we can create a flag in user model and use Paypal IPN and when the user transaction notified, set that flag.
But in the case when the user is redirected to Paypal but doesn't complete the transaction, if the user returns to registration and signup again, our model should not throw error saying that the email entered already exists in the table.
How can we handle all these scenarios, is there any gem or plugin available to work with?
Here i am posting the detail code for performing the whole process.
registration_controller.rb
module Auth
class RegistrationController < Devise::RegistrationsController
include Auth::RegistrationHelper
def create
#user = User.new params[:user]
if #user.valid?
redirect_to get_subscribe_url(#user, request)
else
super
end
end
end
end
registration_helper.rb
module Auth::RegistrationHelper
def get_subscribe_url(user, request)
url = Rails.env == "production" ? "https://www.paypal.com/cgi-bin/webscr/?" : "https://www.sandbox.paypal.com/cgi-bin/webscr/?"
url + {
:ip => request.remote_ip,
:cmd => '_s-xclick',
:hosted_button_id => (Rails.env == "production" ? "ID_FOR_BUTTON" : "ID_FOR_BUTTON"),
:return_url => root_url,
:cancel_return_url => root_url,
:notify_url => payment_notifications_create_url,
:allow_note => true,
:custom => Base64.encode64("#{user.email}|#{user.organization_type_id}|#{user.password}")
}.to_query
end
end
payment_notification_controller.rb
class PaymentNotificationsController < ApplicationController
protect_from_forgery :except => [:create]
layout "single_column", :only => :show
def create
#notification = PaymentNotification.new
#notification.transaction_id = params[:ipn_track_id]
#notification.params = params
#notification.status = "paid"
#custom = Base64.decode64(params[:custom])
#custom = #custom.split("|")
#user = User.new
#user.email = #custom[0]
#user.organization_type_id = #custom[1].to_i
#user.password = #custom[2]
if #user.valid?
#user.save
#notification.user = #user
#notification.save
#user.send_confirmation_instructions
end
render :nothing => true
end
def show
end
end

Rails: retrieving image from Facebook after Omniauth login with Devise

I setup Facebook login with Devise and omniauth with these instructions https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
The Devise wiki gives some instructions for getting facebook info from the hash stored in this variable request.env['omniauth.auth'] See bottom for the hash.
For example, Devise wiki has these two methods for the User.rb model
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"]
end
end
end
So, using the hash below, I added the following to those two methods to get the name and image
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20], :name => data.name, :image => access_token.info.image) #I added access_token.info.image based on first answer
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"]
user.name = data["name"]
user.image = access_token.info.image #i changed this based on first answer below
end
end
end
Then in my view, I added the following to show the user name and image
<p>Name:<%= user.name %></p>
<p>Image: <%= image_tag user.image %>
However, only the name is showing. No image.
In my database, I have a name and an image column. The name from Facebook is being stored, but the image column says 'nil'
Any ideas how I can get the image to work?
Hash stored in request.env['omniauth.auth'] https://github.com/mkdynamic/omniauth-facebook/blob/master/lib/omniauth/strategies/facebook.rb#L31-47
info do
prune!({
'nickname' => raw_info['username'],
'email' => raw_info['email'],
'name' => raw_info['name'],
'first_name' => raw_info['first_name'],
'last_name' => raw_info['last_name'],
'image' => "#{options[:secure_image_url] ? 'https' : 'http'}://graph.facebook.com/#{uid}/picture?type=square",
'description' => raw_info['bio'],
'urls' => {
'Facebook' => raw_info['link'],
'Website' => raw_info['website']
},
'location' => (raw_info['location'] || {})['name'],
'verified' => raw_info['verified']
})
end
The image can be found at env["omniauth.auth"]["info"]["image"]. So in your case, access_token.info.image.
If you want to take a good look at the hash of nested hashes returned and see for yourself where everything is, put this as the first line of your callback controller:
render :text => "<pre>" + env["omniauth.auth"].to_yaml and return
EDIT: Ok, so here's what you need to do:
def self.find_for_facebook_oauth(omniauth)
if user = User.find_by_email(omniauth.info.email)
if omniauth.info.image.present?
user.update_attribute(:image, omniauth.info.image)
end
user
else # Create a user with a stub password.
User.create!(:email => omniauth.info.email,
:name => omniauth.info.name,
:image => omniauth.info.image,
:password => Devise.friendly_token[0,20])
end
end
As for the other method, if I'm not mistaken, it should look like this:
def self.new_with_session(params, session)
super.tap do |user|
if omniauth = session["devise.facebook_data"]
user.email = omniauth.info.email
user.name = omniauth.info.name
user.image = omniauth.info.image
end
end
end
But when is this method used? It's used by Devise when something goes wrong when creating your user. Imagine that the authentication provider doesn't give you an email (Twitter, for example, does this), what can you do? Well, you can redirect the user to your sign up page where he can complete the signup process. But if you redirect the user, you lose the data received by the oauth. The solution is to put this data into the session.
So in your controller, you should have something like:
if user.save
sign_in_and_redirect user, :event => :authentication
else
session["devise.facebook_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
Another problem, however, is that most of the times the data returned by the authentication provider is too big to fit in the session, so we have to pick exactly what we want to put in the session. Since you are only getting a name and an image, you can trim the extra info like so:
session["devise.facebook_data"] = env["omniauth.auth"].except('extra')

Authlogic Create new session without password

I'm trying to build Facebook OAuth into my existing Authlogic login system. I have the OAuth part complete, and stored the facebook access_token. The problem I'm facing is to actually log the user in (create a session) without the user typing in their password.
#facebook's OAuth callback
def callback
access_token = client.web_server.get_access_token(params[:code], :redirect_uri => redirect_uri)
fb_user = JSON.parse(access_token.get('/me'))
#user = User.find_by_facebook_id(fb_user["id"]) || User.find_by_email(fb_user["email"]) || User.new
#user.update_attributes({
:facebook_id => fb_user["id"],
:first_name => fb_user["first_name"],
:last_name => fb_user["last_name"],
:gender => fb_user["gender"],
:email => fb_user["email"],
:timezone => fb_user["timezone"],
:locale => fb_user["locale"],
:facebook_url => fb_user["link"],
:facebook_access_token => access_token.token
}) #unless #user.updated_at < 2.days.ago
# TODO: set current_user
# Maybe something like this?
# #user_session = UserSession.new({
# :remember_me => true,
# :password =>"[FILTERED]",
# :email => email
# }).save
flash[:success] = "Welcome, #{#user.name}"
redirect_to :root
end
Nevermind I figured it out. It was in the README the whole time.
UserSession.new(#user, true) //true = persistent session

Resources