2012-03-09 60 views
5

我想将我的几个模型类扩展到“资产”类。 这四种类型的Assets中的每一种都能够生成一个slug从而避免set_callback(:save, :before)因此,我不想写出四种相同的方法,而是希望他们扩展一个Asset类,该类将具有set_callback(以及其他方法)。Mongoid的Rails模块

起初我试着简单地让它们扩展Asset类,但遇到了问题,当我将其中一个资产保存到数据库(mongo)时,它们插入的集合称为Asset而不是它们自己的名称。

在我搜索周围的人似乎推荐使用模块来代替。所以,我已经试过了:

module Asset 
    field :slug, :type => String 

    set_callback(:save, :before) do |document| 
    # make document.slug = to whatever 
    end 
end 

class Video 
    include Mongoid::Document 
    include Asset 
    field :video_name, :type => String 
    field :description, :type => String 
    field :some_more_fields, :type => String 
end 

,但我得到了一些错误,当我包括资产:

'undefined method `field' for Asset:Module' 

注:我使用Mongoid

回答

7

方法字段没有在已知资产模块的上下文。所以,你必须调用只有当模块包括现场:

module Asset 
    def self.included(base) 
     base.send(:field, :slug, :type => String) 
    end 
    end 

编辑:在代码块包装代码

+0

谢谢,对我很好。在我的Notifiable模块中也使用'''base.send(:before_create,:notify_on_create)''和''base.send(:embeds_many,:notifications,:as =>:notifiable)'''' – genkilabs 2013-07-26 20:02:37

+0

你将如何去发送声明在该模块范围? – Alex 2013-12-09 00:01:12

+0

我得到'包含':资产:模块(NoMethodError)未定义的方法'字段'。也许这不适用于Ruby 2.3.1? – 2016-05-06 18:10:08

2

好,使用的担忧使得这么多更容易和更好的写:

module Asset 
include extend ActiveSupport::Concern 
    included do 
    field: slug, type: String 
    before_create: :notify_on_create 
    scope: my_scope, ->(var) { where(slug: var) } 
    end 
end 
end 

查看http://api.rubyonrails.org/classes/ActiveSupport/Concern.html了解更多详情。