0

I have been reading a lot on the difference between STI and polymorphic associations and decided to use 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"

However, upon further reading, this becomes even more complicated. All I am really looking to do is to find some way to sort my articles by type. For example, is it possible that I simply have a string column tag and specify that tag must be either politics, sports, or food?

Community
  • 1
  • 1
Timmy Von Heiss
  • 2,160
  • 17
  • 39

1 Answers1

1

In this case, use an enum:

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

The only drawback to this would be that you can only assign one enum value to your model; from the use case you've outlined, it seems that's what you need.


The enum will allow you to use the following:

@article = Article.find params[:id]

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

@article.profile_type #-> "sport"

You also get a set of class methods to identify the various objects you need from the db:

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

To create an @article through a form, you'll need 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 %>

Update

Pagination occurs on data received from the db.

Thus, if you wanted to "include" data in the pagination, you'd just have to make sure you're pulling it from the db. To do this, you'd need to include as many article_types as you want:

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

This will allow you to use the following:

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

As per the docs:

Conversation.where(status: [:active, :archived])
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • How can I setup a form to accept an enum value when I build @article? – Timmy Von Heiss Feb 03 '16 at 18:18
  • You can use a `collection_select`, I'll update the answer – Richard Peck Feb 03 '16 at 18:26
  • Is it supposed to be [ :sport, :politic, :food ] ? Other tutorials show it that way. – Timmy Von Heiss Feb 03 '16 at 19:19
  • Are you Rich of richonrails.com? – Timmy Von Heiss Feb 03 '16 at 20:41
  • how can i setup the controller if i want to paginate all of the `@article.sport` and all of the `@article.food` using `<% @articles.in_groups_of(6, false).each do |group| %>` in index.html.erb. For example, I currently have `@articles = Article.sport.all.paginate(page: params [:page], per_page: 12)` but I also want to show `Article.food` in the same pagination. – Timmy Von Heiss Feb 04 '16 at 04:21
  • I am trying to write a scope perhaps. – Timmy Von Heiss Feb 04 '16 at 04:53
  • Updated answer with the above – Richard Peck Feb 04 '16 at 09:30
  • How do you know to get from what is listed in the docs (which I read) to that code? It doesn't seem intuitive to me (noob). – Timmy Von Heiss Feb 04 '16 at 19:12
  • The docs are reference material. You cannot infer entire structural patterns from the documentation, just how specific functionality works. If you know how different functions work together, you can piece them together to get a workable solution – Richard Peck Feb 04 '16 at 20:13
  • The accumulated knowledge behind a recommendation on here is built from 10+ years of heavy computer usage; 3 years professional software development. One of the reasons I spend a long time on here is so I can keep my skills sharp, knowing how different aspects of the system work – Richard Peck Feb 04 '16 at 20:14