I am working on rails 3 and using the koala gem to get a connection to the facebook graph api.
And I am using omniauth to autenticate users.
So when a new user logs to the site, the session_controller handles the new user:
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env['omniauth.auth'])
session[:user_id] = user.id
redirect_to root_url, notice: "Signed in!"
end
The create method call the "from_omniauth" class metod in the User.rb model, to create a new user:
class User < ActiveRecord::Base
has_many :friends
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth["provider"]
user.uid = auth["uid"]
user.name = auth["info"]["name"]
user.first_name = auth["info"]["first_name"]
user.last_name = auth["info"]["last_name"]
user.image = auth["info"]["image"]
user.email = auth["info"]["email"]
user.gender = auth["extra"]["raw_info"]["gender"]
user.location = auth["extra"]["raw_info"]["location"]["name"]
user.token = auth["credentials"]["token"]
end
user.save!
end
I would like to save user facebook friends also and store it in a separate tabel called friends, so I made this friend model:
class Friend < ActiveRecord::Base
attr_accessible :name
belongs_to :user
validates :user_id, presence: true
def facebook
#Facebook ||= Koala::Facebook::API.new(token)
end
def add_friends
facebook { |fb| fb.get_connection("me", "friends") }
end
end
But I am lost on how to store users friends, I whould like to know:
How I can create a user, and store it friends
Where should I call the add_friends method?
fb.get_connection("me", "friends") return a array of hashes, like this > [{"name"=>"Johan Gyllenspetz", "id"=>"3624556"}, {"name"=>"Gustaf Josefsson", . And I would like to store the name and uid.
This is how I'd do this:
class User < ActiveRecord::Base
has_many :friends
def self.from_omniauth(auth)
user = where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth["provider"]
user.uid = auth["uid"]
user.name = auth["info"]["name"]
user.first_name = auth["info"]["first_name"]
user.last_name = auth["info"]["last_name"]
user.image = auth["info"]["image"]
user.email = auth["info"]["email"]
user.gender = auth["extra"]["raw_info"]["gender"]
user.location = auth["extra"]["raw_info"]["location"]["name"]
user.token = auth["credentials"]["token"]
end
user.add_friends
user.save
user
end
def add_friends
#facebook.get_connection("me", "friends").each do |hash|
self.friends.where(:name => hash['name'], :uid => hash['id']).first_or_create
end
end
private
def facebook
#facebook ||= Koala::Facebook::API.new(token)
end
end
Related
I want to get my tweets using user_timeline()and save them to my application database.
I'm not sure where to call that function and how to save each tweet associating with my user.
This is the way I'm saving users to the database
class SessionsController < ApplicationController
def create
auth = request.env['omniauth.auth']
session[:omniauth] = auth.except('extra')
user = User.sign_in_from_omniauth(auth)
session[:user_id] = user.id
redirect_to root_url, notice: "SIGNED IN"
end
end
Here's my model...
class User < ActiveRecord::Base
def self.sign_in_from_omniauth(auth)
find_by(provider: auth['provider'], uid: auth['uid']) || create_user_from_omniauth(auth)
end
def self.create_user_from_omniauth(auth)
create(
provider: auth['provider'],
uid: auth['uid'],
name: auth['info']['name'],
screen_name: auth['info']['nickname'],
oauth_token: auth['credentials']['token'],
oauth_secret: auth['credentials']['secret']
)
end
def twitter
Twitter::REST::Client.new do |config|
config.consumer_key = 'XXXXXXXXXXXXXXXX'
config.consumer_secret = 'XXXXXXXXXXXXXXXX'
config.access_token = oauth_token
config.access_token_secret = oauth_secret
end
end
end
Where I should call user_timeline() and save all tweets?
Approach #1
Send email reminder to <%= email_field_tag :email, nil, placeholder: 'Enter Email', class: "send-email" %> # :email belongs to the users table
Approach #2
Send email reminder to <%= f.email_field :default_email, class: "send-email", placeholder: "Enter Email" %> # :default_email belongs to the challenges table. The point of this is to try something in the create process like current_user.email == #challenge.default_email
The user is then redirected to signup url
If a user signs up via Facebook a random email is generated so that he can get through the validation process: user.email = SecureRandom.hex + "#mailinator.com"
user.rb
def self.from_omniauth(auth)
# Sets 60 day auth token
oauth = Koala::Facebook::OAuth.new("125402372971231236229929", "ee917abf2e8f1c98274cdafssadffddffaebb1346f4")
new_access_info = oauth.exchange_access_token_info auth.credentials.token
new_access_token = new_access_info["access_token"]
new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.image = auth.info.image
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = new_access_token # auth.credentials.token <- your old token. Not needed anymore.
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.password = (0...8).map { (65 + rand(26)).chr }.join
user.email = SecureRandom.hex + "#mailinator.com" unless user.email.present?
user.activated = true
user.save!
end
end
But how can we make the email the user inputted in the challenges/create.html.erb form seen above override the SecureRandom email?
users_controller
def create
#user = User.new(user_params)
if #user.save
action = session.delete(:challenge_action)
deadline = session.delete(:challenge_deadline)
committed = session.delete(:challenge_committed)
date_started = session.delete(:challenge_date_started)
order = session.delete(:challenge_order)
days_challenged = session.delete(:challenge_days_challenged)
why = session.delete(:challenge_why)
conceal = session.delete(:challenge_conceal)
#user.challenges.create(action: action, deadline: deadline, why: why, conceal: conceal, date_started: date_started, committed: committed, days_challenged: days_challenged)
end
redirect_to root_url
else
render 'new'
end
end
challenges_controller
before_action :update_user_email, if: proc {|c| c.current_user.present? && c.params[:email].present? }
def create
#challenge = Challenge.new(challenge_params)
if params[:step] == '2'
if current_user == nil
# If there is no user, store values to the session.
session[:challenge_action] = challenge_params[:action]
session[:challenge_committed] = challenge_params[:committed]
session[:challenge_deadline] = [params["challenge"]["deadline(3i)"], params["challenge"]["deadline(2i)"], params["challenge"]["deadline(1i)"]].join('/')
session[:challenge_date_started] = [params["challenge"]["date_started(3i)"], params["challenge"]["date_started(2i)"], params["challenge"]["date_started(1i)"]].join('/')
session[:challenge_order] = challenge_params[:order]
session[:challenge_days_challenged] = challenge_params[:days_challenged]
session[:challenge_why] = challenge_params[:why]
session[:challenge_conceal] = challenge_params[:conceal]
redirect_to signup_path
else
#challenge = current_user.challenges.build(challenge_params)
#challenge.save
redirect_to root_path
end
else
respond_modal_with #challenge
end
end
private
def update_user_email
email = params[:email]
current_user.update_attribute(:email, email)
end
sessions_controller
class SessionsController < ApplicationController
def new
end
def facebook
user = User.from_omniauth(env["omniauth.auth"])
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
redirect_to root_url
end
def create
assign_email(cookies[:challenges_email])
user = User.find_by(email: params[:session][:email].downcase)
assign_email(cookies[:challenges_email])
if user && user.authenticate(params[:session][:password])
assign_email(cookies[:challenges_email])
log_in user
params[:session][:remember_me] == 'nil' ? forget(user) : remember(user)
redirect_to root_url
else
flash.now[:info] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
log_out if logged_in?
redirect_to root_url
end
end
We talked about setting it as a cookie in another question. If you're taking that approach, you could pass the cookie to a method. Something like what is discussed in this question:
before_create :set_user_email
def assign_email(email)
#email = email
end
def set_user_email
self.email = #email
end
then in the controller action where you have access to the cookie:
assign_email(cookies[:challenge_email])
#joseph had answered it pretty simple but i think you can just get email in the field by setting it in the controller like;
User.new(:email => "email you want to show in the field")
no need to pass nil user object pass a new object.
And in the view file it will shown in email field with
Send email reminder to <%= f.email_field :email, class: "send-email", placeholder: "Enter Email" %>
On My current app that i'm developing, i can sign up using Facebook and Google+. But when I added the ability for signing up with just a regular email, i got this error, I'll appreciate some help please ...
Here are some of my code
#SessionsController
def create
#user = User.from_omniauth(env["omniauth.auth"])
# session[:user_id] = #user.id
# redirect_to root_path
#user = User.find_by_email params[:email]
if #user && #user.authenticate(params[:password])
session[:user_id] = #user.id
redirect_to root_path
else
flash[:alert] = "Wrong email or password"
render :new
end
end
#user.rb
class User < ActiveRecord::Base
has_secure_password
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.image = auth.info.image
user.gender = auth.extra.raw_info.gender
user.location = auth.extra.raw_info.location.name
user.location = auth.extra.raw_info.locale
# user.url = auth_hash['info']['urls'][user.provider.capitalize]
user.save
end
end
So When attempting to signUp with using the email, here's what happen !
enter image description here
I'm guessing that error coming because i'm calling from_omniauth and i'm not passing a provider, which i don't need to use in this case.
You might consider starting fresh - using https://github.com/plataformatec/devise and then adding OmniAuth on top of this (https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview).
I am using omniauth-facebook gem. I need to fetch gender and email from facebook, but it is not happening. Can anyone help me out here?
User Model
class User < ActiveRecord::Base
attr_accessible :email, :name, :uid, :provider, :gender, :oauth_token, :oauth_expires_at
validates_presence_of :name, :uid
validates_uniqueness_of :uid
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.gender = auth.info.gender
user.image = auth.info.image
user.save!
end
end
end
User Contoller
class UsersController < ApplicationController
respond_to :html, :json
def create
#user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = #user.id
redirect_to api_browsing_screen_url
end
end
omniauth.rb
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
if Rails.env.production?
provider :facebook, 'app_id', 'app_secret_key'
elsif Rails.env.development?
provider :facebook, 'app_id', 'app_secret_key', {:scope => 'publish_actions,email', :client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" }}}
else
provider :facebook, 'app_id', 'app_secret_key'
end
end
You can get gender attribute from extra.raw_info.gender. like below
user.gender = auth.extra.raw_info.gender
I am trying to create a facebook login my ap and i get this error at runtime when sigin in with facebook is clicked
ActiveRecord::StatementInvalid in SessionsController#create
SQLite3::SQLException: no such column: users.provider: SELECT "users".* FROM "users" WHERE "users"."provider" = 'facebook' AND "users"."uid" = 'FACEBOOK KEY' ORDER BY "users"."id" ASC LIMIT 1
Extracted source (around line #6):
4 def self.from_omniauth(auth)
5 where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
6 user.provider = auth.provider
7 user.uid = auth.uid
8 user.name = auth.info.name
Rails.root:/selfstarter
Application Trace | Framework Trace | Full Trace
app/models/user.rb:6:in `from_omniauth'
app/controllers/sessions_controller.rb:3:in `create'
Here is the code from user.rb
class User < ActiveRecord::Base
has_many :orders
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
Here is the code from sessions controller
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_path
end
def destroy
session[:user_id] = nil
redirect_to root_path
end
end