Rails: Using OmniAuth (FB authorization), Reading Data From Facebook Hash - ruby-on-rails

Using OmniAuth, I successfully fetched the hash data from Facebook: stored in "auth"
# extra=#] last_name="Jordan" link="http://www.facebook.com/michael" locale="en_US" middle_name="Ball" name="Michael Jordan" quotes="\"lalala\"\n\n\"lala\"" timezone=9 updated_time="2011-09-01T20:25:58+0000" username="mjordan82" verified=true>> info=# verified=true> provider="facebook" uid="123456879">
In User Model, I do as follows:
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth["provider"]
user.uid = auth["uid"]
user.name = auth["name"]
end
end
When I checked the database, I only got provider and uid. User.name row was empty. From testing, I figured out I couldn't store other data than provider and uid. For example, user.name = auth["provider"] or user.name = auth["uid"] stored with no problem, but when I tried something like user.name = auth["timezone"] or user.name = auth["last_name"], nothing was stored in the variable. Anyone know how to fix this? I also tried user.name = auth["user_info"]["name"], but it returned an error.
I am not sure why user.name = auth["name"] does not store anything. In other words, why is auth["name"] not "Michael Jordan" in this case?

The key was this: I was accessing the auth hash in a wrong way. The answer is you do
user.name = auth["info"]["name"]
Here's detailed information about the Auth Hash:
:provider => 'facebook',
:uid => '1234567',
:info => {
:nickname => 'jbloggs',
:email => 'joe#bloggs.com',
:name => 'Joe Bloggs',
:first_name => 'Joe',
:last_name => 'Bloggs',
:image => 'http://graph.facebook.com/1234567/picture?type=square',
:urls => { :Facebook => 'http://www.facebook.com/jbloggs' },
:location => 'Palo Alto, California',
:verified => true
},
:credentials => {
:token => 'ABCDEF...', # OAuth 2.0 access_token, which you may wish to store
:expires_at => 1321747205, # when the access token expires (it always will)
:expires => true # this will always be true
},
:extra => {
:raw_info => {
:id => '1234567',
:name => 'Joe Bloggs',
:first_name => 'Joe',
:last_name => 'Bloggs',
:link => 'http://www.facebook.com/jbloggs',
:username => 'jbloggs',
:location => { :id => '123456789', :name => 'Palo Alto, California' },
:gender => 'male',
:email => 'joe#bloggs.com',
:timezone => -8,
:locale => 'en_US',
:verified => true,
:updated_time => '2011-11-11T06:21:03+0000'
}
source: https://github.com/mkdynamic/omniauth-facebook
This is why I could access "provider" and "uid" with simply auth["provider"], and I needed to do
auth["info"]["name"]
to access the name information. Similarly, to get the user's timezone, you could do
auth["extra"]["timezone"]

Related

Ruby - Stripe: Missing required param: type

I am trying to add a bank account using Ruby stripe API. but it gives the stripe error "Missing required param: type".
I am using following ruby code:
account = Stripe::Account.create({
:country => 'US',
:managed => true,
:transfer_schedule => {
:interval => 'weekly',
:weekly_anchor => 'friday'
},
:legal_entity => {
:dob => {
:day => birthday.day,
:month => birthday.month,
:year => birthday.year
},
:first_name => first_name,
:last_name => last_name,
:type => 'individual'
},
:tos_acceptance => {
:date => Time.now.to_i,
:ip => request.remote_ip
}
})
You are not passing the proper parameters to the API.
Please check this document for the proper request and response returned by Stripe.
https://stripe.com/docs/api?lang=ruby#create_account
require "stripe"
Stripe.api_key = "sk_test_bcd1234"
Stripe::Account.create(
:type => 'standard',
:country => 'US',
:email => 'bob#example.com'
)
To point out you are not passing :type param in the outer hash. You need to move it to the first level.
account = Stripe::Account.create(
{
:country => 'US',
:managed => true,
:type => 'individual', # Move this from nested to first level
:transfer_schedule => {
:interval => 'weekly',
:weekly_anchor => 'friday'
},
:legal_entity => {
:dob => {
:day => birthday.day,
:month => birthday.month,
:year => birthday.year
},
:first_name => first_name,
:last_name => last_name
},
:tos_acceptance => {
:date => Time.now.to_i,
:ip => request.remote_ip
}
}
)

How to get the country and state from a paypal transaction?

I would like to know how to obtain the country and state, from the billing address, in a paypal transaction.
So far I can get a transaction object via the code below:
# ...
def self.paypal_transaction_details(txn_id)
#api = PayPal::SDK::Merchant.new
get_transaction_details = #api.build_get_transaction_details({:TransactionID => txn_id })
response = #api.get_transaction_details(get_transaction_details)
end
Is it possible to get the location info? Or should I use geocoder to get the country and state from the ip address?
Reference: https://github.com/paypal/merchant-sdk-ruby
Response:
response.PaymentTransactionDetails.PayerInfo.Address
=> #<PayPal::SDK::Merchant::DataTypes::AddressType:0x007fd58f604660 #AddressOwner="PayPal", #AddressStatus="None">
Thanks in advance
I am not sure if you are using this gem 'paypal-sdk-rest'
but if you are, when you Create Payment
you can do
require 'paypal-sdk-rest'
include PayPal::SDK::REST
PayPal::SDK::REST.set_config(
:mode => "sandbox", # "sandbox" or "live"
:client_id => "EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM",
:client_secret => "EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM")
# Build Payment object
#payment = Payment.new({
:intent => "sale",
:payer => {
:payment_method => "credit_card",
:funding_instruments => [{
:credit_card => {
:type => "visa",
:number => "4567516310777851",
:expire_month => "11",
:expire_year => "2018",
:cvv2 => "874",
:first_name => "Joe",
:last_name => "Shopper",
:billing_address => {
:line1 => "52 N Main ST",
:city => "Johnstown",
:state => "OH",
:postal_code => "43210",
:country_code => "US" }}}]},
:transactions => [{
:item_list => {
:items => [{
:name => "item",
:sku => "item",
:price => "1",
:currency => "USD",
:quantity => 1 }]},
:amount => {
:total => "1.00",
:currency => "USD" },
:description => "This is the payment transaction description." }]})
# Create Payment and return the status(true or false)
if #payment.create
#payment.id # Payment Id
else
#payment.error # Error Hash
end
I hope that this helps.
ps.
you have to request the info first, if not there would be nil or '' when you want to get them back

How to pull the number of Google+ friends from GPlus API?

I'd like to pull the number of Google+ friends that my users have once they have successfully connected their Google+ account through omniauth-gplus: the gplus gem.
I was able to display the number of Twitter Followers and Facebook Friends that my user have using the omniauth-twitter, and omniauth-facebook gems and this was easier as the documentation was clearer on those two gems and API's.
Please see the below code for how I am pulling the Facebook and Twitter followers/friends under the Users::OmniauthCallbacksController:
Authorizations:
class Authorization < ActiveRecord::Base
attr_accessible :provider, :uid, :token, :secret, :first_name, :last_name, :link, :name, :connections_count
def update_connections_number(provider)
if provider == 'Facebook'
connections_count = Koala::Facebook::API.new(self.token).get_connections("me", "friends").count
self.update_attributes(connections_count: connections_count)
elsif provider == 'LinkedIn'
client = LinkedIn::Client.new(ENV['FR_LINKEDIN_KEY'], ENV['FR_LINKEDIN_SECRET'])
client.authorize_from_access(self.token, self.secret)
self.update_attributes(connections_count: client.connections.total)
end
end
end
Users
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def find_for_ouath(provider, access_token, resource=nil)
user, email, name, uid, auth_attr = nil, nil, nil, {}
case provider
when "Facebook"
uid = access_token['uid']
email = access_token['info']['email']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'],
:secret => nil, :first_name => access_token['info']['first_name'],
:last_name => access_token['info']['last_name'], :name => access_token['info']['name'],
:link => access_token['extra']['raw_info']['link'] }
when "Twitter"
uid = access_token['extra']['raw_info']['id']
name = access_token['extra']['raw_info']['name']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'],
:secret => access_token['credentials']['secret'], :first_name => access_token['info']['first_name'],
:last_name => access_token['info']['last_name'], :name => name,
:link => "http://twitter.com/#{name}", :connections_count => access_token['extra']['raw_info']['followers_count'] }
when 'LinkedIn'
uid = access_token['uid']
name = access_token['info']['name']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'],
:secret => access_token['credentials']['secret'], :first_name => access_token['info']['first_name'],
:last_name => access_token['info']['last_name'],
:link => access_token['info']['public_profile_url'] }
when 'GPlus'
uid = access_token['uid']
name = access_token['info']['email']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'],
:secret => access_token['credentials']['secret'], :first_name => access_token['info']['first_name'],
:last_name => access_token['info']['last_name'],
:link => access_token['info']['public_profile_url'] }
else
raise 'Provider #{provider} not handled'
end
if resource.nil?
if email
user = find_for_oauth_by_email(email, resource)
elsif uid && name
user = find_for_oauth_by_uid(uid, resource)
if user.nil?
user = find_for_oauth_by_name(name, resource)
end
end
else
user = resource
end
auth = user.authorizations.find_by_provider(provider)
if auth.nil?
auth = user.authorizations.build(:provider => provider)
user.authorizations << auth
end
auth.update_attributes auth_attr
auth.update_connections_number(provider)
return user
end
def find_for_oauth_by_uid(uid, resource=nil)
user = nil
if auth = Authorization.find_by_uid(uid.to_s)
user = auth.user
end
return user
end
def find_for_oauth_by_email(email, resource=nil)
if user = User.find_by_email(email)
user
else
user = User.new(:email => email, :password => Devise.friendly_token[0,20])
user.save
end
return user
end
def find_for_oauth_by_name(name, resource=nil)
if user = User.find_by_name(name)
user
else
first_name = name
last_name = name
user = User.new(:first_name => first_name, :last_name => last_name, :password => Devise.friendly_token[0,20], :email => "#{UUIDTools::UUID.random_create}#host")
user.save(:validate => false)
end
return user
end
end
How can I do this with Google+?
Cheers!

Activerecord map to array

I'm trying to take everything out of my Users table and send it to mail chimp for subscription.
I need to go from User.all to
[{:email => {:email => "example#domain.org"},
:merge_vars => {:FNAME => "First name", :LNAME => "Last name"}
}]
I'm trying to do this with map but I'm struggling, any ideas of the cleanest way of doing this?
subscription_array = User.all.collect do |user|
{
:email => {:email => user.email},
:merge_vars => {:FNAME => user.first_name, :LNAME => user.last_name}
}
end
users_array = []
User.all.find_each {|u| users_array << {:email => u.email, :merge_vars => {:FNAME => u.first_name, :LNAME => u.last_name} }
I chose to use find_each is it's a more efficient way of loading your collection.
http://api.rubyonrails.org/classes/ActiveRecord/Batches.html

Rails model not getting the params correctly

i'm having a kinda weird & annoying bug with Rails. I have a HAML form, a model, and a method for handling it:
View
%form{ :action => "/new", :method => "post", :style=>"margin-top: 6px"}
%input{:type=>"hidden", :name=>"authenticity_token", :value=>form_authenticity_token.to_s}
%input{:type => "text", :name => "blogName", :placeholder=>"Blog name"}
%input{:type => "text", :name => "blogSubdomain", :placeholder=>"Blog URL"}
%input{:type => "text", :name => "username", :placeholder=>"username"}
%input{:type => "text", :name => "email", :placeholder=>"email"}
%input{:type => "password", :name => "password", :placeholder=>"password"}
%br/
%input{:type => "submit", :value => "Send", :class => "btn btn-primary"}
- unless session[:error].nil?
%div{:class=>"alert alert-error", :style=>"font-size:13px; font-weight:normal;"}
%strong Please correct the following errors
%br
- session[:error].each do |value|
- unless value.nil?
%li= "#{value}"
- session[:error]=nil
Model:
class User
include MongoMapper::Document
key :screen_name, String, :required => true, :unique => true
key :blog_name, String, :required => true, :unique => true
key :blog_subdomain, String, :required => true, :unique => true
key :email, String, :required => true, :unique => true, :format => /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i
key :password, String, :required => true
key :admin, Boolean
timestamps!
validate :finalValidate
before_save :stripSpaces, :hashPassword
def stripSpaces
self.blog_subdomain = self.blog_subdomain.gsub(/[\ _]/, "-")
end
def finalValidate
if blog_subdomain.length > 10
errors.add(:blog_subdomain, "Your chosen subdomain is too long, the maximum is 9 characters")
end
case blog_subdomain
when "www"
when "api"
errors.add(:blog_subdomain," - Sorry but that subdomain is reserved!")
end
end
def hashPassword
self.password = Digest::SHA512.hexdigest(self.password)
end
end
And the method to do it
def new_post
if session[:r]
redirect_to root_path, :subdomain => nil
else
user = User.new({
:screen_name=>params[:username],
:blog_name => params[:blogName],
:blog_subdomain => params[:blogSubdomain],
:email => params[:email],
:password => params[:password],
:admin => false
})
if user.save
session[:screen_name] = user.screen_name
session[:blog_subdomain] = user.blog_subdomain
session[:blog_name] = user.blog_name
session[:twitter_user] = "nothin"
session[:r] = true
flash[:success] = "Blog created!"
redirect_to root_path, :subdomain => user.blog_subdomain
else
errors = Array.new()
for i in 0..user.errors.full_messages.count
errors.push(user.errors.full_messages[i])
end
session[:error] = errors
flash[:error] = "Error creating blog"
redirect_to '/new'
end
end
end
The method fails on if user.save, going straight to the else statement. I'm getting errors when passing the email and password. MongoMapper returns:
Email can't be blank
Email has already been taken
Email is invalid
Password can't be blank
If I remove the validations then the values are just nil. I double checked all, but I couldn't get what's wrong. On the log I see how the params are being sent:
Started POST "/new" for 127.0.0.1 at 2012-03-10 20:46:56 +0100
Processing by ActionsController#new_post as HTML
Parameters: {"authenticity_token"=>"T7J8DDaWWd25LBP6dRgbvpAs4bkC/zLk3GiQ5rVLmiw=", "blogName"=>"wut", "blogSubdomain"=>"WUT", "username"=>"someuser", "email"=>"some#validmail.net", "password"=>"[FILTERED]"}
Redirected to http://myapp.dev/new
Completed 302 Found in 745ms
What I'm doing wrong?
EDIT: Put a logger on the model, and bot mail and password classes are NilClass
Shouldn't be there rather
user = User.new(
:screen_name=>params[:username],
:blog_name => params[:blogName],
:blog_subdomain => params[:blogSubdomain],
:email => params[:email],
:password => params[:password],
:admin => false
)
?
The problem was attr_accessible. I didn't added the email and password fields to it, and it was returning nil because of that

Resources