I have three models ie image, datafiles and video. I want to fetch the latest content by a user from all the three models.
One very bad of doing this can be:
images = User.find(8).images
videos = User.find(8).videos
data_files = User.find(8).data_files
All the content:
all_content = images + videos + data_files
all_content.sort_by(&:created_at).reverse.paginate(:page => params[:page],:per_page=> per_page)
How can do this in just one query to make the code better.
Probably it's a good idea to have a Content model which connects a user to his contents. Something like this:
class User < ActiveRecord::Base
has_many :contents
end
class Content < ActiveRecord::Base
belongs_to :user
# Remember the contentable_type and contentable_id columns
belongs_to :contentable, :polymorphic => true
end
# Similar relations for Image/File models
class Video < ActiveRecord::Base
has_one :content, :as => :contentable
belongs_to :user, :through => :content
end
# Then to fetch the last contents from the user
Content.where(:user_id => 8).order('created_at DESC')
.paginate(:page => params[:page], :per_page=> per_page)
It's just a proof of concept, you could even go with single table inheritance if you prefer, it depends on the attributes each of your content model has, probably it's the better thing given these object usually contains a title, a body, a link to the content, an url and similar stuff and few differences.
If you go with STI you need to define a base model (Content in this case) with the common attributes and several other model for each of your content model (e.g. Image or Video). These models inherit from the Content model. Remember to have a contents table in your DB with a type column (which will contain the string with the type of content, e.g. 'Video') and all the columns for the child models (yes, if you use this approach all the data will go in a single table).
UPDATE: The Single Table Inheritance approach has several pros, e.g. you get all the contents' data in one query, the previous solution is good for sorting but you still need to get the Video, and other specific data with other queries:
# The contents table has a type string column and
# all the specific models's columns
class Content < ActiveRecord::Base
end
# Video class inherit from Content (a Video is a Content!)
class Video < Content
end
In this case if you want all the user's content you can use user.contents and you'll get an array of the specific objects (Video, Image and so on) depending of their type.
You can also get just the images or videos with something like this Video.all
Of course these are just ideas, the real implementation depends on your problem and requirements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With