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
0
記事の執筆者にステッカーを贈る
有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。
さらに詳しく →Feedbacks
ログインするとコメントを投稿できます。
関連記事
- レイアウトおよび部分テンプレートに関するまとめ (Rails4)レイアウトおよび部分テンプレートはどちらもテンプレート (*.html.erb) に共通の要素をまとめておき、任意のテンプレートから利用できるようにしておくための仕組みです。フッターやヘッダーといった大枠はレイアウト、小さなパーツは部分テンプレートというイメージで使い分けましょう。 レイアウトの使用方法 クラス毎に指定する方法と、アクション毎に指定する方法があります。 app/views/layo...
- Ruby コードスニペット (正規表現)sample.rb str = "001: This is a string." var1,var2 = 2,3 # 'EOS'とすると#{}による変数展開がなされない (%03dは展開される) doc = (<<"EOS" % var1) # 括弧は省略可。要は<<"EOS"の次の行からEOSまで。(参: <<-"EOS"とすると前に空白...
- OAuthを用いずにTwitterに自動投稿する (回数制限あり, Selenium with Ruby)Seleniumを用いて、OAuthを用いずにTwitterに自動投稿するRubyスクリプトを記述してみます。連続で複数回実行すると、ボット判定としてキャプチャ認証が発生します。その認証までは通過できませんので悪しからず。また、Twitterの仕様変更次第ではDOMの構造が変化するため、下記サンプルは機能しなくなる恐れが有ります。 twitter_post.rb #!/usr/bin/ruby r...
- Ruby における日本語のエンコーディング日本語を含めて多言語対応する際には、Asciiコード以外の文字コードセットが必要になります。日本語が主となる場合、よく使われる文字セットにはUnicode, Shift_JIS, EUC-JPがあります。このうち Unicode だけは特殊であり、世界中のあらゆる文字を収録しようとしていることから 1 文字を表現するために必要なバイト数が大きくなってしまっています。そのため Unicode のうち...
- Rails3ビューテンプレートの基本的な使用方法 (Ruby)Railsでは、ERB (eRuby (テキストファイルにRubyスクリプトを埋込む書式の仕様) をRubyで実装したもの) を用いてHTML内にRubyスクリプトを埋込むことができます。 <% %> で囲むと出力されません (if-elseなど制御構文を記述します) <%= %> で囲むとエスケープ出力されます <%== %> で囲むとエスケープされずに...