2014-04-01 141 views
3

我有一个哈希字段的Mongoid模型。这个Mongoid模型具有使用单个集合继承的子类。现在我想为主模型的每个子类设置不同的默认散列键为mongoid哈希字段设置默认哈希键

主要模式

class Sport 
    include Mongoid::Document 
    field :rules, type: Hash, default: {} 
end 

子类,我想设置不同默认的哈希键:规则哈希场。例如,对于足球我想要有规则:{:offside =>'',:penalty =>''}对于拳击,我们可能有规则的散列键{:biting =>'不允许'} 。开源应用Errbit做了它在子类中使用常数设置默认哈希键,但我可以看到他们是如何使用常量来填充哈希,如:https://github.com/errbit/errbit/blob/master/app/models/issue_trackers/github_issues_tracker.rb

class Sport::Football < Sport 
end 

class Sport::Boxing < Sport 
end 

我并覆盖在子类中的字段定义如下所示,可在导轨控制台中使用。当我做a = Sport :: Football.new然后致电a.smtp返回默认设置。但这里的问题是,当我去到父类,并做b = Sport.newb.smtp,我希望它能够列出所有的子类的默认键,它不是因为我已覆盖子类中的散列字段。

class Sport::Football < Sport 
    field :rules, type: Hash, default: {:offside => '', :penalty => ''} 
end 

有没有一种方法来设置一个子类默认哈希键不重写字段定义。可以通过覆盖每个子类中散列字段的setter和getter来完成此操作。

回答

5

:default选项可以将lambda作为其值。在该lambda中,self将成为您创建的新实例。这意味着,你可以(间接)调用方法提供的默认值:

class Sport 
    include Mongoid::Document 
    field :rules, type: Hash, default: lambda { default_rules } 
end 

class Sport::Football < Sport 
private 
    def default_rules 
    { :offside => '', :penalty => '' } 
    end 
end 

class Sport::Boxing < Sport 
private 
    def default_rules 
    { :biting => 'not allowed except for ears' } 
    end 
end 

你不必做default_rules私人课程。如果您想直接实例化Sport,则还需要default_rules中的Sport

您也可以使用回调的一个手工设置的规则:

class Sport 
    include Mongoid::Document 
    field :rules, type: Hash 
    after_initialize :set_default_rules, :if => :new_record? # Or one of the other callbacks. 
end 

和子类可以说在他们set_default_rules实现self.rules = ...

+0

谢谢。我需要添加的唯一更改是在体育模型中代表** default_rules **的空方法。没有这一点,如果我打电话** Sport.new **它会引发错误** NameError:未定义的局部变量或方法'default_rules'**。如果没有更好的办法来防止这种错误,那么我可以离开那里。 – brg

+0

这是故意的,我将Sport看作是一种永远不会实例化的虚拟基类(即只有子类会被实例化)。 –

+0

确定这是更清楚。干杯。 – brg