LoginSignup
10
11

More than 5 years have passed since last update.

ActiveRecordでunion使いたい

Last updated at Posted at 2014-10-05

やりたいこと

ActiveRecordでunion使いたい

どうやるか

調べてもよくわからなかったので、下記を追加した

config/initializer/model_customizer.rb
ActiveRecord::Base.send(:define_singleton_method , "union", proc { |*queries|
  from "(#{ queries.map { |q| q.ast.to_sql }.join(' UNION ') }) AS #{self.table_name}"
})

つかいかた

app/model/post.rb

    self.union(query1, query2, query3)

注意

scopeでorder定義しているときはunscopeしないとSQLExceptionになる。
unionメソッド定義の中でunscopedするとsqlが変わってしまうので、渡す前にunscopedすることにした。

例:

app/model/post.rb

  default_scope -> { order('created_at DESC') }

  def self.from_users_followed_by(user)
    followed_user_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id"
    where("user_id IN (#{followed_user_ids}) OR user_id = :user_id", user_id: user.id)
  end

  def self.from_tags_followed_by(user)
    subquery1 = "SELECT tag_id FROM tag_follows WHERE user_id = :user_id"
    subquery2 = "SELECT post_id FROM taggings WHERE tag_id IN (#{subquery1})"
    where("id IN (#{subquery2}) ", user_id: user.id)
  end

  def self.feed(user)
    self.union(
      self.unscoped.from_users_followed_by(user),
      self.unscoped.from_tags_followed_by(user)
    ).order('created_at DESC')
  end
10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11