我试图为一个简单的博客系统建模这个继承
博客有很多Entries,但它们的本质可能不同。我不想对部落格表建模,我关心的是条目:
最简单的条目是有text
Quote,和title的Article,但是没有标题,并且有短的Article有url和comment...
用对此进行建模的正确方法是什么?那是
。
当我将数据拆分为Entry + PostData、QuoteData等时,可以在这些数据中使用belongs_to :entry而不必在Entry类中使用has_one ???吗?这将是在sql中使用的标准方法,entry.post_data可以由postdata表中的entry_id解析。
编辑:我不想对博客表建模,我可以这样做,我关心的是条目,以及如何将继承映射到表中。
发布于 2011-08-27 18:42:17
我曾多次遇到这个数据问题,并尝试过几种不同的策略。我认为我最喜欢的就是cicloon提到的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)您不能通过update属性设置:type字段,您的控制器必须实例化适当的Article.new来保存它(您可以在这里使用工厂)。
2)您必须使用becomes()方法(@article.becomes(Entry))来处理条目,而不是子类。
希望这能有所帮助。
警告说,我以前确实用过媒体作为模型名。在我的例子中,它在rails 2.3.x中产生了一个名为medias的表,但是在rails 3中,它希望我的模型被命名为media,而我的表媒体是我的。您可能需要在这个命名上添加一个自定义的变化,尽管我不确定。
发布于 2011-08-27 18:05:31
您可以使用ActiveRecord STI轻松地处理这一问题。它要求在条目表中有一个类型字段。这样你就可以像这样定义你的模型:
def Blog > ActiveRecord::Base
has_many :entries
def articles
entries.where('Type =', 'Article')
end
def quotes
entries.where('Type =', 'Quote')
end
def medias
entries.where('Type =', 'Media')
end
end
def Entry > ActiveRecord::Base
belongs_to :blog
end
def Article > Entry
end
def Quote > Entry
end
def Media > Entry
endhttps://stackoverflow.com/questions/7216215
复制相似问题