Skip to content

Commit

Permalink
Merge branch 'master' of github.com:defaude/asciicasts.com-translations
Browse files Browse the repository at this point in the history
  • Loading branch information
eifion committed Aug 8, 2011
2 parents 0207c71 + fb4e1ac commit a7485e4
Show file tree
Hide file tree
Showing 4 changed files with 419 additions and 3 deletions.
2 changes: 1 addition & 1 deletion episodes/000_summaries/summaries_ja.html
Expand Up @@ -2,7 +2,7 @@
Deviseはフル機能の認証手法で、すべてのコントローラロジックとフォームビューを自動的に処理します。今回のエピソードでその設定方法を学びましょう。
[authentication, plugins, rails-30]
210 - Deviseのカスタマイズ
In this episode we continue looking at devise with a focus on customizing its views, routing and validations.
今回のエピソードでは引き続きdeviseを見ていきますが、今回は特にビュー、ルーティング、バリデーションのカスタマイズ方法を取り上げます。
[rails-30, plugins, authentication]
241 - 簡単なOmniAuth
ユーザ名、パスワードを持つ必要がなかったり、ユーザごとに複数の認証を行わなくてもいい場合、OmniAuthで簡単に認証のしくみを付加できます。
Expand Down
253 changes: 253 additions & 0 deletions episodes/210/ja.html
@@ -0,0 +1,253 @@
<p>前回のエピソード[<a href="http://railscasts.com/episodes/209-introducing-devise">動画を見る</a>, <a href="http://asciicasts.com/episodes/209-introducing-devise">読む</a>]で、Railsアプリケーションでユーザ認証を行うために<a href="http://github.com/plataformatec/devise">devise</a>を設定する方法を紹介しました。今回は、前回から引き続いてdeviseをカスタマイズする方法を見ていきます。</p>

<p>前回と同じアプリケーションを使うので、登録、ログイン、ログアウトのページがあり、すでにある程度の認証のしくみができています。</p>

<div class="imageWrapper">
<img src="/system/photos/368/original/E210I01.png" width="800" height="327" alt="プロジェクト管理用アプリケーション"/>
</div>

<h3>アクセスを制限する</h3>

<p>次のステップでは、ログインユーザのみに特定のアクションへのアクセスを制限します。ログインしたユーザだけがプロジェクトを作成、編集、削除できるようにします。このために<code>ProjectsController</code>を修正し<code>before_filter</code>を追加して、deviseが提供する<code>authenticate_user!</code>というメソッドを呼び出すようにします。このメソッドはユーザがログインしているかどうかを確認し、ログインしていない場合はユーザをログインページにリダイレクトします。<code>index</code><code>show</code>の各アクションはすべてのユーザから見えるべきなので、<code>:except</code>パラメータを追加してフィルターからこれらのアクションを除外します。</p>

<p class="codeFilePath">/app/controllers/projects_controller.rb</p>
<pre class="ruby">
class ProjectsController &lt; ApplicationController

before_filter :authenticate_user!, :except =&gt; [:show, :index]

def index
#rest of class
</pre>
<p>「新規プロジェクト(New Project)」リンクをクリックすると、ログインしていない場合はログインページにリダイレクトされます。</p>

<div class="imageWrapper">
<img src="/system/photos/369/original/E210I02.png" width="801" height="475" alt="新規プロジェクトを作成しようとするとログインページにリダイレクトされる"/>
</div>

<p>認証が単純でユーザがログインしているかどうかを確認するだけでよければ、この手法でうまくいくでしょう。より複雑な認証のニーズに対しては、エピソード192 [<a href="http://railscasts.com/episodes/192-authorization-with-cancan">動画を見る</a>, <a href="http://asciicasts.com/episodes/192-authorization-with-cancan">読む</a>]で紹介したCanCanのような追加の認証ツールをdeviseと一緒に使用することができます。</p>

<h3>Deviseのビューをカスタマイズする</h3>

<p>次にdeviseのビューの見え方をカスタマイズする方法を紹介します。すでにサイトの見た目をかなり作り込んでいる場合、deviseが提供するフォームも他のページに合うデザインにしたいでしょう。deviseはRailsエンジンなのでそれ自身がビューを持っていますが、アプリケーションにビューを追加することで簡単にオーバーライドできます。deviseはまたそれらのビューを簡単にコピーするためのジェネレータも提供します。アプリケーションのディレクトリから<code>rails generate devise_views</code>を実行すると、ビューファイルが自動的に作成されます。</p>
<pre class="terminal">
$ rails generate devise_views
create app/views/devise
create app/views/devise/confirmations/new.html.erb
create app/views/devise/mailer/confirmation_instructions.html.erb
create app/views/devise/mailer/reset_password_instructions.html.erb
create app/views/devise/mailer/unlock_instructions.html.erb
create app/views/devise/passwords/edit.html.erb
create app/views/devise/passwords/new.html.erb
create app/views/devise/registrations/edit.html.erb
create app/views/devise/registrations/new.html.erb
create app/views/devise/sessions/new.html.erb
create app/views/devise/shared/_links.erb
create app/views/devise/unlocks/new.html.erb
</pre>

<p>このコマンドですべてのビューがRailsエンジンであるdeviseからコピーされるので、それらを目的に合うように編集することができます。例えば下のコードは前に見たログインページ用のビューです。</p>

<pre class="codeFilePath">/app/views/devise/sessions/new.html.erb</pre>
<pre class="ruby">
&lt;h2&gt;Sign in&lt;/h2&gt;

&lt;%= form_for(resource_name, resource, :url =&gt; session_path(resource_name)) do |f| %&gt;
&lt;p&gt;&lt;%= f.label :email %&gt;&lt;/p&gt;
&lt;p&gt;&lt;%= f.text_field :email %&gt;&lt;/p&gt;

&lt;p&gt;&lt;%= f.label :password %&gt;&lt;/p&gt;
&lt;p&gt;&lt;%= f.password_field :password %&gt;&lt;/p&gt;

&lt;% if devise_mapping.rememberable?-%&gt;
&lt;p&gt;&lt;%= f.check_box :remember_me %&gt; &lt;%= f.label :remember_me %&gt;&lt;/p&gt;
&lt;% end -%&gt;

&lt;p&gt;&lt;%= f.submit "Sign in" %&gt;&lt;/p&gt;
&lt;% end %&gt;

&lt;%= render :partial =&gt; "devise/shared/links" %&gt;
</pre>

<p>このページを次のように修正します。</p>

<p class="codeFilePath">/app/views/devise/sessions/new.html.erb</p>

<pre class="ruby">
&lt;% title "Sign In" %&gt;

&lt;%= form_for(resource_name, resource, :url =&gt; session_path(resource_name)) do |f| %&gt;
&lt;ol class="formList"&gt;
&lt;li&gt;&lt;%= f.label :email %&gt; &lt;%= f.text_field :email %&gt;&lt;/li&gt;
&lt;li&gt;&lt;%= f.label :password %&gt; &lt;%= f.password_field :password %&gt;&lt;/li&gt;
&lt;% if devise_mapping.rememberable?-%&gt;
&lt;li&gt;&lt;%= f.check_box :remember_me %&gt; &lt;%= f.label :remember_me %&gt;&lt;/li&gt;
&lt;% end %&gt;
&lt;li&gt;&lt;%= f.submit "Sign in" %&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;% end %&gt;
&lt;%= render :partial =&gt; "devise/shared/links" %&gt;
</pre>

<p>上のコードで、Ryan Batesの<a href="http://github.com/ryanb/nifty-generators">nifty generators</a>が提供する<code>title</code>メソッドの呼び出しでヘッダを置き換えました。つまりヘッダのテキストがページのタイトルにも現れます。(この方法はエピソード30 [<a href="http://railscasts.com/episodes/30-pretty-page-title">動画を見る</a>, <a href="http://asciicasts.com/episodes/30-pretty-page-title">読む</a>]で紹介しました。) またページのレイアウトも修正して、フォーム要素がリスト項目として表示されるようにしました。CSSでスタイルを定義することで、これを使って各テキストフィールドのラベルを移動してフィールドの横に表示させることができます。</p>

<div class="imageWrapper">
<img src="/system/photos/370/original/E210I03.png" width="800" height="394" alt="カスタマイズされたログインフォーム"/>
</div>

<p>他のすべてのビューも同じ方法でカスタマイズできるので、アプリケーションの他のページとデザインを合わせることができます。</p>

<h3>エラーメッセージをカスタマイズする</h3>

<p>Deviseは、何か間違った操作をした場合に表示するエラーメッセージをいくつか持っています。例えば、正しくないメールアドレスやパスワードを入力すると「メールアドレスかパスワードが不正です」というメッセージが表示されます。これらのメッセージはすべてlocaleファイルに保存されているので、簡単に修正したり他の言語に翻訳することが可能です。下のlocaleファイルでは<code>devise.failure.invalid</code>メッセージを修正しました。</p>

<p class="codeFilePath">/config/locales/devise.en.yml</p>
<pre class="ruby">
en:
errors:
messages:
not_found: "not found"
already_confirmed: "was already confirmed"
not_locked: "was not locked"

devise:
failure:
unauthenticated: 'You need to sign in or sign up before continuing.'
unconfirmed: 'You have to confirm your account before continuing.'
locked: 'Your account is locked.'
invalid: 'OH NOES!ERROR IN TEH EMAIL!'
invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.'
sessions:
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'
#rest of file omitted.
</pre>
<p>不正なメールアドレスでログインしようとすると、書き換えたメッセージが表示されます。</p>

<div class="imageWrapper">
<img src="/system/photos/371/original/E210I04.png" width="800" height="430" alt="カスタムのエラーメッセージが表示される"/>
</div>

<p>これでエラーメッセージは対応できましたが、deviseが表示するバリデーション(例えばユーザ登録時に誤った情報を入力した場合など)はどうすればいいでしょうか。</p>

<div class="imageWrapper">
<img src="/system/photos/372/original/E210I05.png" width="800" height="558" alt="Deviseのデフォルトのバリデーションメッセージ"/>
</div>

<p>アプリケーションの<code>/config/initializers</code>ディレクトリの中に<code>devise.rb</code>というファイルがあり、このファイルにはdeviseを設定するために使用する多くのオプションが含まれています。これらのオプションについてはドキュメントに詳しい説明があるので、変更したい場合にはどの部分を修正すればいいかが簡単にわかるでしょう。例えば、パスワードの最小文字数を6から4に変えたければ、ファイル中の該当するパートの一番下の行のコメントをはずして、必要な変更を加えます。なんらか変更を加えた後は、アプリケーションにそれを反映させるためにサーバを再起動する必要があります。</p>

<p class="codeFilePath">/config/initalizers/devise.rb</p>
<pre class="ruby">
# ==&gt; Configuration for :validatable
# Range for password length
# config.password_length = 6..20
</pre>

<p>これをさらに進めたければ、バリデーションのデフォルト設定を削除して、自分で書いたコードと置き換えます。<code>User</code>モデルの中を見ると、アプリケーションが使用しているdeviseモジュールのリストがあり、その一つが<code>:validatable</code>です。</p>

<p class="codeFilePath">/app/models/user.rb</p>
<pre class="ruby">
class User &lt; ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable and :activatable
# :confirmable,
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation
end
</pre>

<p><code>:validatable</code>モジュールは、登録時にメールアドレスとパスワードのバリデーション処理を行います。この動作を変更したい場合は、このモジュールを削除して自分でバリデーション処理を行うこともできます。しかしvalidatableモジュールはデフォルト設定のままでほとんどの用途に使えるので、今はそのままにしておきます。</p>

<h3>ルーティング</h3>

<p>次にルートのカスタマイズについて見ていきます。デフォルトでは登録ページは<code>/users/sign_up</code>にあるのですが、それを<code>/register</code>に変更します。前回のエピソードではdeviseのジェネレータで<code>devise_for :users</code>というルートを作成しました。このルートにいくつかのパラメータを指定して目的に合うようにルートを修正します。</p>

<p class="codeFilePath">/config/routes.rb</p>
<pre class="ruby">
ProjectManage::Application.routes.draw do |map|
devise_for :users

resources :projects
root :to =&gt; 'projects#index'
end
</pre>

<p>追加できるパラメータのひとつは、<code>:path_names</code>で、これを使って登録ページのルートを変更できます。</p>

<p class="codeFilePath">/config/routes.rb</p>
<pre class="ruby">
ProjectManage::Application.routes.draw do |map|
devise_for :users, :path_names =&gt; { :sign_up =&gt; "register" }

resources :projects
root :to =&gt; 'projects#index'
end
</pre>

<p>この修正によって、/users/sign_upにアクセスするとルーティングエラーが発生するようになり、代わりに<code>/users/register</code>にアクセスさせます。devise_forルートに渡すことができるオプションは他にも多くあり、そのリストを<a href="http://rdoc.info/projects/plataformatec/devise">ドキュメント</a>で参照できます。</p>

<h3>ログイン要件をカスタマイズする</h3>

<p>現在のアプリケーションではユーザのログインにメールアドレスとパスワードを用いていますが、メールアドレスの代わりにユーザ名を要求するようにしたければ、それも簡単に実現できます。</p>

<p>まず最初に<code>User</code>テーブルに<code>username</code>列を追加しますが、これをマイグレーションを作成して行います。</p>

<pre class="terminal">
$ rails generate migration add_username_to_users username:string
</pre>

<p>次にマイグレーションを実行します。</p>
<pre class="terminal">
$ rake db:migrate
</pre>

<p>データベースには1件のユーザしかないので、簡単にRailsコンソールにログインしてそのユーザのusername属性の値を設定します。</p>

<pre class="terminal">
$ rails c
Loading development environment (Rails 3.0.0.beta2)
ruby-1.8.7-p249 &gt; User.first.update_attribute(:username, "eifion")
=&gt; true
</pre>

<p>データベースを修正したのでdeviseの設定ファイルも修正します。<code>config.authentication_keys</code>の行を非コメント化して、値を<code>:email</code>から<code>:username</code>に変えます。</p>

<p class="codeFilePath">/config/initializers/devise.rb</p>
<pre class="ruby">
config.authentication_keys = [ :username ]
</pre>

<p>この値が設定されると、deviseはusernameフィールドを認証キーとして使用するようになります。またログインフォームを修正して、メールアドレスの代わりにユーザ名のフィールドを配置します。</p>

<p class="codeFilePath">/app/views/devise/sessions/new.html.erb</p>
<pre class="ruby">
&lt;% title "Sign In" %&gt;

&lt;%= form_for(resource_name, resource, :url =&gt; session_path(resource_name)) do |f| %&gt;
&lt;ol class="formList"&gt;
&lt;li&gt;&lt;%= f.label :username %&gt; &lt;%= f.text_field :username %&gt;&lt;/li&gt;
&lt;li&gt;&lt;%= f.label :password %&gt; &lt;%= f.password_field :password %&gt;&lt;/li&gt;
&lt;% if devise_mapping.rememberable?-%&gt;
&lt;li&gt;&lt;%= f.check_box :remember_me %&gt; &lt;%= f.label :remember_me %&gt;&lt;/li&gt;
&lt;% end %&gt;
&lt;li&gt;&lt;%= f.submit "Sign in" %&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;% end %&gt;

&lt;%= render :partial =&gt; "devise/shared/links" %&gt;
</pre>

<p>ユーザ登録フォームも同じように修正する必要があります。また<code>User</code>モデルの属性に検証を追加しなくてはいけませんが、ここでは省略します。</p>

<p>サーバを再起動して設定の変更を反映させたら、ログインページにアクセスしてメールアドレスの代わりにユーザ名でログインできます。</p>

<div class="imageWrapper">
<img src="/system/photos/373/original/E210I06.png" width="800" height="403" alt="ユーザ名でログインできるようになった"/>
</div>

<p>deviseのカスタマイズについての今回のエピソードはこれで終わりです。deviseはRailsアプリケーションで認証を行うための優れたツールで、デフォルト設定のままでも十分使用できますが、どのようにでもカスマイズできる柔軟性も持っています。</p>

0 comments on commit a7485e4

Please sign in to comment.