railstutorial.jp 6章メモ
テーマ
- ユーザ登録
- モデル
- バリデーション
認証と権限のモジュールはたくさんあるけどここでは自前で作る
- Clearance
- Authlogic
- Device
- Cancan
モデルは単数形で指定
$ 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自身を返す