Rails3でFacebook認証 with Mongoid

Standard
Rails3でFacebook認証 with Mongoid

これこの辺とかを参考にやってみる。
 
準備
 
上のリンクを参考にFacebookアプリを登録しておく。mongodbのインストールはこんな感じ
 
labbie/.rvmrc

if [[ -s "labbie.gems" ]] ; then
  rvm gemset import labbie.gems | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
fi
rvm  1.9.2@labbie

 
labbie/Gemfile

source 'http://rubygems.org'

gem 'rails', '3.0.5'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'haml'
gem 'haml-rails'
gem 'jquery-rails'

#gems for Mongoid
gem "mongoid", ">= 2.0.0.beta.19", :git => "https://github.com/mongoid/mongoid.git"
gem "bson_ext", ">= 1.2"
gem "koala", :git => 'https://github.com/arsduo/koala.git'

group :development, :test do
  gem "rspec-rails", ">= 2.0.0.beta.13"
  gem "rspec-integration", ">= 2.0.0.beta.13"
  gem "factory_girl", :git => 'https://github.com/thoughtbot/factory_girl.git'
  gem "factory_girl_rails", :git => 'https://github.com/thoughtbot/factory_girl_rails.git'
  gem "cucumber", :git => 'https://github.com/aslakhellesoy/cucumber.git'
  gem "cucumber-rails"
  gem "capybara"
  gem "database_cleaner"
  gem "spork"
  gem "launchy"
  gem "nifty-generators"
  gem 'rails3-generators'
end

 

  • r new labbie -J
  • cd labbie
  • gem update bundler
  • bundle install
  • r g rspec:install

 
labbie/spec/spec_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'factory_girl'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  # == Mock Framework
  #
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
  #
  # config.mock_with :mocha
  # config.mock_with :flexmock
  # config.mock_with :rr
  config.mock_with :rspec

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  #config.fixture_path = "#{::Rails.root}/spec/factories"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  #config.use_transactional_fixtures = true
end

 

  • git init
  • git add .
  • git commit -m ‘first commit’
  • gem install passenger
  • rvmsudo passenger-install-nginx-module

 
koalaはFacebook API用のラッパ。koala用に設定を追加する。
 
labbie/config/facebook.yml

development:
  app_id: "YOUR_APP_ID"
  secret_key: "YOUR_SECRET_KEY"
test:
  app_id: "YOUR_APP_ID"
  secret_key: "YOUR_SECRET_KEY"
production:
  app_id: "YOUR_APP_ID"
  secret_key: "YOUR_SECRET_KEY"

 
labbie/config/initializers/koala.rb

# Monkey-patch in Facebook config so Koala knows to 
# automatically use Facebook settings from here if none are given

module Facebook
  CONFIG = YAML.load_file(Rails.root.join("config/facebook.yml"))[Rails.env]
  APP_ID = CONFIG['app_id']
  SECRET = CONFIG['secret_key']
end

Koala::Facebook::OAuth.class_eval do
  def initialize_with_default_settings(*args)
    case args.size
      when 0, 1
        raise "application id and/or secret are not specified in the config" unless Facebook::APP_ID && Facebook::SECRET
        initialize_without_default_settings(Facebook::APP_ID.to_s, Facebook::SECRET.to_s, args.first)
      when 2, 3
        initialize_without_default_settings(*args) 
    end
  end 

  alias_method_chain :initialize, :default_settings 
end

 
あとはmongoid用の設定。
 
labbie/config/application.rb

require File.expand_path('../boot', __FILE__)

# If you are deploying to Heroku and MongoHQ,
# you supply connection information here.
require 'uri'
if ENV['MONGOHQ_URL']
  mongo_uri = URI.parse(ENV['MONGOHQ_URL'])
  ENV['MONGOID_HOST'] = mongo_uri.host
  ENV['MONGOID_PORT'] = mongo_uri.port.to_s
  ENV['MONGOID_USERNAME'] = mongo_uri.user
  ENV['MONGOID_PASSWORD'] = mongo_uri.password
  ENV['MONGOID_DATABASE'] = mongo_uri.path.gsub('/', '')
end

require 'mongoid/railtie'
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'active_resource/railtie'
require 'rails/test_unit/railtie'

# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)

module Labbie
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Custom directories with classes and modules you want to be autoloadable.
    # config.autoload_paths += %W(#{config.root}/extras)

    # Only load the plugins named here, in the order given (default is alphabetical).
    # :all can be used as a placeholder for all plugins not explicitly named.
    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]

    # Activate observers that should always be running.
    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # JavaScript files you want as :defaults (application.js is always included).
    config.action_view.javascript_expansions[:defaults] = %w(rails)

    config.generators do |g|
      g.orm             :mongoid
      g.template_engine :haml
      g.test_framework  :rspec, :fixture => true
      g.fixture_replacement :factory_girl, :dir => "spec/factories"
    end

    # Configure the default encoding used in templates for Ruby 1.9.
    config.encoding = "utf-8"

    # Configure sensitive parameters which will be filtered from the log file.
    config.filter_parameters += [:password]
  end
end

 
labbie/config/mongoid.yml

defaults: &defaults
  host: localhost
  # slaves:
  #   - host: slave1.local
  #     port: 27018
  #   - host: slave2.local
  #     port: 27019

development:
  < <: *defaults
  database: labbie_development

test:
  <<: *defaults
  database: labbie_test

# set these environment variables on your prod server
production:
  host: <%= ENV['MONGOID_HOST'] %>
  port: < %= ENV['MONGOID_PORT'] %>
  username: < %= ENV['MONGOID_USERNAME'] %>
  password: < %= ENV['MONGOID_PASSWORD'] %>
  database: < %= ENV['MONGOID_DATABASE'] %>

 
設定おわり。
 
 
モデルの定義
 
Facebookから取得したプロフィールをHashの形でDBに突っ込んでみる。
 
labbie/app/models/user.rb

class User
  include Mongoid::Document
  include Mongoid::Timestamps
  field :facebook_id, :type => BigDecimal
  field :access_token, :type => String
  field :facebook, :type => Hash
end

 
コントローラとビュー
  
labbie/app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper_method :current_user

  private
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
end

 
labbie/app/controllers/top_controller.rb

class TopController < ApplicationController
  def index
  end
end

 
labbie/app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def create
    begin
      access_token = Koala::Facebook::OAuth.new(login_url).get_access_token(params[:code]) if params[:code]
      rest = Koala::Facebook::GraphAndRestAPI.new(access_token)
      me = rest.get_object("me")

      user = User.where(:facebook_id => me["id"], :access_token => access_token)
      if user.empty?
        user = User.new(
          :facebook_id => me["id"],
          :access_token => access_token,
          :facebook => me
        )
      else
        user = user.first
        user.facebook = me
      end

      user.save
      session[:user_id] = user.id
      redirect_to root_url, :notice => "Signed in!!"
    rescue Exception
      puts "#$!"
      render :file => "#{::Rails.root.to_s}/public/500.html", :layout => false, :status => 500
    end
  end
  
  def destroy
    reset_session
    redirect_to root_url, :notice => "Signed out!!"
  end
end

 
labbie/config/routes.rb

Labbie::Application.routes.draw do
  get "top/index"

  match '/auth/callback' => 'sessions#create', :as => 'login'
  match '/logout' => 'sessions#destroy', :as => 'logout'
  root :to => "top#index"
end

 
labbie/app/views/top/index.html.haml

%h1 Top#index
%p Find me in app/views/top/index.html.haml
- unless current_user
  = link_to 'Login with Facebook', Koala::Facebook::OAuth.new.url_for_oauth_code(:callback => login_url)
- else
  %p
    Login as
    = link_to current_user.facebook["name"], current_user.facebook["link"]
  %ul
    - current_user.facebook.each do |k,v|
      %li
        %b #{k}&nbsp;:&nbsp;
        = v
  %p
    = link_to "Logout", logout_url

 
 
こんな感じになる。
 
cap

cap1

 
OAuthアクセスを許可すると
 
cap

cap2

 
herokuにデプロイ
アドオンを追加すればmongodbがherokuでも使える。herokuをbundlerでインストールするとなんか古いバージョンが入るのでgem install herokuしないといかんです。

  • gem install heroku
  • heroku create labbie
  • heroku stack:migrate bamboo-mri-1.9.2
  • git commit –allow-empty -m “migrating to bamboo stack”
  • heroku addons:add mongohq:free
  • git push heroku master

Facebook comments:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>