CommunityGuides 1/12 - Introduction, Authentication with Devise
http://www.communityguides.eu/articles/1
に、書いてある通りにやってみる。
my 環境
ruby 1.9.2p290
Rails 3.2.0
devise (2.0.4)
tutorialサイトの方は、Rails 3.0.5, Devise 1.1.7
プロジェクトのプランニング
例の通り「コミュニティガイド」というサイトを作る
ユーザ登録したユーザは記事を書いたり、編集。
記事はコメントや評価される。
・ひとつの記事は、一人のユーザに属す。一人のユーザは複数の記事を持てる
・ひとつのコメントは、一人のユーザとひとつの記事に属す。
・ひとつの評価は、一人のユーザとひとつの記事に属す。
・一人のユーザはひとつの国に属し、ひとつの国はたくさんのユーザを持つ。
(日本語って冗長。。。)
Model構造
Model User:
country_id
string: name, email, weburl
text: shortbio
Model Article:
user_id
string: title, version, message
text: teaser, body, changelog, freezebody
integer: state
date: submitted, accepted
Model Comment:
user_id
article_id
text: body
Model Rating:
user_id
article_id
integer: stars
Model Country:
name
xxxx_idの部分は他モデルの要素と連携。xxxxの部分に他モデルで使っている名前が入る。
ひとりのユーザはひとつの国に属す、ので Model Userにはcountry_idが必要というわけ。
作成開始
% rails new comguide
(本物はcommuniyguideでやってますが、自分は2回目なのでcomguideでやってます)
% cd comguide
% rails generate scaffold Article user_id:integer title:string teaser:text body:text version:string changelog:text message:string freezebody:text state:integer submitted:date accepted:date
% rake db:migrate
% rails server
Gemfileにgem 'devise'して
% bundle install
% rails generate devise:install
3つのことをやれというメッセージ
config/environments/development.rbに
“config.action_mailer.default_url_options = { :host => ‘localhost:3000’ }”
config/routes.rbに
root :to => “articles#index”
public/index.htmlを消してなければ消す。
views/layouts/application.html.erbに警告メッセージの枠を追加する、のは後回しにする
flash messages
deviseが使うメールアカウントの設定
テスト用にgmailアカウント取得。
config/environments/development.rb
以下追記
# Send emails via Gmail
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => 'gmail.com',
:user_name => 'テスト用アカウント@gmail.com',
:password => 'パスワード',
:authentication => 'plain',
:enable_starttls_auto => true }
deviseのバージョンのせいか、tutorialとファイル内容が少し違う。
route追加
route.rbに
resources :articles
*resourcesはCRUD系の7つの基本ルーティングをまとめて作成する。
Userモデル作成
% rails g devise User
メアド確認と失敗ログイン制限を追加。
:confirmable, :lockable
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
deviseは2.0からschema styleが変わっているらしい。
https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style
migrationファイルにも追加と書いてあるが、tutorialと違うのでcomfirmableとlockableのところのコメントアウトを全部外した。
db/migrate/….create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Encryptable
# t.string :password_salt
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
add_index :users, :confirmation_token, :unique => true
add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end
% rake db:migrate
viewを編集
application.html.erb
ログイン/ログアウト/サインアップ部
<% if user_signed_in? %>
<%= current_user.email %>
<%= link_to "My Profile", edit_user_registration_path %>
<%= link_to "Sign out", destroy_user_session_path %>
<% else %>
<%= link_to "Sign up", new_user_registration_path %>
<%= link_to "Sign in", new_user_session_path %>
<% end %>nk_to "Sign in", new_user_session_path %>
フラッシュメッセージ部分
<% flash.each do |key, value| %>
<%= value %>
<% end %>
*hashなんですね。
実は、ここで最初のscaffoldしてないことに気づいてこのタイミングでやりました。。。
ログインしていない時のアクションを限定
ariticles_controllerにbefore_filterを追記して、ログインしていない時にできるアクションをindexとshowに限定。
before_filter :authenticate_user!, :except => [:index, :show]
動作確認
登録、メアド確認などokだがsign_outするとエラー。
Routing Error
No route matches [GET] "/users/sign_out"
なぜならsign_outのroutesはDELETEメソッドだから、らしい。
http://stackoverflow.com/questions/6557311/no-route-matches-users-sign-out-devise-rails-3
application.html.erbのdestroy_user_session_pathのところに追加
:method => :delete
Signed out successfully.
1/12おわり。