railstutorial.jp 6章メモ

  • テーマ

    • ユーザ登録
    • モデル
    • バリデーション
  • 認証と権限のモジュールはたくさんあるけどここでは自前で作る

モデルは単数形で指定

$ rails generate model User name:string email:string

t.timestampsはマジックカラム

マイグレーションアップ/ダウン

$ rake db:migrate
$ rake db:rollback


$ rails db
.schema

サンドボックスモードでのDB変更は終了時に全てロールバックされる

$ rails console —sandbox

検索

User.find(3)
User.find_by_email("mhartl@example.com")
User.first
User.all

リロード

user.email
user.email = "foo@bar.com”
user.reload.email

更新

user.save
user.update_attribute(:name, "The Dude")

テスト用データベースの作成

$ rake db:migrate
$ rake test:prepare
rake aborted!
Don't know how to build task 'test:prepare'

エラー。Rails4.1で無くなったらしい。代替コマンドを実行

$ rake db:migrate RAILS_ENV=test

テストでつかわれているrespond_toはRubyのrespond_to?
シンボルが表すメソッドまたは属性に対して応答する場合はtrue、応答しない場合はfalse
要はあるかどうか、のテスト

バリデーション

validates :name, presence: true
user.save #=> false
user.valid? #=> false

エラー取得

user.errors
user.errors.full_messages

be_fooはfoo?を実行しているのと同じ

it { should be_valid }

バリデーション結果が正しくないこと

it { should_not be_valid }

文字×数字は文字数分連結と同じ

@user.name = "a" * 51

文字数チェックのバリデーション

validates :name,  presence: true, length: { maximum: 50 }

emailのバリデーション

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.freeze

validates :email, presence: true, format: {with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive:false }

uniqueness: { case_sensitive:false }で大小文字を無視してユニークチェックをする

\Aは文字列の先頭
\zは文字列の末日

正規表現エディタ http://www.rubular.com/

dupメソッドで、id, updated_at, created_atを空にした状態のコピーを作る

@user.dup

String.upcaseメソッド

インデックスを追加するマイグレーション

$ rails generate migration add_index_to_users_email
def change
  add_index :users, :email, unique: true

end
$ rake db:migrate

失敗するときはrails console —sandboxによってDBをロックしていないかを確認

モデルのコールバック
before_save

パスワードを暗号化するgem

gem bcrypt-ruby

モデルにhas_secure_passwordを書いてデータベースにpassword_digestカラムを追加しただけで以下全部やってくれる

  • password、password_confirmationの追加
  • パスワードの存在の要求
  • パスワードの一致の要求
  • 認証のためのauthenticateメソッドの提供

_to_usersとすると、usersテーブルにカラム追加するマイグレーションになる

$ rails generate migration add_password_digest_to_users password_digest:string
add_column :users, :password_digest, :string

仮想カラムpassword、password_confirmationを追加

リスト6.25ではパスワードの空欄チェックの時に与えているpasswordとpassword_confirmationには半角スペースが入っているぽいけどそれだとテストが通らなかった。

letメソッド 変数の作成と変数への値をセット

let(:found_user) { User.find_by(email: @user.email) }

eqメソッド オブジェクト同士が同値であるか

it { should eq found_user.authenticate(@user.password) }

specifyはitと同義 英語として不自然な場合の代替

it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }

be_falseのテストが通らない。Rspec3から利用できなくなったらしい。

http://qiita.com/yujinakayama/items/a1d31b2caa35642e8e69

be_trueは、その名前にもかかわらず、テスト対象が真(false, nil以外)であればパスしており、trueとの同一性はテストされていなかった。 be_falseも同様に、テスト対象が偽(false, nil)であればパスしており、falseとの同一性はテストされていなかった。 といったように、名前と挙動が一致していませんでした。

なので、be_falseのように曖昧なままであればbe_falsey、厳格に比較するなら be falseをつかう。
be はequalマッチャへのalias。

パスワードの長さバリデーション

validates :password, length: { minimum: 6 }

authenticateメソッド
パスワードが合っていないときにはfalseを返す
パスワードが合っているときにはUser自身を返す