有没有比使用 STI 或多态关联更简单的方法?

Is there a simpler way than using STI or polymorphic associations?

我已经阅读了很多关于 STI 和多态关联之间的区别的文章,并决定使用 STI:

user.rb
Class User < ActiveRecord::Base
   has_many :articles
end

article.rb
Class Article < ActiveRecord::Base
   belongs_to :users
end

sport.rb
Class Sport < Article
end

politic.rb
Class Politic < Article
end

food.rb
Class Food < Article
end

create_table "articles", force: :cascade do |t|
t.string   "title"
t.string   "artwork"
t.integer  "user_id"
t.datetime "created_at",                 null: false
t.datetime "updated_at",                 null: false
t.boolean  "approved",   default: false
t.string   "type"

然而,进一步reading,这变得更加复杂。我真正想要做的就是找到某种方法来按类型对我的文章进行排序。例如,是否有可能我只是有一个 string column tag 并指定该标记必须是 politics, sports, or food

在这种情况下,使用 enum:

#app/models/article.rb
class Article < ActiveRecord::Base
  enum article_type: [:sport, :politic, :food] #-> "article_type" (int) column required
end 

这样做的唯一缺点是您只能为模型分配 一个 枚举值;从您概述的用例来看,这似乎就是您所需要的。


enum 将允许您使用以下内容:

@article = Article.find params[:id]

@article.sport?    #-> true
@article.politic?  #-> false
@article.food?     #-> false

@article.profile_type #-> "sport"

你还得到一组class methods来从数据库中识别你需要的各种对象:

@sports_articles = Article.sport #-> collection of "sport" articles

要通过表单创建 @article,您需要 collection_select:

#app/views/articles/new.html.erb
<%= form_for @article do |f| %>
   <%= f.collection_select :profile_type, Article.profile_types, :first, :first %>
   <%= f.submit %>
<% end %>

更新

分页发生在从数据库收到的数据上。

因此,如果您想 "include" 分页中的数据,您只需确保从数据库中提取数据即可。为此,您需要包含任意数量的 article_types

#app/models/article.rb
class Article < ActiveRecord::Base
   scope :by_type, (types) -> { where(article_type: Array.new(types)) }
end

这将允许您使用以下内容:

@articles = Article.by_type(:sport, :politic).paginate(page: params [:page], per_page: 12)

根据 docs:

Conversation.where(status: [:active, :archived])