acts_as_authenticatedの使い方 - その2

ActionMailerの設定

前回のacts_as_authenticatedプラグインを使って、ActionMailerの設定を行う。acts_as_authenticatedプラグインが用意しているジェネレータのうち、authenticated_mailerを実行する。

$ ./script/generate authenticated_mailer user
      exists  app/models/
      create  app/views/user_notifier
      exists  test/unit/
      create  app/models/user_notifier.rb
      create  app/models/user_observer.rb
      create  test/unit/user_notifier_test.rb
      create  app/views/user_notifier/activation.rhtml
      create  app/views/user_notifier/signup_notification.rhtml

ここで生成されるuser_observer.rbはuserモデル(app/model/user.rb)のオブザーバ用コードで、userモデルに対するCRUD操作に対して自動的に呼び出されるハンドラを定義している。authenticated_mailerがデフォルトで生成するコードは以下の通り。

class UserObserver < ActiveRecord::Observer
  def after_create(user)
    UserNotifier.deliver_signup_notification(user)
  end

  def after_save(user)
    UserNotifier.deliver_activation(user) if user.recently_activated?
  end
end

デザインパターンで言うところのObserverパターンと同じで、あるオブジェクトの状態が変化した時に、それに依存するオブジェクトにそのことが自動的に通知される仕組みを実装している。
このオブザーバの存在をActiveRecordに知らせるために、config/environment.rbに以下のコードを追加する。これはコードブロック Rails::Initializer.run do |config| の中に書く。

config.active_record.observers = :user_observer

UserObserverに対して定義できるコールバックは、こちらのページに記載されている。

authenticated_mailerジェネレータで生成したコードでは日本語のメールをそのまま扱うことができないので、メールをiso-2022-jp化するためのプラグインであるActiveHeartを組み込んでおく。ActiveHeartのうち、日本語メールの部分だけを利用したいので、script/plugin installコマンドは使わずに、必要なファイルだけをlibディレクトリにダウンロードする。

wget http://svn.rails2u.com/public/plugins/trunk/active_heart/lib/iso2022jp_mailer.rb

次にmodel/user_notifier.rbのクラスを宣言のところで、以下のようにActionMailer::Baseではなく、Iso2022jpMailerからサブクラス化するように変更する。

#class UserNotifier < ActionMailer::Base  #コメント化
class UserNotifier < Iso2022jpMailer

また、UserNotifierの各メソッドを以下のように修正する。

        :
        :
  def signup_notification(user)
    setup_email(user)
    @subject    += 'Please activate your new account'
#    @body[:url]  = "http://YOURSITE/account/activate/#{user.activation_code}"
    @body[:url]  = "http://localhost:3000/account/activate/zzzzzzzzz"
  end

  def activation(user)
    setup_email(user)
    @subject    += 'Your account has been activated!'
#    @body[:url]  = "http://YOURSITE/"
    @body[:url]  = "http://localhost:3000/"
  end

  protected
  def setup_email(user)
    @recipients  = "#{user.email}"
#    @from        = "ADMINEMAIL"
    @from        = "自分のメールアドレス"
#    @subject     = "[YOURSITE] "
    @subject     = "[localhost:3000] "
    @sent_on     = Time.now
    @body[:user] = user
  end
end

ActionMailerはメールの送信のためにいくつかの設定を予め実施しておかなければならない。以下の設定はconfig/environment.rbに追加しておく。

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.default_charset = "iso-2022-jp"

ActionMailer::Base.smtp_settings = {
  :address => "自分のSMTPサーバのアドレス名",
  :port => 25,
  :domain => "自分のドメイン名(HELOドメインのこと)",
  :authentication => :login,
  :user_name => "自分のSMTPサーバのユーザアカウント名",
  :password => "自分のSMTPサーバのパスワード",
}

そしてscript/consoleから、以下のようにUserクラスを初期化して、deliver_signup_notificationを呼び出すと、自分のメールアドレスにメールが送信されるはずだ。

>> user = User.new(:email=>"自分のメールアドレス", :login=>"登録する名前(半角)", :password=>"登録するパスワード(半角)")
>> UserNotifier.deliver_signup_notification(user)

到着したメールは以下のようになっている。

Your account has been created.

  Username: yourname
  Password: yourpass

Visit this url to activate your account:

  http://localhost:3000/account/activate/zzzzzzzzz

ここまでで、メール送信の設定は終了したことになるが、メールの中身も日本語にしてみよう。以下のようにapp/views/user_notifier/signup_notification.rhtmlを日本語に書き換える。

アカウントが生成されました。

  Username: <%= @user.login %>
  Password: <%= @user.password %>

以下のURLにアクセスしてアカウントをアクティベートしてください。

  <%= @url %>

これで再度メールを送信すれば、日本語のiso-2022-jpになったメールが到着するはずだ。

acts_as_authenticatedの使い方 - その1

まずはプラグインをインストールする。プラグインはvendor/pluginにインストールされる。


$ ./script/plugin discover
$ ./script/plugin install acts_as_authenticated
script/generatorではvendor/pluginにインストールされた以下のジェネレータを起動できるようになっている。

Plugins: authenticated, authenticated_mailer
authenticatedジェネレータを使って認証用コードを生成するには以下のようにモデル名(user)とコントローラ名(account)名を指定する。

$ ./script/generate authenticated user account
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/account
exists test/functional/
exists test/unit/
create app/models/user.rb
create app/controllers/account_controller.rb
create lib/authenticated_system.rb
create lib/authenticated_test_helper.rb
create test/functional/account_controller_test.rb
create app/helpers/account_helper.rb
create test/unit/user_test.rb
create test/fixtures/users.yml
create app/views/account/index.rhtml
create app/views/account/login.rhtml
create app/views/account/signup.rhtml
create db/migrate
create db/migrate/001_create_users.rb
自動的にマイグレート用コードも生成されるので、データベーステーブルを生成しておく。
$ rake db:migrate
生成されるテーブル構造は以下の通り。

                                                                                                      • -
Table Create Table
                                                                                                      • -
users CREATE TABLE `users` (

`id` int(11) NOT NULL auto_increment,
`login` varchar(255) default NULL,
`email` varchar(255) default NULL,
`crypted_password` varchar(40) default NULL,
`salt` varchar(40) default NULL,
`created_at` datetime default NULL,
`updated_at` datetime default NULL,
`remember_token` varchar(255) default NULL,
`remember_token_expires_at` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

                                                                                                      • -

authenticatedジェネレータが生成したaccountコントローラにはindex, login, signup, logoutが含まれている。
indexメソッドを変更し、ログインしていない時にはログインフォームを表示するようにする。

  def index
  # redirect_to(:action => 'signup') unless logged_in? || User.count > 0
    unless User.count > 0
      redirect_to(:action => 'signup')
      return
    end
    redirect_to(:action => 'login') unless logged_in?
  end

もともと存在しているuserレコードが1つも存在していない時はsignupへリダイレクトするという処理は残しておく。(運用時の最初の一回しか呼ばれないのであまり意味はない)
app/views/account/index.rhtmlにあるポエムは削除し、代わりに現在のユーザのログインステートを表示する。

<% if logged_in? %>
  <p>You are logged in</p>
<% else %>
  <p>You are not logged in</p>
<% end %>

RailsによるアジャイルWebアプリケーション開発 第2版がそろそろ発売

RailsによるアジャイルWebアプリケーション開発」の第2版が出版されるらしいです。ISBNなどはこちらにあります。私にとってはRails本として一番最初に購入した思い出深い本になります。といってもまだ1年半しか経ってないんですね。この第2版はオリジナルの英語版が2006年の12月に出ているので、情報としてはそれほど新しいものではないと思いますが、細かい辞書的な使い方としてはいいかもしれません。それでも、世の中はもうすぐ2.0のリリースがやってきます。まだまだRailsドッグイヤーですね。

Rails 2.0 Preview Releaseのインストール

2.0 Previewの一番簡単なインストール方法は、svnコマンドでvendor/railsにローカルコピーをエクスポートする方法だと思う。


mkdir -p test/vendor
cd test
svn co http://dev.rubyonrails.org/svn/rails/tags/rel_2-0-0_PR vendor/rails

これでvendor/railsに2.0 Previewがエクスポートされる。

既存のRailsプロジェクトではrakeコマンドを使用できる。


rake rails:freeze:edge TAG=rel_2-0-0_PR

いずれの場合もrailsコマンドを一度実行しなければならない。


ruby vendor/rails/railties/bin/rails .

Yahoo REST APIの使い方

REST方式のWeb APIの良いところはその呼び出し方法が簡単なところにあるわけですが、ここではYahoo!の検索APIを使ってみます。取得されたデータをきれいに整形して表示するにはJavascriptを使ったAJAX的手法とすべきですが、単純にAPIを呼び出すだけなら、HTMLのformでも可能です。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Yahoo! REST APIサンプル (超簡単版)</title>
</head>
<body>
<h2>フォーム内容</h2>
<form action="http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch" method="GET">
<input type="hidden" name="appid" value="YahooDemo">
検索文字列:<INPUT type="text" name="query">
<input type="hidden" name="result" value="2">
<input type="submit">
</form>
</body>
</html>

これはブラウザに以下のURLを指定するのと同じことです。あくまでもAPIを呼び出してXMLを取得するだけならこれでもよいわけです。

http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?appid=YahooDemo&query=test&result=2

Yahoo APIの仕様にもある通りUTF-8を使っています。

Edge Railsのインストール

EdgeRailsのインストールはsvnコマンドで最新のリビジョンからローカルコピーを取得することで行なえます。


mkdir -p drop_of_today/vendor
cd drop_of_today/
svn co http://dev.rubyonrails.org/svn/rails/trunk vendor/rails

これでvendorディレクトリ以下に最新のリビジョンがコピーされます。次にコピーされたrailsコマンドをカレントディレクトリに対して実行します。


ruby vendor/rails/railties/bin/rails .

あとはscript/serverやscript/generateなどで動作を確認します。この方法はカレントディレクトリ配下にコピーを生成するのでgemでインストールしたRails (/usr/local/bin/railsなど)には影響を与えません。

RESTfulなscaffold

EdgeRailsをインストールして最新のRails(たとえばリビジョン7507など)のscaffoldを生成してみるとわかりますが、現行1.2.3のscaffoldは既に廃止され、scaffold_resourceのようにRESTfulなscaffoldに変更されています。

./script/generate scaffold model_nameを行った後、試しに以下のようなリクエストを行ってみると、


http://localhost:3000/profiles/1.xml
次のようなXMLが返されます。




2007-06-05T01:25:24+09:00
user-name
1
xxxxxxx

REST指向であるRailsとしては正しい方向性を提案しているということなのでしょう。ただし、このままだと入門として今までお世話になってきたscaffoldは次回のバージョンからは使えないということになってしまいそうです。また、scaffold_resourceジェネレータは既に存在していません。