造型继承使用Ruby / Rails的奥姆斯 [英] Modeling inheritance with Ruby/Rails ORMs

查看:267
本文介绍了造型继承使用Ruby / Rails的奥姆斯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想这个继承模型的一个简单的博客系统

I'm trying to model this inheritance for a simple blog system

博客有很多条目,但他们可能会在他们的性质不同。我不想博客表模型,我关心的是有关的条目:

Blog has many Entries, but they may be different in their nature. I don't want to model the Blog table, my concern is about the entries:

  • 在简单的条目是文章,有标题文本
  • 引用,但是,没有一个标题和短文本
  • 传媒有一个网​​址评论。 ..
  • 等等...
  • simplest entry is an Article that has title and text
  • Quote, however, does not have a title and has short text
  • Media has a url and a comment...
  • etc...

什么是正确的方法来模拟这种使用Ruby on Rails的?这就是

What is a proper way to model this with Ruby on Rails? That is

  • 我应该使用ActiverRecord这个或切换到DataMapper的?
  • 我想,以避免有很多空单元格的一大桌的做法

当我将数据拆分成输入 + 的PostData QuoteData 等我可以有 belongs_to的:进入在这些DATAS,而无需在<$ C HAS_ONE ??? $ C>输入类?这将是标准的方式来做到这一点的SQL和 entry.post_data 可以通过 entry_id 在<$得到解决C $ C> POSTDATA 表。

When I split the data into Entry + PostData, QuoteData etc can I have belongs_to :entry in these Datas without having has_one ??? in the Entry class? That would be standard way to do it in sql and entry.post_data may be resolved by the entry_id in the postdata table.

编辑:我不想博客表模型,我能做到这一点,我关心的是有关条目以及如何将继承映射表(S)

I don't want to model the Blog table, I can do that, my concern is about the entries and how would the inheritance be mapped to the table(s).

推荐答案

我已经遇到这个数据的问题几次,并尝试了一些不同的策略。我想一个我的忠实粉丝,是所提到的cicloon的STI的方法。请确保您有一个键入列在你的项目表。

I've come across this data problem several times and have tried a few different strategies. I think the one I'm a biggest fan of, is the STI approach as mentioned by cicloon. Make sure you have a type column on your entry table.

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协会给他们,从而对您的输入表中增加额外的列。它也工作得很好,当你做你的观点的:

The thing I like about this approach, is you can keep the generic Entry data in the entry model. Abstract out any of the sub-entry type data into their own data tables, and have a has_one association to them, resulting in no extra columns on your entries table. It also works very well for when you're doing your views:

app/views/articles/_article.html.erb
app/views/quotes/_quote.html.erb
app/views/media/_media.html.erb # may be medium here....

和从你的观点,你可以做两种:

and from your views you can do either:

<%= render @blog.entries %> <!-- this will automatically render the appropriate view partial -->

或有更多的控制:

or have more control:

<%= render @blog.quotes %>
<%= render @blog.articles %>

您可以找到的产生形成了一个pretty的通用方式,以及,我通常会呈现一个输入/ _form.html.erb 部分通用输入字段。在那个部分,我也有一个

You can find a pretty generic way of generating forms as well, I usually render the generic entry fields in an entries/_form.html.erb partial. Inside that partial, I also have a

<%= 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 打通正确传递的数据。

type render for the sub form data. The sub forms in turn can use accepts_nested_attributes_for + fields_for to get the data passed through properly.

唯一的痛苦,我有这样的做法,是如何处理的控制器和路线佣工。由于每一项都是它自己的类型的,你要么必须创建自定义的控制器/为每个类型的路由(你可能想要这个...),或使通用的。如果你把通用的方法,有两件事要记住。

The only pain I have with this approach, is how to handle the controllers and route helpers. Since each entry is of its own type, you'll either have to create custom controllers / routes for each type (you may want this...) or make a generic one. If you take the generic approach, two things to remember.

1)你不能设置一个:通过更新类型字段属性,您的控制器将有实例相应的 Article.new 来保存它(您可以使用此工厂)。

1) You can't set a :type field through update attributes, your controller will have to instantiate the appropriate Article.new to save it (you may use a factory here).

2)你必须使用成为()办法( @ article.becomes(输入) ),以与条目作为条目,而不是一个子类的工作。

2) You'll have to use the becomes() method (@article.becomes(Entry)) to work with the entry as an Entry and not a subclass.

希望这有助于。

警告,我已经实际使用媒体作为过去一个型号名称。在我的情况下,它导致了一个名为然而,在轨媒体2.3.x导轨中3台,它希望我的模型被命名为中型和我同桌的媒体。您可能需要添加自定义的拐点在这个命名,虽然我不知道。

这篇关于造型继承使用Ruby / Rails的奥姆斯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆