2014-10-01 61 views
2

我正在寻找在我的项目之一中的实施策略设计模式,这是在轨道上。基本上,我必须调用由数据库中的单个字段区分的对象的方法,而这种差异将确保不同的方法行为。在数据库中存储类名以模仿设计模式 - Ruby on Rails

经过一番研究,我发现红宝石很少需要设计模式,它使用鸭子打字。现在为了实现同样的效果,我正在考虑将类名称存储在数据库中,并在需要时调用该类的方法。像这样,

duckOne = Duck.find(id) 
duckOne[:className].fly(duckOne) #This scenario is same as Class.fly,but class is coming from db 

duckTwo = Duck.find(id) 
duckTwo[:className].fly(duckTwo) #Similar to above, just a different class from database 

有没有更好的方法来做到这一点?这种方法是否正确?

+0

的此另一种方法被定义在[此处](http://stackoverflow.com/questions/3570611/cheat-sheet-for-all-design-patterns-implemented-in - 鲁比),看看。 – Anss 2014-10-01 08:58:26

回答

1

基本上,从你所描述的,我认为你正在寻找Single Table Inheritance (STI)(你可能需要滚动才能找到信息)。

使用STI,您可以使用一个数据库表来表示来自同一个超类的多个类。 Rails使用名为type的列来知道将哪个类解释为db行。

您仍然可以在超类上使用find方法来查找各种子类模型。

例如:

class Bird < ActiveRecord::Base 
    def quack 
    "quack" 
    end 
end 

class Duck < Bird 
    def quack 
    "foo" 
    end 
end 

class Goose < Bird 
    def quack 
    "bar" 
    end 
end 

duck = Duck.create 
goose = Goose.create 

Bird.find(duck.id).quack 
# => "foo" 
Bird.find(goose.id).quack 
# => "bar" 
+0

这是一个可能的解决方案,但它完全不符合我的方案。我将类名存储在数据库中,获取它,做了'className.constantize',并将className用作class'className.fly'超级简单! – Anss 2014-10-01 14:30:56

+0

请解释此解决方案如何不符合您的“问题”(这似乎更像是一个讨论邀请)。我认为STI可以根据数据库中的某些数据来实现某种行为变化,尤其是与属于同一个表中的对象有关的情况。使用继承是在面向对象的上下文中建模的一种好方法。 – Jesper 2014-10-01 14:42:07

+0

当然,如果你想在几个模型上共享这个策略模式,其中一些不使用相同的数据库表,你最好做一些你所做的变体,或许把它抽象成一个模块。 – Jesper 2014-10-01 14:47:14