Ruby on Railsを使ってFacebook認証+ページにいいねしないとコンテンツを見ることが出来ないサービスを作ったので、実装方法を書いておきます。広告用にアプリを作りたい!という時とかに役立つ機能だと思います。
実装例:「同じ誕生日の有名人は誰?」
このWebアプリと同じ実装をしていきます。
環境
- Ruby (2.1.1p76)
- Rails (4.1.1)
- devise (3.2.4)
- omniauth-facebook (1.6.0)
- koala (1.8.0)
Gemのインストール
Gemfileに以下のコードを追加してbundle install
します。
# Gemfile
gem 'devise'
gem 'omniauth-facebook'
gem 'koala'
ユーザ認証機能の実装
ユーザ認証にdeviseとomniauth-facebookを使っていきます。
Deviseの導入
# config/inistializer/devise.rbを(設定ファイル)作成
$ rails g devise:install
# deviseの認証用のviewの作成
$ bundle exec rails g devise:views
# 認証用のモデルを作成(今回はUserにした)
$ rails g devise user
Deviseのmigration設定
Facebookの認証に必要なカラムをUserモデルに追加していきます。
# db/migrate/*_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## この3つを追加する!!
t.integer :uid, null: false, limit: 8
t.string :provider
t.string :token
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
end
end
追加し終わったらmigrateしましょう
$ bundle exec rake db:migrate
deviseのモデルを編集
Userモデルにomniauthを使用することを記入します。
# app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :omniauthable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Facebookアプリの登録
こちらのサイトを見て、開発者登録、アプリの登録を済ませる
[Settings]から[Add Platform]をクリックし、[Website]を選択
[App Details]で各種設定をすませる
※ SiteURLは開発環境なら http://localhost:3000/ とかとりあえずいれといて下さい。
API Keyの設定
取得したApp ID, App Secretをdevise.rbに記入していきます。
# config/initializers/devise.rb
Devise.setup do |config|
# ...
# API key
config.omniauth :facebook, "App ID", "App Secret",
scope: 'basic_info, email, user_likes, public_profile'
end
OAuth の callback 用ルーティングを追加
config/routes.rb に callback 用のルーティングを追加します。
# config/routes.rb
devise_for :users, :controllers => {
:omniauth_callbacks => "users/omniauth_callbacks"
}
Users::OmniauthCallbacksController を作成
omniauth_callbacks_controller.rbというファイルをapp/controllers/users/に作成し、以下の内容を記述します。
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
@user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if @user.persisted?
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
sign_in_and_redirect @user, :event => :authentication
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
find_for_facebook_oauthメソッドの定義
コールバックメソッドの中でfind_for_facebook_oauthというメソッドを使用するので、これを定義します。app/models/user.rbに以下の内容を追加して下さい。
# app/models/user.rb
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(name: auth.extra.raw_info.name,
provider: auth.provider,
uid: auth.uid,
email: auth.info.email,
password: Devise.friendly_token[0,20]
)
end
user
end
ViewにOauth認証のリンクを追加
トップ画面等、Facebook認証をさせたい画面に以下のリンクを挿入します。
<%= link_to "Facebookでサインイン", user_omniauth_authorize_path(:facebook) %>
とりあえずここまででfacebook認証は実装出来たはずです。
いいねしないと表示出来ない機能の実装
では、いいねをしないと表示出来ないコンテンツを作成していきましょう。
ここでは、例として、pages_controllerを作成し、checkアクションでいいねしているかどうかのチェック、およびにいいねをさせる。resultアクションでコンテンツを表示していきます。
コントローラの作成
まずはコントローラを作成しましょう。
$ rails generate controller page check result
続いて、ログインしてるユーザのみアクセスできるように、pages_controlerに :authenticate_user!メソッドを追加
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
before_filter :authenticate_user!
def result
end
def check
end
end
ルーティング設定もしておきます。
# config/routes.rb
match "/result", to: "pages#result", via: "get"
match "/check", to: "pages#check", via: "get"
checkを通らずにresultにいけないようにする
checkを通らずにresultを表示出来ないようにしていきます。まずは画面遷移をsessionに記録するようにします。
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
after_filter :store_location
def store_location
session[:previous_url] = request.fullpath
end
end
次に、pages_controllerのresultメソッドに以下の内容を記入します
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
before_filter :authenticate_user!
def result
if session[:previous_url] != check_path && session[:previous_url] != result_path
redirect_to check_path
end
end
#...
end
ページにイイネしているかのチェック!
koalaを使って、特定のfacebookページにイイネしているかどうかのチェックをしていきます。
まずはuserモデルにユーザのfacebook graphを取得するメソッドを追加します。
# app/models/user.rb
class User < ActiveRecord::Base
# ...
def graph
Koala::Facebook::API.new(self.token)
end
end
次にpages_controllerのcheckアクションでユーザがいいねをしていたらresultに飛ばす実装をしていきます。
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
# ...
def check
client = current_user.graph
likes = client.get_connections("me", "likes")
likes.each do |like|
if like["id"] == "あなたのFacebookページのID"
redirect_to result_path
end
end
end
end
ビューにいいねボタンを追加
最後に、checkアクションに使うviewにいいねボタンを埋め込みましょう。
<!-- app/views/pages/check.html.erb -->
<p>結果を見るには下のいいね!ボタンを押して下さい</p>
<div class="like-box"><div class="fb-like" data-href="あなたのfacebookページのURL" data-width="500" data-layout="box_count" data-action="like" data-show-faces="true" data-share="false"></div></div>
<div id="fb-root"></div>
<script>
// facebook
window.fbAsyncInit = function() {
FB.init({
appId : 'あなたのAPP ID',
status : false, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true // parse XFBML tags on this page?
});
// いいねしたときの処理
FB.Event.subscribe('edge.create',
function(response) {
location.href = "<%= result_url %>";
}
);
};
</script>
以上です。後は好きにviewやコントローラをいじってコンテンツを作成して下さい。
お疲れさまでした。
参考
- 「plataformatec/devise」
- EasyRamble - Rails4 で Devise と OmniAuth で、Twitter/Facebook のOAuth認証と通常フォームでの認証を併用して実装
- arsduo/koala
ブログやってます!!
=>http://alex23drum.hatenablog.com