はじめに
業務の中でためになったことを雑にまとめたものです。
コンテンツ
whereの条件を反転
invert_where
でスコープの条件の反転ができる。
注意点があるので複雑な条件の時は発行されるSQLを確認したほうがいい。
class User
scope :enabled, -> { where(enabled: true) }
end
User.enabled
# enabled = falseを抽出できる
User.enabled.invert_where
Hash値およびキーワード引数の省略記法
Ruby 3.1から。
下記のように、同じ名前で変数名を定義すれば省略ができる。
dataA = "test"
dataB = "test2"
Model.where(dataA:, dataB:)
複数のデータを大量に保存する処理の時
activerecord-import
というgemを入れてあれば、下記のようにimport
を使ってパフォーマンスよく書ける。
tests = []
10.times do |i|
tests << Test.new(name: "name_#{i}")
end
Test.import tests
あるテーブルのレコードのなかから最大値を取得
Model.maximum(:created_at)
条件を加えることもできる。
Model.where(flg: false).maximum(:created_at)
指定したテーブルに関連がないレコードのみを取得
relationが設定されていること前提です。
下記ではrelation_tableに登録のないModelのレコードを全て取得する。
Model.where.missing(:relation_table)
反対に関連があるものだけ取得したいときはjoinを使えば良い。
Model.join(:relation_table)
主キーのカラムデータを配列として取得
特定の条件に当てはまるレコード全てに対して何か処理を行う時などにパフォーマンスを考慮して使ったりする。
Model.ids
条件に応じてどちらかの値を返したい時
ret = (i > 0) ? i : 0
ret = [i, 0].max
カラム名でfind_by検索
下記の2パターンの書き方ができる。
find_by_name("テスト")
find_by(name: "テスト")
ハッシュから値を取り出す方法
下記のように書くことで、キーが存在しない場合のデフォルトの返却値を設定することができ、エラーを回避できる。
hash = {1 => 'a', 2 => 'b', 3 => 'c'}
# キーが存在するのでbがかえる
value = hash.fetch(2, 0)
# キーが存在しないので0がかえる
value = hash.fetch(4, 0)
ハッシュを合体する方法
下記のように書くことで、キーが重複する場合の処理を指定できる。
もし、keyが重複していた場合は、A_val(sampleAのvalue) + B_val(sampleBのvalue)の値を返すようにする。
sampleA = { a: 1, b: 2, c: 3 }
sampleB = { b: 3, c: 4, d: 5 }
result = sampleA.merge(sampleB) { |key, A_val, B_val| A_val + B_val }
自由にページを増やせる
コントローラーのアクションを増やさなくても、下記のように書けば、showアクションひとつのみで複数ページを設定できる。(静的ページを表示するだけのviewだけ増やしたい時に有効)
class TestController < AplicationController
def index
end
def show
render template: "test/#{params[:keyword]}"
end
end
namespace :test do
get "/", action: "index"
get "/:keyword", action: "show"
end
flattenを使う
配列を取得したいとき、取得結果が多次元配列の時、eachなどを使って配列にする操作をしなくても、flattenを使えば良い。
arr = [1, 2, 3, [6,8], 9]
arr.flatten
=> [1, 2, 3, 6, 8, 9]
読み込みをして、エラーのないものだけを抽出したい時
eachブロック内でエラーのチェックをして、エラー時はfalseをかえすようにする。
そうすれば、下記のようにselect
で取得できる。
# 2で割り切れるものを抽出する
[1, 2, 3, 4, 5, 6].select { |n| n % 2 == 0 }
# => [2, 4, 6]
既存を検索。なければ作る。すでにある場合を判定する。
find_or_initializeでOK。
重複を避けるためにすでに存在している場合を判定したい時はpersisted?
を使う。
user = User.new(name: "ichiro", age: "20")
user.persisted?
# false
user.save
user.persisted?
# true