blog.waterlow.work

Ruby, Rails, js, etc...

Railsのソースレビューで印象に残ったこと

link_toimage_tagを使おう。

erbやhamlでは(slimも?)link_toを使わずとも以下のようにコードを埋め込めます。

<a href="<%= url>">"><%= text %></a>
%a{ href: url}= text

しかしながらモデルのインスタンスを渡すだけでパスを作ってくれたり、config/routesのasの指定を取得したりと、いろいろ便利な機能があったり、また習慣的にもビューヘルパを使って各事が多いため基本はビューヘルパを使いましょう。

・dbへの問い合わせを減らそう

モデルが以下のように定義されているとします。

class Contact < ActiveRecord::Base
  has_many :phones
end

includesを使うと以下のように後から問い合わせるsqlを先に発行するらしい(合ってる?) 以下の例だとほとんど変わらないがContactが1万件とかあると大きく違う。

irb(main):001:0> Contact.all.each { |contact| contact.phones.each { |phone| puts phone }}
  Contact Load (0.1ms)  SELECT "contacts".* FROM "contacts"
  Phone Load (0.1ms)  SELECT "phones".* FROM "phones"  WHERE "phones"."contact_id" = ?  [["contact_id", 1]]
  Phone Load (0.1ms)  SELECT "phones".* FROM "phones"  WHERE "phones"."contact_id" = ?  [["contact_id", 2]]
  Phone Load (0.1ms)  SELECT "phones".* FROM "phones"  WHERE "phones"."contact_id" = ?  [["contact_id", 3]]
irb(main):002:0> 
irb(main):003:0> Contact.includes(:phones).each { |contact| contact.phones.each { |phone| puts phone.phone }}
  Contact Load (0.1ms)  SELECT "contacts".* FROM "contacts"
  Phone Load (0.2ms)  SELECT "phones".* FROM "phones"  WHERE "phones"."contact_id" IN (1, 2, 3)

・遅延評価を知っておこう

@users = User.allのようにモデルのインスタンスを代入すると@users.each{}のように@usersメソッドを実行するときに初めてsqlが発行される。Userが膨大にいる場合は(やらないと思うけど)先に条件を絞った上でeach等のメソッドを実行する。先にallで取ってからselectなんてことはしない。

少なくともこれらの周辺知識はしっかり勉強しておく必要がありそう。