Railsチュートリアル

Rails チュートリアル メモ 第13章

メモ

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")

buildcreate と違って 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 するようなメソッドを作って登録する