メモ
references
$ rails generate model Micropost content:text user:references
のように、モデルの generate 時に references
型を指定すると、外部キー参照付きのカラムが作られる。また、Micropost モデルに
belongs_to :user
が自動的に追記される。これによって、Micropost のインスタンスに user
メソッドが生えて、micropost.user
のように関連するユーザーを参照することができるようになる。
たぶん xxx_id の xxx の部分が重要なんだろう。
belong_to / has_many
belongs_to / has_many の関係を設定することで、チュートリアル中の 表13.1 のようなメソッドが使えるようになる。このうち1つはすでに前述した。
重要なのは、所有側(今回でいう User)に user.microposts.create
のようなメソッドが生えることである。これを使うと、user_id
が初めから埋まった状態で Micropost のインスタンスを作ることができる。むしろ、Micropost のインスタンスは そのようにして作るのが慣習 らしい。
# 慣習的に間違い
@micropost = Micropost.new(content: "Lorem ipsum", user_id: @user.id)
# 慣習的に正しい
@micropost = @user.microposts.build(content: "Lorem ipsum")
build
は create
と違って DB に保存しない。細かいところでいうと、@user.micropost **s**
のように複数形であることに注意。 has_MANY だからね。
belong_to は Micropost モデルの generate 時に自動的に記述されたが、User クラスに has_many を書くところまではやってくれないので、そこは自分で書く必要がある。
並び順の制御
default_scope を使う。
チュートリアルでは default_scope を並び順の制御にだけ使っているが、そのためだけの機能ではないんだろうなと思う。詳細は こちら を参照。何となく、DB から検索するときの SQL にデフォルト条件を設定するようなイメージっぽい。
親を消したときの子の扱い
親側のモデルで設定する。具体的には has_many にオプションを渡す。
dependent: :destroy
を渡すと、親(user)が消えたときに子(microposts)も消す。DB にゴミが残らないのでスッキリする。他にもいくつか選択肢があるんだろうな。
DB の操作
User.order(:created_at).take(6)
Rails から DB を操作するときは、上記のようにメソッドチェーンを使う。
take
と似た働きのメソッドとして limit
がある。take
は User のインスタンスの配列が得られるが、limit
で得られるのは ActiveRecord::Relation クラスのオブジェクトである。
・・・とここまで書いてからわかったけど、take は ruby の Enumerable に定義された標準メソッドでした。
Fixture 同士の関連付け
orange:
content: "I just ate an orange!"
created_at: <%= 10.minutes.ago %>
user: michael
上記のような micropost の Fixture を書くと、自動的に user の Fixture から michael を探して関連付けてくれる。user_id
ではなく user
なところにも注意。Rails のこういう仕様を把握しきれる自信がない。
resources によるルーティングの only オプション
route.rb で resources を使ってルーティングを定義すると、RESTful なルートが片っ端から用意されてしまうが、今回のように「create と destroy しか使う気がない」という場合は、only オプションで絞ることができる。
resources :microposts, only: [:create, :destroy]
DB の操作2
where 句は以下のように使う。
Micropost.where("user_id = ?", id)
ここで重要なのが ?
の利用だ。こうすることで、変数の中身がエスケープされて展開されるらしい。つまり SQL インジェクションの危険性が減る。下記のようにしないよう注意。
# ダメな例!
Micropost.where("user_id = #{id}")
簡易 friendly redirecting
request.referrer
を使えば可能。ログインの場合はログイン画面が request.referrer
に入ってしまうのでダメだが、ポスト削除の場合は削除画面を経由したりすることがないので、これで十分。
redirect_to request.referrer || root_url
||
を使って、request.referrer が空だったときのケアをしている。rails 5 からは redirect_back(fallback_location: root_url)
でもいいらしい。
バリデーションの自作
- validates ではなく validate なので注意(s がつかない)
- データをチェックして、不正だったら
errors.add
するようなメソッドを作って登録する