2014-04-01 108 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