ActiveRecord’s queries tricks小記
2432 ワード
ActiveRecord’s queries tricks小記
原文https://medium.com/rubyinside...
関連テーブルjoinの使用条件
より良い方法
merge https://apidock.com/rails/Act... https://api.rubyonrails.org/c...について
ネストjoinの違い User has_one Profile Profile has_many Skills
内部リンクと外部接続
Exist query
存在しない
Subqueriesサブクエリ
たとえば、一部のユーザー(user)の投稿をクエリーする(post)
悪いやり方
ここでの欠点は、2つのSQLクエリーを実行することです.1つはユーザーのIDを取得するために使用され、もう1つはこれらのuser_から使用されます.id投稿の取得
これでクエリーを書けばいいです
きそ
.to_sqlはSQL文文字列を生成する.explainクエリー分析の取得
Booleans
nullも含めてこう書くべきだ
or
原文https://medium.com/rubyinside...
関連テーブルjoinの使用条件
# User model
scope :activated, ->{
joins(:profile).where(profiles: { activated: true })
}
より良い方法
# Profile model
scope :activated, ->{ where(activated: true) }
# User model
scope :activated, ->{ joins(:profile).merge(Profile.activated) }
merge https://apidock.com/rails/Act... https://api.rubyonrails.org/c...について
ネストjoinの違い
User.joins(:profiles).merge(Profile.joins(:skills))
=> SELECT users.* FROM users
INNER JOIN profiles ON profiles.user_id = users.id
LEFT OUTER JOIN skills ON skills.profile_id = profiles.id
# So you'd rather use:
User.joins(profiles: :skills)
=> SELECT users.* FROM users
INNER JOIN profiles ON profiles.user_id = users.id
INNER JOIN skills ON skills.profile_id = profiles.id
内部リンクと外部接続
Exist query
存在しない
# Post
scope :famous, ->{ where("view_count > ?", 1_000) }
# User
scope :without_famous_post, ->{
where(_not_exists(Post.where("posts.user_id = users.id").famous))
}
def self._not_exists(scope)
"NOT #{_exists(scope)}"
end
def self._exists(scope)
"EXISTS(#{scope.to_sql})"
end
Subqueriesサブクエリ
たとえば、一部のユーザー(user)の投稿をクエリーする(post)
悪いやり方
Post.where(user_id: User.created_last_month.pluck(:id))
ここでの欠点は、2つのSQLクエリーを実行することです.1つはユーザーのIDを取得するために使用され、もう1つはこれらのuser_から使用されます.id投稿の取得
これでクエリーを書けばいいです
Post.where(user_id: User.created_last_month)
きそ
.to_sqlはSQL文文字列を生成する.explainクエリー分析の取得
Booleans
User.where.not(tall: true)
に対してpgの下でSELECT users.* FROM users WHERE users.tall <> 't'
が生成され、これはtallがfalseであるレコードを返し、nullを含まないnullも含めてこう書くべきだ
User.where("users.tall IS NOT TRUE")
or
User.where(tall: [false, nil])