我有三个模型,即图像,数据文件和视频。我想从这三个模型中获取用户的最新内容。

这样做的一个非常不好的可能是:

  images = User.find(8).images
  videos = User.find(8).videos
  data_files = User.find(8).data_files

全部内容:
 all_content = images + videos + data_files
 all_content.sort_by(&:created_at).reverse.paginate(:page => params[:page],:per_page=> per_page)

如何在一个查询中做到这一点,以使代码更好。

最佳答案

拥有一个将用户连接到其内容的Content模型可能是一个好主意。像这样:

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)

这只是概念的证明,如果愿意,甚至可以使用single table inheritance,它取决于每个内容模型具有的属性,考虑到这些对象通常包含标题,正文和内容链接,可能会更好,网址和类似内容,并且几乎没有区别。

如果您使用STI,则需要定义一个具有通用属性的基本模型(在这种情况下为Content),并为每个内容模型(例如ImageVideo)定义几个其他模型。这些模型从Content模型继承。请记住,在数据库中有一个contents表,其中包含type列(该列将包含具有内容类型的字符串,例如'Video')和子模型的所有列(是的,如果使用此方法,则所有数据将放在一张桌子上)。

更新:单表继承方法具有多个优点,例如您可以在一个查询中获得所有内容的数据,以前的解决方案很适合排序,但是您仍然需要通过其他查询来获取视频和其他特定数据:
# 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

在这种情况下,如果您想要所有用户的内容,则可以使用user.contents,并根据它们的类型获得特定对象(视频,图像等)的数组。
您也可以只获取带有此类Video.all的图像或视频

当然,这些只是想法,实际的实现取决于您的问题和要求。

关于ruby-on-rails - 订购来自三种不同型号的数据的 ruby ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11833666/

10-16 00:22
查看更多