
Ruby on Rails 5アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2017/04/14
- メディア: 大型本
- この商品を含むブログを見る
序文
「Ruby on Rails 5 アプリケーションプログラミング」学習17日目。
読者登録してるのにイタズラされたんですが。
GitHub
進捗
- 第5章 モデル開発
- 5.3 データ取得のためのその他のメソッド
(学習時間:3時間)
- 5.3 データ取得のためのその他のメソッド
コード実装部分
↓config/routes.rb
# 省略 get 'record/pluck' get 'record/exists' get 'record/scope' get 'record/def_scope' get 'record/count' get 'record/average' get 'record/groupby2' get 'record/literal_sql' end
↓/railbook/app/models/cd.rb
class Cd < ApplicationRecord has_many :reviews has_and_belongs_to_many :artists has_many :listeners, through: :reviews has_many :memos, as: :memoable # アロー演算子は無名関数を定義していると思いねえ scope :sazanami, -> { where(label: 'サザナミレーベル')} scope :newer, -> { order(released: :desc)} scope :top10, -> { newer.limit(10)} # スコープをパラメータ化することもできる scope :whats_new, ->(lab){ where(label: lab).order(released: :desc).limit(5) } end
↓/railbook/app/models/review.rb
class Review < ApplicationRecord belongs_to :cd belongs_to :listener default_scope{ order(updated_at: :desc) } end
↓/app/controllers/record_controller.rb
class RecordController < ApplicationController # 省略 # 指定列の配列を取得する def pluck render plain: Cd.where(label: 'サザナミレーベル').pluck(:title, :price) # SQL # SELECT "cds"."title", "cds"."price" FROM "cds" WHERE "cds"."label" = ? [["label", "サザナミレーベル"]] # 出力結果 # [["僕は停滞気味", 2000], ["エロス", 2000]] end # レコードの存在を確認する def exists flag = Cd.where(label: 'サザナミレーベル').exists? render plain: "存在するか? : #{flag}" # SQL # SELECT 1 AS one FROM "cds" WHERE "cds"."label" = ? LIMIT ? [["label", "サザナミレーベル"], ["LIMIT", 1]] # 出力結果 # 存在するか? : true # その他の例 # 主キー検索 # flag = Cd.exists?(1) # レーベル名指定 # flag = Cd.exists?(label: > 'サザナミレーベル') # 5000円以上 # flag = Cd.exists?(['price > ?', 5000]) end # 名前付きスコープの使用例 def scope # 名前付きスコープ(検索条件)はモデルファイル内で定義する @cds = Cd.sazanami render 'yahoo/list' # SQL # SELECT "cds".* FROM "cds" WHERE "cds"."label" = ? [["label", "サザナミレーベル"]] # パラメータ化したスコープの呼び出し例 # @cds = Cd.whats_new('サザナミレーベル') end # デフォルトスコープの使用例 def def_scope # デフォルトスコープ(検索条件)はモデルファイル内で定義する render plain: Review.all.inspect # SQL # SELECT "reviews".* FROM "reviews" ORDER BY "reviews"."updated_at" DESC LIMIT ? [["LIMIT", 11]] # デフォルトスコープを解除したい場合はunscope()メソッドを使えばいいらしい end def count cnt = Cd.where(label: 'サザナミレーベル').count render plain: "#{cnt}件です" # SQL # SELECT COUNT(*) FROM "cds" WHERE "cds"."label" = ? [["label", "サザナミレーベル"]] # その他の例 # 主キー検索 # cnt = Cd.count # label列が空でないレコードの件数 # cnt = Cd.count(:label) # label列の種類 # cnt = Cd.distinct.count(:label) end def average price = Cd.where(label: 'サザナミレーベル').average(:price) render plain: "平均価格は#{price}円です。" end def groupby2 @cds = Cd.group(:label).average(:price) render plain: @cds # SQL # SELECT AVG("cds"."price") AS average_price, "cds"."label" AS cds_label FROM "cds" GROUP BY "cds"."label" # 出力結果 # {"エピックレコードジャパン"=>0.28e4, "サザナミレーベル"=>0.2e4, "ビクターエンタテインメント"=>0.3035e4, "モジャーレコーズ"=>0.333333333333333e4} # ↓とだいたい同じだけど呼び出し方法が異なる # @cds = Cd.select('label, AVG(price) AS avg_price').group(:label) # ↑呼び出し方が直感的なので、こっちの方法を推奨 end def literal_sql @cds = Cd.find_by_sql(['SELECT label, AVG(price) AS avg_price FROM "cds" GROUP BY label HAVING AVG(price) >= ?', 2500]) render 'record/groupby' # SQL # SELECT label, AVG(price) AS avg_price FROM "cds" GROUP BY label HAVING AVG(price) >= 2500 end end
実行結果
感想
その他のデータ取得のクエリについて学習。
find_by_sqlばっかり使っていたので、こんなのあったのか…と反省ばかり。
全体的にあんまりエンジンがかからなかった。
粘り強さが信条ではあるけど、一日一日の学習濃度ももうちょっとあげたほうがいい気がする。
1回もういいやと思ってやめた、ポモドーロなんちゃらをふたたびやってみようかな。
カロリーメイトください。
BGM
ダイエッター / 小林未奈 www.youtube.com