omniauth+fb_graph でfacebookのウォールに投稿する
こんにちは。@bussorenreです。 表題の通り、Ruby on Rails でfacebook のウォールに投稿するための記事が日本語でも英語でもパッと見つからなかったので、自分でまとめてみました。
開発に使っている環境は以下のとおりです。
- Ruby 1.9.3
- Ruby on Rails 3.2.12
- Mac Book Air (Mountain Lion)
- 最終確認日:2013年3月16日
なお、今回はfacebook との認証のためにomniauthを使いますが、別にdeviseを使っても問題ないです。要はAccess_token が取得出来ればいいので…。
1 プロジェクトを作成する
rails new facebookpost
今回はfacebookpost という名前のプロジェクトを使用します。 githubにて今回のサンプルを公開しているので、良ければぜひお使いください。
https://github.com/bussorenre/facebookpost
2. Gemfile の修正
プロジェクトを作成したら、次にGemfile を開き以下の文句を追加します。
gem 'omniauth'
gem 'omniauth-facebook'
gem 'fb_graph'
Facebook に投稿する便利なgemは他にkoala などもあります。書き終わったらbundle installで。
3. ログインに用いるUser model の作成
次にUser model を作成します。今回はfacebook 認証でのみログインするような形のUserModel です。E-mailや、password などを実装したいときはこれに別途追加する形で問題ないと思います。
rails g scaffold users name:string facebookid:string desc:text token:text
rake db:migrate
本当はscaffold で生成するのではなく、ちゃんとuser model を作成して、用途に合わせてコントローラーを作るべきですが、今回はサンプルなので細かいことは気にしない。
僕はここで最もハマりました。 理由・原因は全くよくわからないのですが、アクセストークンを保存するフィードを、access_token:string にしたら一切動かなくなりました。名前が悪いのか、string だったのが悪いのか謎です。どなたか教えていただけると幸いです。
で、出来上がったmodel/user.rb に以下の文言を追加(バリデーションです)
VALID_FACEBOOKID_REGEX = /^[1-9][0-9]*$/
validates :name, presence: true,
length: { maximum: 48 }
validates :facebookid, presence: true,
format: { with: VALID_FACEBOOKID },
uniqueness: { case_sensitive: false }
validates :token, presence: true
バリデーションはざっとこんな形。複数ユーザーが登録しないように、facebookid にはユニークな値のみ通すよう設定
4. facebook APPの作成
https://developers.facebook.com/ に飛んで、Facebook アプリを作成します。
Apps →アプリを作成を押します。
こんな感じで、アプリの名前とネームスペースを決定します。heroku で動かすときは、このチェックボックスを入れるといいかもしれません。
すると、App ID とApp Secret が生成されます。これ絶対使うので、他の人に知られないようにしてくださいね。
次に、callback のURL を指定します。
ざっとこんなかんじに。
次に、権限の付与をします。
Twitter と違い、facebook には非常に多くの権限フラグがあります。必要最小限のフラグのみを立てるようにしましょう。 自らのウォールに投稿したい場合のフラグは図の通り。もしかしたら余計なのが多いかも(email とか絶対要らない。
5. Omniauth によるログイン認証の実装
http://npb.somewhatgood.com/blog/archives/715 完全にこのサイトを参考にしました。すごいいい記事。
omniauth を用いてfacebook 認証をします。まず、config/initializers/omniauth.rb を新規作成し、以下のようにコードを書きます。
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook,"App ID","App Secret", scope: 'email,publish_stream'
end
ここのApp ID と App Secret は先程取得したものを各自書いてください。 もっとも大事なのは、アプリ側で権限をしっかり明記すること。これに僕は4時間くらいハマりました笑
次に、facebookログインへのリンクを作ります。これはどこに書いてもいいのですが、参考にした記事を見習ってviews/layouts/application.html.rb に書くことにしました。
<div id="user_nav">
<%= link_to "facebookでlogin", "/auth/facebook" %>
</div>
次に、facebook からのcallback を受け取るアクションを作成します。今回はめんどくさいので、scaffold で生成した既存のUsers#new に当てようと思います。
config/routes.rb に以下のような文句を書きます。
resources :users # 多分書き込まれている
root :to => 'users#index'
match "/auth/:provider/callback" => "users#new"
書き換えたら、最後に、User Controller の編集。new アクションを大いに書き換えます。
def new
@user = User.new
# omniauth の情報を取得
auth = request.env["omniauth.auth"]
# ユーザーを探す
if auth['provider'] == 'facebook'
user = User.find_by_facebookid auth['uid']
end
# ユーザーが入ればそのユーザーでログイン
# 今回はログイン処理省略
# ユーザーがいなければ新規登録画面に移動
@user = User.new
if auth['provider'] == 'facebook'
@user.facebookid = auth['uid']
@user.name = auth['info']['name']
@user.desc = auth['info']['description']
@user.token = auth['credentials']['token']
# fb_graph テスト
me = FbGraph::User.me(@user.token)
me.feed!(
:message => 'Facebook に投稿するアプリのテスト!',
#:picture => 'https://graph.facebook.com/matake/picture',
#:link => 'https://github.com/bussorenre',
:name => 'facebook Post Sample',
:description => 'Facebook に投稿するアプリのサンプル'
)
end
end
(サンプルを作るのがめんどくさくなってきたので)アカウントの作成時に、facebook に投稿しちゃうことにします。(本当は# fb_Graph のテストという部分は、create アクションの中でやるべき。
omniauth がfacebook から持ってくる情報は、全部request.env["omniauth.auth"]に入っているので、そこからユーザー情報を全部引き出します。
そして、そのtoken を元に、Facebook への投稿を行います。ここでようやくFbGraph の登場。
Fb_graph に関しては公式のドキュメントが非常に充実しているので、詳しくはこっちを見て欲しいのですが(英語だけど全然読める!)フィードに流すための方法は上記のような感じです。簡単!