0

Rails: includes with polymorphic association

combine 2 objects and sort rails 5

Here is my current code:

user.rb 

def photo_feed
  following_ids = "SELECT followed_id FROM relationships
                   WHERE follower_id = :user_id"
  Photo.approved.where("user_id IN (#{following_ids})", user_id: id)
end

def video_feed 
  following_ids = "SELECT followed_id FROM relationships
                       WHERE follower_id = :user_id"
  Video.approved.where("user_id IN (#{following_ids})", user_id: id)
end

UsersController

def feed
  @user_feed_photo_items = current_user.photo_feed.order('created_at desc').paginate(page: params[:page], per_page: 15)
  @user_feed_video_items = current_user.video_feed.order('created_at desc').paginate(page: params[:page], per_page: 15)
end 

Users follow others users who upload photos and videos. My goal is to stop separating photos and videos and to instead display photos and videos in a polymorphic association as described in the answers above ordered bycreated_at.

But the above answers that I linked to are much simpler. When a new object is created it is just added to the timeline. In my case, objects will not be added into the timeline until a user follows another user, and when unfollowed they would need to removed form the timeline. And they would still need to be sorted by their created_at date inside the timeline.

How can I go about achieving this goal?

Community
  • 1
  • 1
Timmy Von Heiss
  • 2,160
  • 17
  • 39

1 Answers1

0

Normally to do this you would have two classes that inherited from a single base class, for example:

class Media < ActiveRecord::Base
end
class Video < Media
end
class Audo < Media
end

And there would be a single underlying table called medias. See http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

If you are stuck with two separate tables then one solution is to create a view, for example if you are using Postgres then something like this:

CREATE OR REPLACE VIEW media AS
   SELECT id, 'Video' as type, a,b,c FROM videos
   UNION
   SELECT id, 'Audio' as type, a,b,c FROM audios;

And then create a 'fake' model on top of that:

class Media < ActiveRecord::Base
end

You could then use this as a read-only record set to query on.

Marc Rohloff
  • 1,332
  • 7
  • 8
  • so you are saying that with the above If I create a video object it will get id 1 and then if i create an audio object it will get id 2? – Timmy Von Heiss Mar 11 '17 at 23:30
  • If you use STI with a single table, then yes, they will get unique id's. If you merge two tables with a union view then id's could overlap which is why I added the `type` column. – Marc Rohloff Mar 12 '17 at 03:56