bussorenre Laboratory

hoge piyo foo bar

omniauth+fb_graph でfacebookのウォールに投稿する

こんにちは。@bussorenreです。 表題の通り、Ruby on Railsfacebook のウォールに投稿するための記事が日本語でも英語でもパッと見つからなかったので、自分でまとめてみました。

開発に使っている環境は以下のとおりです。

  • 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 アプリを作成します。

f:id:bussorenre:20130312181201p:plain

Apps →アプリを作成を押します。

f:id:bussorenre:20130312181458p:plain

こんな感じで、アプリの名前とネームスペースを決定します。heroku で動かすときは、このチェックボックスを入れるといいかもしれません。

すると、App ID とApp Secret が生成されます。これ絶対使うので、他の人に知られないようにしてくださいね。

次に、callback のURL を指定します。

f:id:bussorenre:20130312182321p:plain

ざっとこんなかんじに。

次に、権限の付与をします。

f:id:bussorenre:20130312181823p:plain

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 に関しては公式のドキュメントが非常に充実しているので、詳しくはこっちを見て欲しいのですが(英語だけど全然読める!)フィードに流すための方法は上記のような感じです。簡単!