Rails4にはActiveRecordが実装されています。ここでは特にデータの読み出しに関するサンプルを見てみます。
$ rails new myApp
$ rails generate scaffold myModel field1:string field2:integer field3:date field4:boolean
$ rake db:migrate
app/models/my_model.rb
class MyModel < ActiveRecord::Base
scope :my_named_scope1, -> { where(field1: 1) }
scope :my_named_scope2, -> { order(id: :desc) }
scope :my_named_scope3, -> { my_named_scope2.limit(20) }
scope :my_named_scope4, -> (val) {
where(field1: val)
}
# default_scope { order(id: :desc) }
end
app/controllers/my_models_controller.rb
(いずれも、SQL文はコンソールに出力されます)
class MyModelsController < ApplicationController
before_action :set_my_model, only: [:show, :edit, :update, :destroy]
# GET /my_models
# GET /my_models.json
def index
# すべてを取得
# @my_models = MyModel.all
# プライマリキーで検索
# @my_models = [MyModel.find(1)]
# @my_models = MyModel.find([1,2])
# ↑SELECT "my_models".* FROM "my_models" WHERE "my_models"."id" IN (1, 2)
# @my_models = MyModel.find(1,2)
# 特定の列で検索
# @my_models = [MyModel.find_by(field1: 1)]
# ↑SELECT "my_models".* FROM "my_models" WHERE "my_models"."field1" = 1 LIMIT 1
# @my_models = [MyModel.find_by(field1: 1, field2: nil)]
# 検索結果の最初または最後
# @my_models = [MyModel.all.order(id: :desc).first, MyModel.all.order(id: :desc).last]
# 空の結果を返す
# @my_models = MyModel.none
### ↓メソッドチェーンが行われる場合、SQL文の発行は最後まで遅延されます
# WHERE句
# @my_models = MyModel.where(field3: '2014-01-01'..'2015-01-01', field2: nil).order(field1: :desc, field3: :asc)
# ↑AND,BETWEEN,ORDER
# ↑SELECT "my_models".* FROM "my_models" WHERE ("my_models"."field3" BETWEEN '2014-01-01' AND
# '2015-01-01') AND "my_models"."field2" IS NULL ORDER BY "my_models"."field1" DESC
# @my_models = MyModel.where(field1: [1,2]) #IN
# ↑SELECT "my_models".* FROM "my_models" WHERE "my_models"."field1" IN (1, 2)
# プレイスホルダ
# @my_models = MyModel.where('field1 = ? AND field2 IS ?', 1, nil)
# @my_models = MyModel.where('field1 = :val1 AND field2 IS :val2', val1: 1, val2: nil)
# 否定
# @my_models = MyModel.where.not('field1 = :val1 AND field2 IS :val2', val1: 1, val2: nil)
# ↑SELECT "my_models".* FROM "my_models" WHERE (NOT (field1 = 1 AND field2 IS NULL))
# 不要な列は取得しない (メモリの節約)
# @my_models = MyModel.where.not('field1 = :val1 AND field2 IS :val2', val1: 1, val2: nil)
# .select(:field1, :field2, :field3, :field4, :id)
# 途中のいくつかを取得 (ページャなどで利用)
# @my_models = MyModel.order(field1: :desc).limit(1).offset(1)
# よく使用するスコープはモデルファイルに記述しておく
# @my_models = MyModel.my_named_scope2
# @my_models = MyModel.my_named_scope4(1)
# SQLを直接発行 (非推奨)
# @my_models = MyModel.find_by_sql('SELECT * from "my_models"')
# @my_models = MyModel.find_by_sql(['SELECT * from "my_models" where field1 = ?', 2])
# デフォルトスコープ
# render text: MyModel.all
# ↑SELECT "my_models".* FROM "my_models" ORDER BY "my_models"."id" DESC
# render text: MyModel.unscoped.all
# ↑SELECT "my_models".* FROM "my_models ← デフォルトスコープを一時的に解除
# SQLレベルで重複を排除 (取得後のuniqではない)
# render text: MyModel.select(:field1).distinct.count
# 存在確認 (whereのあとに記述)
# render text: MyModel.where(field1: 2).exists?
# ↑SELECT 1 AS one FROM "my_models" WHERE "my_models"."field1" = 2 LIMIT 1
# 個数
# render text: MyModel.all.count
# ↑SELECT COUNT(*) FROM "my_models"
# 基本的な統計処理
# render text: MyModel.all.sum(:field1)
# render text: MyModel.all.average(:field1)
# render text: MyModel.all.maximum(:field1)
# render text: MyModel.all.minimum(:field1)
# GROUP BY:
# $ rails runner 'p MyModel.select("field4, AVG(field1) AS avg_field1").group(:field4).first.avg_field1'
# GROUP_BY and HAVING
# $ rails runner 'p MyModel.select("field4, AVG(field1) AS avg_field1").group(:field4)
# .having("avg_field1 = ?", 2).first.avg_field1'
# 無名配列化
# render text: MyModel.all.pluck(:field1)
# ↑SELECT "my_models"."field1" FROM "my_models"
# render text: MyModel.all.select(:field1).map{|model| model.field1} #これも同じ意味
# render text: MyModel.all.pluck(:field1, :field2) #複数の列を指定可能
# → 例: [["1", nil], ["2", nil], ["3", nil]]
end
なお、上記サンプル中にもあるように、"rails runner" を利用することで、cronで実行するためのバッチファイルを作成したり、デバッグに役立てることができます。
$ rails runner 'p MyModel.find(1)'
出力例
#<MyModel id: 1, field1: "1", field2: nil, field3: "2014-06-15", field4: false, created_at: "2014-06-15 23:05:36",
updated_at: "2014-06-15 23:05:36">
アセットパイプラインの検索パスを調査する例
$ rails runner 'p Rails.application.assets.paths'
["/vagrant/app/assets/images", "/vagrant/app/assets/javascripts",
"/vagrant/app/assets/stylesheets", "/vagrant/vendor/assets/javascripts",
"/vagrant/vendor/assets/stylesheets"]
以下の操作と同等の情報を得られます。
$ rails c
[1] pry(main)> puts Rails.application.assets.paths
/vagrant/app/assets/images
/vagrant/app/assets/javascripts
/vagrant/app/assets/stylesheets
/vagrant/vendor/assets/javascripts
/vagrant/vendor/assets/stylesheets
=> nil