I want to show a time link mixing comments and post so I have this objects
@posts = Post::all()
@comments = Comment::all()
If I do this
Posts and comments are different models (and different tables), so we can't write SQL to get sorted collection, with pagination etc.
Usually I use next approach when I need mixed timeline.
I have TimelineItem
model with source_id
, source_type
and timeline_at
fields.
class TimelineItem < ApplicationRecord
belongs_to :source, polymorphic: true
end
Then I add in models logic to create timeline_item instance when needed:
has_many :timeline_items, as: :source
after_create :add_to_timeline
def add_to_timeline
timeline_items.create timeline_at: created_at
end
Then search and output as simple as
TimelineItem.includes(:source).order(:timeline_at).each { |t| pp t.source }
Solution#1 You can achieve this using UNION query.
sql= 'SELECT id, name, date FROM posts UNION ALL SELECT id, name, date FROM comments ORDER BY date'
ActiveRecord::Base.connection.execute(sql)
but union query will only work when you have same column names in both tables.
Solution#2 Add ordering logic in your view.
If you are simply displaying these records on html page then let them load on page without any specific order i.e.(first posts and then comments). Write javascript code to sort DOM elements which will run after page load.
for ref: Jquery - sort DIV's by innerHTML of children
Solution#3 Refactor your DB schema and put posts and comments in same database table. Then you will be able to query on single table. Something like this,
class Text < ActiveRecord::Base
end
class Post < Text
end
class Comment < Text
end
Query will be Text.order(:date)
Refactoring your DB schema is too much to solve this problem. Do it if it makes sense for your application.