我有一个带有哈希字段的Mongoid模型。 这个Mongoid模型具有使用单集合继承的子类。 现在我想为主模型的每个子类设置不同的默认哈希键 。
主要模型
class Sport include Mongoid::Document field :rules, type: Hash, default: {} end我想为:rule hash字段设置不同的默认哈希键的子类。 例如,对于足球,我想要规则:{:offside =>'',:penalty =>''}对于拳击,我们可能有规则的哈希键:{:biting =>'not allowed'} 。 开源应用程序Errbit使用子类中的常量设置默认哈希键,但我可以看到他们如何使用常量来填充哈希值: https : //github.com/errbit/errbit/blob/master/app/车型/ issue_trackers / github_issues_tracker.rb
class Sport::Football < Sport end class Sport::Boxing < Sport end我确实覆盖了子类中的字段定义,如下所示,它在rails控制台中有效。 当我做一个= Sport :: Football.new然后调用a.smtp返回默认设置。 但问题是,当我去父类并执行b = Sport.new和b.smtp时 ,我希望它能够列出子类的所有默认键,但它没有,因为我已经覆盖了子类中的哈希字段 。
class Sport::Football < Sport field :rules, type: Hash, default: {:offside => '', :penalty => ''} end有没有办法为子类设置默认哈希键而不覆盖字段定义 。 可以通过覆盖每个子类中哈希字段的setter和getter来做到这一点。
I have a Mongoid model with a hash field. This Mongoid model has subclasses using single collection inheritance. Now I want to set different default hash keys for each subclass of the main model.
The main model
class Sport include Mongoid::Document field :rules, type: Hash, default: {} endSubclasses where I want to set different default hash keys for the :rule hash field. For instance, for football I want to have rules: {:offside => '', :penalty => ''} For Boxing we might have hash keys of rules: {:biting => 'not allowed'}. The open source app Errbit does something like it using constant in subclass to set default hash keys but I can see how they use the constant to populate the hash: https://github.com/errbit/errbit/blob/master/app/models/issue_trackers/github_issues_tracker.rb
class Sport::Football < Sport end class Sport::Boxing < Sport endI did overwrite the field definition in the subclass as shown below which works in the rails console. When I do a = Sport::Football.new and then call a.smtp returns the default settings. But the problem here is that when I go to the parent class and do b = Sport.new and b.smtp, I want it to be able to list all the default keys for the subclasses and it doesn't because I have overridden the hash field in the subclass.
class Sport::Football < Sport field :rules, type: Hash, default: {:offside => '', :penalty => ''} endIs there a way to set default hash keys for a subclass without overriding the field definition. It is okay to do this by overriding the setters and getters for the hash field in each subclass.
最满意答案
: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你还需要在Sport使用default_rules 。
您还可以使用其中一个回调来手动设置规则:
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 = ...
The :default option can take a lambda as its value. Inside that lambda, self will be the new instance you're creating. That means that you can (indirectly) call methods to supply defaults:
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 endYou don't have to make default_rules private of course. You'll also want default_rules in Sport if you want to instantiate Sport directly.
You could also use one of the callbacks to set the rules by hand:
class Sport include Mongoid::Document field :rules, type: Hash after_initialize :set_default_rules, :if => :new_record? # Or one of the other callbacks. endand subclasses could say self.rules = ... in their set_default_rules implementations.
更多推荐
发布评论