ruby チュートリアル6章 メモ
Model
データモデルとして扱うデフォルトのデータ構造のことをモデルと呼ぶ。データベースとのやり取りを行うライブラリはActiveRecordで、データオブジェクトの生成・保存・検索のメソッドをもつ。よって、SQL文を書かない。マイグレーション機能はデータの定義をRubyでできるようにしてくれている。
モデルの生成
$ rails generate model User name:string email:string
コントローラ名には複数形を使って、モデル名には単数形を使用する。これによって生成されるテーブル名は複数形 (users) になる。上のコマンドで以下のマイグレーションファイルが生成される。タイムスタンプを名前に使用する事で多人数での開発でもコンフリクトを起こさず順番を保持することができる。t.timestampsは特別なコマンドで、created_atとupdated_atという2つの「マジックカラム (Magic Columns)」を作成する。これらは、あるユーザーが作成または更新されたときに、その時刻を自動的に記録するタイムスタンプの役割。また、記述されていないが、id属性が自動で生成される。
# db/migrate/[timestamp]_create_users.rb class CreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| t.string :name t.string :email t.timestamps end end end
マイグレーションは以下のコマンドで実行される。
$ bin/rails db:migrate
ロールバック
$ rails db:rollback
マイグレーションファイルのchange
メソッドはdrop_table
とcreate_table
メソッドがそれぞれ対応していることを理解しており、マイグレーションファイルを呼ぶだけでロールバックが可能になっている。一部カラム削除等の操作はchange
メソッドを使用せず、up
とdown
メソッドを自分で別々に定義する必要がある。
schema.rb
schema.rb
にはマイグレートされたものが記録されていく。ロールバックすると、その分消える。
モデルの生成と保存
$u = User.new(name:"hoge") # hoge以外の値がnil $u.save #idとタイムスタンプに値が入る #上2行と同じ $ User.create(name:"hoge")
validation
モデルのファイルに書く。例えば上のUserモデルであれば以下のようにする。
#app/models/user.rb class User < ApplicationRecord validates :name, presence: true end
validates
はメソッドなので以下のようにカッコを使用してもかける。
class User < ApplicationRecord validates(:name, presence: true) end
この検証をコンソールで確認することも可能。エラー内容を確認することもできる
$ rails console --sandbox >> user = User.new(name: "", email: "mhartl@example.com") >> user.valid? => false >> user.errors.full_messages => ["Name can't be blank"]
インスタンス変数
Minitest
ではsetup
, RSpec
ではbefore
あたりでテスト毎の実行前に呼びたい共通コードを書く。
def setup @user = User.new(name: "Example User", email: "user@example.com") end
頭に@
をつけたインスタンス変数を使用すれば、このコード内でどこからでも参照可能になる。@
をつけなければ、例えばit
内で呼ぶことはできない。
DBレベルでの一意性
一意性を保ちたいものに対して、インデックスを追加し、インデックスの一意性を保つように変更する。
インデックスの追加
インデックスを追加することによって、find等の検索のスピードも早くなる。
$ bin/rails generate migration add_index_to_users_email
上のコードでファイルは生成されるが中身は無い状態なので自分で追加する必要がある。
class AddIndexToUsersEmail < ActiveRecord::Migration[5.0] def change add_index :users, :email, unique: true #trueにすることによって end end
追記したら、以下のコマンドで反映。
$ bin/rails db:migrate
ActiveRecordのコールバックメソッド
ある特定の時点で呼ばれるメソッド。例えば、before_save
を使用すればユーザをデータベースに保存する前に特定の処理を挟むことができる。
class User < ApplicationRecord before_save { self.email = email.downcase } validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } end
ハッシュ化されたパスワード
has_secure_password
メソッドを呼び出す。ハッシュ関数を利用するにはgem 'bcrypt'
のジェムを入れておくこと。利用するには以下のように追記すればok。
class User < ApplicationRecord . . . has_secure_password end
これにより以下の利点がある。
- セキュアにハッシュ化したパスワードを、データベース内のpassword_digestという属性に保存できるようになる。
- 2つのペアの仮想的な属性 (passwordとpassword_confirmation) が使えるようになる。また、存在性と値が一致するかどうかのバリデーションも追加される 。
- authenticateメソッドが使えるようになる (引数の文字列がパスワードと一致するとUserオブジェクトを、間違っているとfalseを返すメソッド) 。
よって、モデルにpassword_digestというカラムを追加する必要がある。
$ rails generate migration add_password_digest_to_users password_digest:string
末尾にto_users
とつけることで、自動でadd_password_digest_to_users
というマイグレーションファイルを生成してくれる。以下がそれ。
class AddPasswordDigestToUsers < ActiveRecord::Migration[5.0] def change add_column :users, :password_digest, :string end end
最後にいつも通りマイグレーションコマンドで変更を反映してあげればok。