首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Ruby/Rails ORM建模继承

用Ruby/Rails ORM建模继承
EN

Stack Overflow用户
提问于 2011-08-27 17:40:16
回答 2查看 320关注 0票数 0

我试图为一个简单的博客系统建模这个继承

博客有很多Entries,但它们的本质可能不同。我不想对部落格表建模,我关心的是条目:

最简单的条目是有text

  • Quote,和titleArticle,但是没有标题,并且有短的Articleurlcomment...

  • etc...

用对此进行建模的正确方法是什么?那是

  • Should I为此使用ActiverRecord或切换到DataMapper?
  • I,希望避免使用“一个大表”方法,使用大量的空单元格

当我将数据拆分为Entry + PostDataQuoteData等时,可以在这些数据中使用belongs_to :entry而不必在Entry类中使用has_one ???吗?这将是在sql中使用的标准方法,entry.post_data可以由postdata表中的entry_id解析。

编辑:我不想对博客表建模,我可以这样做,我关心的是条目,以及如何将继承映射到表中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-27 18:42:17

我曾多次遇到这个数据问题,并尝试过几种不同的策略。我认为我最喜欢的就是cicloon提到的STI方法。确保在条目表中有一个type列。

代码语言:javascript
复制
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关联,从而在条目表中没有额外的列。当您执行您的观点时,它也非常有用:

代码语言:javascript
复制
app/views/articles/_article.html.erb
app/views/quotes/_quote.html.erb
app/views/media/_media.html.erb # may be medium here....

从你的观点来看,你可以这样做:

代码语言:javascript
复制
<%= render @blog.entries %> <!-- this will automatically render the appropriate view partial -->

或者拥有更多的控制权:

代码语言:javascript
复制
<%= render @blog.quotes %>
<%= render @blog.articles %>

您也可以找到一种生成表单的相当通用的方法,我通常在entries/_form.html.erb部分中呈现泛型输入字段。在那个部分里,我也有一个

代码语言:javascript
复制
<%= 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,而我的表媒体是我的。您可能需要在这个命名上添加一个自定义的变化,尽管我不确定。

票数 2
EN

Stack Overflow用户

发布于 2011-08-27 18:05:31

您可以使用ActiveRecord STI轻松地处理这一问题。它要求在条目表中有一个类型字段。这样你就可以像这样定义你的模型:

代码语言:javascript
复制
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
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7216215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档