Hatena::ブログ(Diary)

m-kawato@hatena_diary

2013-04-30

(メモ) HTTPリクエスト・レスポンスのキャプチャ手段

| 11:01 | (メモ) HTTPリクエスト・レスポンスのキャプチャ手段を含むブックマーク

徳丸本こと「体系的に学ぶ 安全なWebアプリケーションの作り方」を読み中です。

(PDF版: http://bookpub.jp/books/bp/144)

この本は、サンプルの動作環境として、プロキシベースのHTTPモニタリングツール「Fiddler」を前提として書かれています。少し触ってみた感じでは、Fiddlerでは非常にお手軽にHTTPリクエスト・レスポンスの情報が見れて、この目的に限ればWiresharkよりも優れている印象ですが、残念ながらWindows版しか存在しないため、LinuxMacでは動きません。

Fiddler公式サイト: http://fiddler2.com/

ぐぐってみた限りでは、Fiddlerと同様にプロキシとして動作するCharlesというツールが定番のようなので、少し触ってみました。

Charles公式サイト: http://www.charlesproxy.com/

機能的にはCharlesで十分そうではあるものの、私が試した範囲では頻繁にフリーズするので、常用には厳しい印象を受けました。

(フリーズするのは、前述の徳丸本中のサンプルを含む特定のURL接続時の模様。フリーズする条件は特定できず)

以下の動作環境で試しています。

ちなみに、Oracle版のJDK7との組み合わせや、(apt版でない) 汎用Linux版でも試してみましたが、状況は変わりませんでした。

Fiddlerスクリーンショット:

f:id:m-kawato:20130430101919p:image:w500

さらに調べたところ、FirefoxFirebugChromeデベロッパーツールでは、HTTPリクエスト・レスポンスの内容を表示する機能があるので、さしあたりはこれで十分かなと思います。(もしかして常識?)

FirefoxFirebugスクリーンショット (「ネットワーク」タブ) :

f:id:m-kawato:20130430101622p:image:w500

Chromeデベロッパーツールのスクリーンショット (「Network」タブ):

f:id:m-kawato:20130430101621p:image:w500

2013-03-03

DataMapperを使ってみる

| 00:11 | DataMapperを使ってみるを含むブックマーク

DataMapper (Ruby向けO/Rマッパー) 以前使ったことがあるものの、最近のバージョンは触っていないので改めて試してみました。

動作環境

DataMapperのインストール

DataMpper 1.2.0 リリースノートより:

# gem install data_mapper dm-sqlite-adapter

実際に試してはいませんが、おそらく事前にlibsqlite3-dev (Ubuntu/Debianの場合) のインストールが必要です。

以下のサンプルプログラムは、DataMpper公式サイト内のGetting Startedを若干アレンジしたものです。

モデル定義

ブログ記事を表現するPost、ブログ記事へのコメントを表現するCommentの2つのモデルオブジェクトを定義します。

モデル定義は、この後作成するスクリプトからrequireできるように単独のファイルとして記述します。

ここでは、テーブルに相当するモデルオブジェクトに属性 (プロパティ) を定義するとともに、オブジェクト間の関連 (association) を has n, belongs_toで定義します。

【サンプルコード】dm_sample_model.rb

require 'data_mapper'

# ブログ記事
class Post
  include DataMapper::Resource

  property :id, Serial
  property :title, String
  property :body, Text
  property :created_at, DateTime

  has n, :comments
end

# コメント
class Comment
  include DataMapper::Resource

  property :id, Serial
  property :posted_by, String
  property :body, Text

  belongs_to :post
end

DataMapper.finalize

マイグレーション

作成したモデル定義に従って、データベース上にテーブル定義を作成します。

ここではデータベースとしてSQLiteを使うため、SQLiteデータベースの接続を記述します。

【サンプルコード】dm_sample_migration.rb

require 'data_mapper'
require 'dm-migrations'
require_relative 'dm_sample_model' # モデル定義

DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite:///tmp/project.db3')

DataMapper.auto_migrate!

【実行結果】

$ ruby dm_sample_migration.rb 
 ~ (0.000342) PRAGMA table_info("posts")
 ~ (0.000034) PRAGMA table_info("comments")
 ~ (0.000025) SELECT sqlite_version(*)
 ~ (0.000057) DROP TABLE IF EXISTS "posts"
 ~ (0.000014) PRAGMA table_info("posts")
 ~ (0.016498) CREATE TABLE "posts" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" VARCHAR(50), "body" TEXT, "created_at" TIMESTAMP)
 ~ (0.000076) DROP TABLE IF EXISTS "comments"
 ~ (0.000014) PRAGMA table_info("comments")
 ~ (0.008521) CREATE TABLE "comments" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "posted_by" VARCHAR(50), "body" TEXT, "post_id" INTEGER NOT NULL)
 ~ (0.002999) CREATE INDEX "index_comments_post" ON "comments" ("post_id")

念のため、sqlite3コマンドで生成されたテーブル定義を見てみます。

モデル定義に含まれる関連に従って、commentsテーブル (Commentクラスに対応) に post_id という属性が自動的に定義されていることが分かります。

$ sqlite3 /tmp/project.db3
sqlite> .schema
CREATE TABLE "comments" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "posted_by" VARCHAR(50), "body" TEXT, "post_id" INTEGER NOT NULL);
CREATE TABLE "posts" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" VARCHAR(50), "body" TEXT, "created_at" TIMESTAMP);
CREATE INDEX "index_comments_post" ON "comments" ("post_id");

(余談) はまりポイント

dm_sample_migration.rbから、同じディレクトリ上にあるモデル定義 (dm_sample_model.rb) を以下のようにしてもロードに失敗します。

require 'data_mapper'
require 'dm-migrations'
require 'dm_sample_model'
..

【実行結果】

$ ruby dm_sample_migration.rb
/usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:55:in `require': cannot load such file -- dm_sample_model (LoadError)
	from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:55:in `require'
	from dm_sample_migration.rb:3:in `<main>'

irbからライブラリ検索パス ($:) を確認してみると、カレントディレクトリ ('.') が含まれていないことが分かります。

$ irb
irb(main):001:0> $:
=> ["/usr/local/lib/ruby/site_ruby/1.9.1", "/usr/local/lib/ruby/site_ruby/1.9.1/x86_64-linux", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/vendor_ruby/1.9.1", "/usr/local/lib/ruby/vendor_ruby/1.9.1/x86_64-linux", "/usr/local/lib/ruby/vendor_ruby", "/usr/local/lib/ruby/1.9.1", "/usr/local/lib/ruby/1.9.1/x86_64-linux"]

結論としては、古いバージョンのRubyではライブラリ検索パス ($:) にカレントディレクトリが含まれていたのが、Ruby 1.9.2から含まれなくなり、代わりにrequire_relativeを使う必要があります。

記事の投稿

次に、新規のPostオブジェクトデータベースに追加します。

実際のアプリケーションでは記事投稿フォームなどのUIを通して投稿することになりますが、ここではコマンドラインで実行します。

【サンプルコード】dm_sample_post.rb

# -*- coding: utf-8 -*-
require 'data_mapper'
require_relative 'dm_sample_model'

DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite:///tmp/project.db3')

# Postオブジェクトの永続化
post = Post.create(
  :title      => "DataMapper記事の投稿",
  :body       => "記事本文です。",
  :created_at => Time.now
)

【実行結果】

$ ruby dm_sample_post.rb 
 ~ (0.007423) INSERT INTO "posts" ("title", "body", "created_at") VALUES ('DataMapper記事の投稿', '記事本文です。', '2013-03-03T23:26:59+09:00')

ここで、テーブル作成のときと同様に、sqlite3コマンドでデータベースの内容を確認してみます。

$ sqlite3 /tmp/project.db3
sqlite> select * from posts;
1|DataMapper記事の投稿|記事本文です。|2013-03-03T23:26:59+09:00

記事の検索

DataMapperで永続化したオブジェクトの検索方法はいくつかありますが、ここではfirst (条件にマッチする最初のオブジェクトを取得) を使います。

ちょっと面白いのは、検索した時点ではすべての属性は取得しておらず、属性を参照した時点でSQLのSELECT文が発行される点です (遅延ローディング: lazy loading)。

【サンプルコード】dm_sample_find.rb

# -*- coding: utf-8 -*-
require 'data_mapper'
require 'pp'
require_relative 'dm_sample_model'

DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite:///tmp/project.db3')

post = Post.first(:title => "DataMapper記事の投稿")
pp post
puts "[id] #{post.id}"
puts "[title] #{post.title}"
puts "[body] #{post.body}"
puts "[created_at] #{post.created_at}"

【実行結果】

$ ruby dm_sample_find.rb 
 ~ (0.000358) SELECT "id", "title", "created_at" FROM "posts" WHERE "title" = 'DataMapper記事の投稿' ORDER BY "id" LIMIT 1
#<Post @id=1 @title="DataMapper記事の投稿" @body=<not loaded> @created_at=#<DateTime: 2013-03-03T23:26:59+09:00 ((2456355j,52019s,0n),+32400s,2299161j)>>
[id] 1
[title] DataMapper記事の投稿
 ~ (0.000038) SELECT "id", "body" FROM "posts" WHERE "id" = 1 ORDER BY "id"
[body] 記事本文です。
[created_at] 2013-03-03T23:26:59+09:00

作成したスクリプトによる出力とDataMapperのログが混在してやや分かりづらいですが、ppによる出力時点では @body=<not loaded> となっていて、その後SELECT文が発行されている様子が観察できます。

コメントの投稿

さらに、先ほどの記事に対するコメントの投稿を試してみます。

基本的には記事の投稿と同様ですが、関連 (association) の定義に従って、Commentオブジェクトのpost属性にPostオブジェクトをセットすることで、どの記事に対するコメントかを指定することができます (データベース上のpost_id属性に相当)。

【サンプルコード】dm_sample_comment.rb

# -*- coding: utf-8 -*-
require 'data_mapper'
require_relative 'dm_sample_model'

DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite:///tmp/project.db3')

post = Post.first(:title => "DataMapper記事の投稿")

comment = Comment.create (
  :posted_by => "m-kawato",
  :body => "コメントです。",
  :post => post
)

【実行結果】

$ ruby dm_sample_comment.rb 
 ~ (0.000359) SELECT "id", "title", "created_at" FROM "posts" WHERE "title" = 'DataMapper記事の投稿' ORDER BY "id" LIMIT 1
 ~ (0.000041) SELECT "id", "body" FROM "posts" WHERE "id" = 1 ORDER BY "id"
 ~ (0.015866) INSERT INTO "comments" ("posted_by", "body", "post_id") VALUES ('m-kawato', 'コメントです。', 1)

さらに、データベースの内容をsqlite3コマンドで確認してみます。

$ sqlite3 /tmp/project.db3
sqlite> select * from comments;
1|m-kawato|コメントです。|1

まとめ

この記事では、ブログ記事とコメントの投稿・検索を題材とした簡単なサンプルを通して、O/RマッパーDataMapperの基本的な機能を確認しました。

2013-01-14

Ubuntu 12.10上でのavconv (旧ffmpeg) を使ったMP3エンコード

| 18:23 | Ubuntu 12.10上でのavconv (旧ffmpeg) を使ったMP3エンコードを含むブックマーク

Ubuntu 12.10上で動画ファイル変換ツールavconv (ffmpegからフォークして名称変更したらしい) を使ってMP3エンコードする方法についてメモ。

参考情報: [SOLVED] Can’t convert to mp3... avconv: libmp3lame not found!

単にavconvとlibmp3lame0を入れただけの状態ではMP3エンコードしてくれないようです。

$ avconv -i infile.flv -c:a libmp3lame -b:a 192k outfile.mp3 
avconv version 0.8.4-6:0.8.4-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers
  built on Nov  6 2012 16:49:20 with gcc 4.7.2
[flv @ 0x8b770c0] Estimating duration from bitrate, this may be inaccurate
Input #0, flv, from 'infile.flv':
(略)
    Stream #0.0: Video: flv, yuv420p, 320x180, 765 kb/s, 1k tbr, 1k tbn, 1k tbc
    Stream #0.1: Audio: nellymoser, 44100 Hz, mono, s16, 88 kb/s
Unknown encoder 'libmp3lame'

「参考情報」に挙げたページによると、"ubuntu-restricted-extras" というパッケージを入れれば良いらしいということで、とりあえず何も考えずに入れてみたら無事エンコードできました。

$ sudo apt-get install ubuntu-restricted-extras

$ avconv -i infile.flv -c:a libmp3lame -b:a 192k outfile.mp3 
avconv version 0.8.4-6:0.8.4-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers
  built on Nov  6 2012 16:49:20 with gcc 4.7.2
[flv @ 0x9e56880] Estimating duration from bitrate, this may be inaccurate
Input #0, flv, from 'infile.flv':
(略)
    Stream #0.0: Video: flv, yuv420p, 320x180, 765 kb/s, 1k tbr, 1k tbn, 1k tbc
    Stream #0.1: Audio: nellymoser, 44100 Hz, mono, s16, 88 kb/s
Output #0, mp3, to 'outfile.mp3':
(略)
    Stream #0.0: Audio: libmp3lame, 44100 Hz, mono, s16, 192 kb/s
Stream mapping:
  Stream #0:1 -> #0:0 (nellymoser -> libmp3lame)
Press ctrl-c to stop encoding
size=  116303kB time=4962.25 bitrate= 192.0kbits/s    
video:0kB audio:116303kB global headers:0kB muxing overhead 0.000490%

apt-get install ubuntu-restricted-extrasで複数のパッケージがインストールされるので、avconv+libmp3lameの必要条件は特定できませんでしたが、おそらくlibavcodec-extra-53あたりが肝かと思います。

なお、今回変換元に使ったFLVファイルではNellymoserというオーディオコーデックが使われており、古めのプレイヤーや変換ツールでは扱えないようです (という動機でavconvを使う方法を試しました)。

2013-01-05

(メモ) Rails+OmniAuthによるTwitterログイン

| 00:18 | (メモ) Rails+OmniAuthによるTwitterログインを含むブックマーク

Ruby/Rails向けの認証連携フレームワークの定番らしいOmniAuthを使って、OAuth経由でTwitterに投稿するサンプルRailsアプリを作ってみました。

参考にしたサイト:

「簡単なOmniAuth」に詳細な使い方が説明されていますが、現在のOmniAuth 1.1と合っていない箇所があるので、適宜公式ドキュメントを参照しています。

動作環境:

Twitterアプリケーション登録

まず準備作業として、Twitterの開発者サイト (https://dev.twitter.com/) で新規のアプリケーションを登録します。開発者サイトの構成は割と良く変わるようですが、この記事を書いた時点では、ログインした状態で右上の自分のアイコンマウスオーバー→My Applicationで行けるようです。

f:id:m-kawato:20130105221111p:image:w500

My applicationsから "Create a new application" を選択し、必要な情報を入力します。ここで重要なのは "Callback URL" で、TwitterWebサイト上でユーザ認証した後に、ここに入れたURLリダイレクト (コールバック) されることになります。今回は、元ネタのASCIIcasts/RailsCastsの記述に合わせて、http://127.0.0.1:3000/auth/twitter/callback とします。

あと、本筋ではありませんが、ここで作成したアプリケーションからTwitterにメッセージを投稿するために、Access TypeをRead onlyからRead and Writeに変える必要があります。この設定は新規アプリケーション作成時にはできなくて、一旦アプリを作成してからSettingsで変更する必要があるようです。

f:id:m-kawato:20130105221112p:image:w500

アプリケーションのページに表示されるOAuthのConsumer key・Consumer secretの内容を後で使います。

f:id:m-kawato:20130105223228p:image:w500

ライブラリを使うための準備

RailsアプリケーションからOmniAuthおよびTwitterライブラリを使うために、Gemfileへの情報追加とBundlerの実行を行います。

rails newコマンドで作成したRailsアプリ (ここではtwitter-omniauth-testとします) のルート直下にあるGemfileファイルに以下の内容を追加した後で、bundle installを実行します。

twitter-omniauth-test/Gemfileの追加内容:

....
# 以下の2行を追加
gem 'omniauth-twitter'
gem 'twitter'

アプリケーションの動作手順

ここで、OmniAuth+omniauth-twitterを使ったアプリケーションの動作手順 (ページ遷移) について整理しておきます。

f:id:m-kawato:20130105230857p:image

  1. まず、ユーザはアプリケーションのトップ画面をブラウザで開きます。この中にある "Sign in with Twitter" のリンクをクリックすると、omniauth-twitterの制御下に移ります。このURLは /auth/twitter となります。
  2. omniauth-twitterは、OAuthのアクセストークンを取得するため、Twitterのサイトにリダイレクトします。
  3. Twitterサイトとユーザの間で認証処理を行います。すでにユーザがTwitterログイン済みである場合には、ユーザは何もせずに4.に進むことになります。
  4. TwitterサイトからOAuthコールバックURL (Twitter開発者サイトで入力したもの) にリダイレクトします。
  5. OAuthコールバックURLに対応するコントローラの中で、認証に成功したユーザについてのセッションを作成します。具体的には、Twitterから発行されたアクセストークンの格納を行います。
  6. OAuthコールバックURLからアプリケーションのトップ画面にリダイレクトします。この状態では、ユーザはすでにログイン済みなので、"Sign in with Twitter" の代わりに "Sign out" のリンクが現れます。

この動作手順のうち、1、5、6の部分はアプリケーション内で記述する必要があり、それに加えてomniauth-twitterを使うための記述が必要になります。

OmniAuth初期化スクリプトの作成

omniauth-twitterに対してOAuthのConsumer Key/Secretをセットするための初期化スクリプトを追加します。

twitter-omniauth-test/initializers/omniauth.rb:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, CONSUMER_KEY, CONSUMER_SECRET
end

CONSUMER_KEY/SECRETには、先ほど取得したConsumer key/secretの内容を入れます。

アプリケーションのトップ画面

ここではビューの中で、ユーザのログイン状態に応じて、ログイン/ログアウト用のリンクを生成します。

コントローラの中で、ユーザがログイン状態であるかどうかを判別するためのヘルパーメソッドを定義します。今回はRailsセッション機能をそのまま使って、セッション情報にOAuthのアクセストークンが含まれていればログイン状態と判断しています。

twitter-omniauth-test/app/controllers/application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :signed_in?

  private
  def signed_in?
    true if session[:oauth_token]
  end 
end

session[:auth_token] の格納については後述します。

ビューでは、先ほど定義した signed_in? メソッドを用いて表示するリンクを切り替えます。

twitter-omniauth-test/app/views/layouts/application_controller.html.erb:

<body>
  <div id="container">
    <div id="user_nav">
      <% if signed_in? %>
        Welcome <%= session[:username] %>!
        <%= link_to "Sign Out", "/signout" %>
      <% else %>
        <%= link_to "Sign in with Twitter", "/auth/twitter" %>
      <% end %>
    </div>
  <%= yield %>
  </div>
</body>

ここで、未ログイン状態のユーザが "Sign in with Twitter" のリンクをクリックすると、omniauth-twitterを介してTwitterサイトにリダイレクトされることになります。

セッションの作成

Twitterサイトでの認証に成功すると、http://localhost:3000/auth/twitter (Twitter開発者サイトで指定したコールバックURL) にリダイレクトされます。

このURLコントローラsessionsのアクションcreateで処理するために、ルーティングの設定を追加します。

twitter-omniauth-test/config/routes.rb:

TwitterOmniauthTest::Application.routes.draw do
  root :to => "tweet#input"
  get "tweet/input"
  post "tweet/update"
  match "/auth/:provider/callback" => "sessions#create"
  match "/signout" => "sessions#destroy"
end

OAuthを用いた認証に成功すると、OmniAuthにより request.env["omniauth.auth"] にアクセストークンなどの情報がセットされるので、sesssions#createではこれらの情報を取得します。参照元のRailsCastではモデルオブジェクトに情報をセットしていますが、ここでは安直にsessionに入れています。

(RailsデフォルトではCookieに入ってクライアント側に渡ることになりますが、本来はサーバ側でDBなどに格納するのが正しいはずです)

class SessionsController < ApplicationController
  def create
    auth = request.env["omniauth.auth"]
    session[:oauth_token] = auth.credentials.token
    session[:oauth_token_secret] = auth.credentials.secret
    session[:username] = auth.extra.access_token.params[:screen_name]
    redirect_to root_url, :notice => "Signed in!"
  end

  def destroy
    session[:oauth_token] = nil
    session[:oauth_token_secret] = nil
    session[:username] = nil
    redirect_to root_url, :notice => "Signed out!"
  end
end

ツイート送信

OAuthに関する処理はこれで完了ですが、取得したアクセストークンを使ってTwitterにアクセスできることを確認します。

アプリケーションのトップ画面に以下のようなフォームを作成して、フォームに入力したメッセージをTwitterに送信します。

twitter-omniauth-test/app/views/tweet/input.html.erb:

<h1>Twitter Sample Application</h1>
<p>Enter a message:</p>
<%= form_tag({:action => "update"}, {:method => "post"}) do %>
  <%= text_field_tag(:message) %>
  <%= submit_tag("Submit") %>
<% end %>

ブラウザから見た画面はこんな感じになります。

f:id:m-kawato:20130106001132p:image:w400

tweet#update のコントローラでは、先ほど取得したアクセストークンを使用してツイートを投稿します。

twitter-omniauth-test/app/controllers/tweet_controller.rb:

class TweetController < ApplicationController
  def input
  end

  def update
    if signed_in?
      client = Twitter::Client.new(
        :oauth_token => session[:oauth_token],
        :oauth_token_secret => session[:oauth_token_secret]
      )
      client.update(params[:message])
      @result = :success
    else
      @result = :not_signed_in
    end
  end
end

2012-12-22

(メモ) Google APIを呼び出すためのOAuth 2.0認可処理

| 00:25 | (メモ) Google APIを呼び出すためのOAuth 2.0認可処理を含むブックマーク

まだちゃんと動くところまで行っていませんが、現時点までの作業メモ。

目的は、Google Calendar APIを用いたWebアプリ (スケジュール入力支援) をRuby on Railsで作ることです。

Google APIにはRuby用のクライアントライブラリも提供されていることもあり、API呼び出し自体はそれほど難しそうではないものの、アクセス権の取得のためにOAuth 2.0への対応が必要になり、むしろこちらの方が手間がかかりそうです。

使用ソフトウェアとバージョン

環境構築 (Google API)

まずGoogle APIを使うための下準備をします。必要な作業は以下の2つ。

いずれもGoogle Calendar APIホームページからたどれるドキュメントを参照して問題なく完了しました。

なお、Google APIRubyクライアントライブラリは現在alpha版とのことで、まだ実運用環境で使える段階ではないようです。

OAuth 2.0認可処理 (スタンドアロン版)

Railsとの組み合わせの前に、Ruby版Google APIクライアントライブラリ に載っているサンプルを元に、スタンドアロン (というかirb) でOAuth2の挙動を確認します。

途中のステップで、Googleのサイトでの承認操作を行ったあと、そこで発行されるauthorization codeが必要になる都合上、ここではirbを用います。途中で登場する <Client ID>, <Client Secret> には、Google APIコンソールから取得した文字列が入ります。

$ irb
irb(main):001:0> require 'google/api_client'
=> true
irb(main):002:0> client = Google::APIClient.new
=> #<Google::APIClient:0x0000000182fbd0 ... >
irb(main):003:0> client.authorization.client_id = <Client ID>
=> <Client ID>
irb(main):004:0> client.authorization.client_secret = <Client Secret>
=> <Client Secret>
irb(main):005:0> client.authorization.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
=> "urn:ietf:wg:oauth:2.0:oob"
irb(main):006:0> client.authorization.scope = 'https://www.googleapis.com/auth/plus.me'
=> "https://www.googleapis.com/auth/plus.me"
irb(main):007:0> redirect_uri = client.authorization.authorization_uri
=> #<Addressable::URI:0xc06fc0 URI:https://accounts.google.com/o/oauth2/auth?... >

上記引用部分最後に出てくる URI:... の部分がGoogleに対する承認操作を行うためのURLです。ブラウザからこのURLにアクセスすると、以下のように許可を求められます。ここで「アクセスを許可」を選択すると、Googleログインしたアカウントの権限で、「Googleでのユーザの把握」という許可をアプリケーション (ここではirb上で動かしているもの) に与えることになります。

f:id:m-kawato:20121223000608p:image

ここで「アクセスを許可」を選択した結果、以下のようなコードが出力されます。

f:id:m-kawato:20121223000609p:image

以下、irbに戻って、先ほど出力されたコードを張り付けることでOAuth 2.0を用いた認可処理が完了になります。

irb(main):008:0> client.authorization.code = '4/g8B6U7tySrGFXRFvpamZ_KkcEOW2.QiOkz9dGebYXgrKXntQAax0O2E6GdwI'
=> "4/g8B6U7tySrGFXRFvpamZ_KkcEOW2.QiOkz9dGebYXgrKXntQAax0O2E6GdwI"
irb(main):009:0> client.authorization.fetch_access_token!
=> {"access_token"=>"ya29.AHES6ZQ (略)", "token_type"=>"Bearer", "expires_in"=>3600, "id_token"=>"eyJhbGc (略)", "refresh_token"=>"1/vYol_NH (略)"}
irb(main):010:0> result = client.execute(:api_method => client.discovered_api('plus').activities.list, :parameters => {'collection' => 'public', 'userId' => 'me'})
=> #<Google::APIClient::Result:0x00000001adadd0 @request=...>

ここまで一応成功しているようです。