我遇到過這個數據問題幾次,並嘗試了幾種不同的策略。我認爲我最大的粉絲之一就是CCI提到的STI方法。確保您的入口表上有一個type
列。
class Blog < ActiveRecord::Base
# this is your generic association that would return all types of entries
has_many :entries
# you can also add other associations specific to each type.
# through STI, rails is aware that a media_entry is in fact an Entry
# and will do most of the work for you. These will automatically do what cicloon.
# did manually via his methods.
has_many :articles
has_many :quotes
has_many :media
end
class Entry < ActiveRecord::Base
end
class Article < Entry
has_one :article_data
end
class Quote < Entry
has_one :quote_data
end
class Media < Entry
has_one :media_data
end
class ArticleData < ActiveRecord::Base
belongs_to :article # smart enough to know this is actually an entry
end
class QuoteData < ActiveRecord::Base
belongs_to :quote
end
class MediaData < ActiveRecord::Base
belongs_to :media
end
我喜歡這種方式的事情,是你可以保持通用輸入數據的入門車型。將任何子條目類型數據抽象到它們自己的數據表中,並將它們與has_one關聯起來,從而不會在條目表上產生額外的列。它也工作得很好,當你做你的意見爲:
app/views/articles/_article.html.erb
app/views/quotes/_quote.html.erb
app/views/media/_media.html.erb # may be medium here....
,並從你的觀點,你可以做兩種:
<%= render @blog.entries %> <!-- this will automatically render the appropriate view partial -->
或有更多的控制:
<%= render @blog.quotes %>
<%= render @blog.articles %>
你可以找到一種非常通用的生成表單的方式,我通常會在entries/_form.html.erb
部分中顯示通用輸入字段。在該部分中,我也有一個
<%= form_for @entry do |f| %>
<%= render :partial => "#{f.object.class.name.tableize}/#{f.object.class.name.underscore}_form", :object => f %>
<% end %>
爲子表單數據類型呈現。子表單反過來可以使用accepts_nested_attributes_for
+ fields_for
來正確傳遞數據。
我對這種方法唯一的痛苦是如何處理控制器和路由幫助器。由於每個條目都是自己的類型,因此您必須爲每種類型創建自定義控制器/路由(您可能需要這樣...)或創建一個通用控制器。如果你採用通用方法,需要記住兩件事。
1)你不能通過更新屬性來設置:type
字段,你的控制器將不得不實例化合適的Article.new
來保存它(你可以在這裏使用一個工廠)。
2)您將不得不使用becomes()
方法(@article.becomes(Entry)
)將條目作爲條目而不是子類使用。
希望這會有所幫助。
警告,我實際上在過去使用過媒體作爲模型名稱。在我的情況下,它導致了一個名爲medias的表格,但是在rails 3中,它希望我的模型被命名爲Medium和我的表格媒體。儘管我不確定,但您可能必須在此命名中添加一個自定義的拐點。
感謝您的回答。但有一個問題:我必須在Blog中指定has_many:articles和has_many:引號嗎?爲什麼不只是has_many:條目?我不希望列舉某種特定類型的條目。 – tillda
感謝您的編輯標記,我沒有時間:)。 沒有蒂爾達,你可以簡單地使用條目關聯,如果這只是你想要的。如果以上述方式進行操作,則可以渲染條目列表,並且軌道將呈現適當的部分。 –