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

时间:2016-02-03 05:34:45

标签: ruby-on-rails single-table-inheritance

我一直在阅读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

1 个答案:

答案 0 :(得分:1)

在这种情况下,请使用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来识别db中所需的各种对象:

@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 %>

<强>更新

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

因此,如果你想在分页中“包含”数据,你只需要确保从数据库中提取数据。为此,您需要包含尽可能多的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])