简体   繁体   中英

Convert some SQL query to active record

So, I have this "advanced" query (not much, really) and I would like to translate it into Ruby Active Record's syntax.

SELECT microposts.* 
FROM microposts
WHERE user_id IN 
      ( SELECT r.followed_id as uid 
        FROM relationships r 
        WHERE follower_id = 1 
      UNION 
        SELECT u.id as uid 
        FROM users as u 
        WHERE id = 1
      ) 
ORDER BY microposts.created_at DESC

The idea was to retrieve all microposts for user 1 AND user 1 followed users in desc creation order, but I really don't know how to translate this easily using Active Record's syntax.

Any thought ?

PS : As asked here is some rails context :

I have 3 models : Microposts , Users , Relationships .

  • Relationships is a join table handling all users relationships (follower/followed stuff).
  • Users have many followed_users/followers through relationships.
  • Users have many microhoops, and microhoops have one user.

Thanks.

Your query is very specific, therefore your best bet would be to write a good portion of it using SQL, or try a gem like squeel that can help out generating very customized SQL from ActiveRecord.

Nevertheless, this should do the work with no additional gems :

user_id = ... #Get the user_id you want to test
Micropost.where("user_id IN 
  ( SELECT r.followed_id as uid 
    FROM relationships r 
    WHERE follower_id = ? )
  OR user_id = ?
  ", user_id, user_id).order("created_at desc")

No idea about Ruby but the SQL can be simplified to:

SELECT microposts.* 
FROM microposts
WHERE user_id IN 
      ( SELECT r.followed_id as uid 
        FROM relationships r 
        WHERE follower_id = 1 
      ) 
   OR user_id = 1
ORDER BY microposts.created_at DESC

My answer will assume (since you've provided no ruby/rails-context outside of your raw SQL query) you have a User model, a Micropost model through relation :microposts , and a Relationship model through relation :following . User has many Micropost and Relationship instances related. You could do

u = User.find(1)
user.microposts + user.following.microposts

or you could move this into a method within Micropost

def self.own_and_following(user)
  user.microposts + user.following.microposts      
end

And call Micropost.own_and_following(User.find(1)) .

This may not be what you're looking for, but in given the above mentioned likely relations you have in your Rails application, it sounds like something similar to this should work.

I managed to do it using only where, seems a lot like a find_by_sql to me, and I don't know which one would be better :

Micropost.order('created_at DESC').
where('user_id in (select r.followed_id as uid from relationships as r where follower_id = ?) or user_id = ?', user.id, user.id)

Don't know how good this is, but it seem to be working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM