将代码从模块/类注入到另一个模块/类中

时间:2014-03-12 13:00:04

标签: ruby-on-rails ruby module metaprogramming dry

我想知道将模块/类中的代码注入另一个模块/类的常见做法。我有:

module MyModule
  extend ActiveSupport::Concern

  included do
    # The has_many association for Article / Post.
    has_many :comments

    # Here, from MyModule, I would like to "inject" the related belongs_to 
    # association into Comment where the belongs_to association should be
    # 'belongs_to :article' for Article and 'belongs_to :post' for Post.
  end

  module ClassMethods
    # ...
  end
end

class Article < ActiveRecord::Base
  include MyModule
end

class Post < ActiveRecord::Base
  include MyModule
end

class Comment < ActiveRecord::Base
end

要将belongs_to关联注入Comment,我可以使用instance_exec方法,但也许有更聪明的方法。我应该怎么做以避免重复代码?我应该include Comment中的MyModule个其他模块,还是将所有相关代码保存在{{1}}中,然后从那里注入?如何处理这些案件?

2 个答案:

答案 0 :(得分:0)

当模型属于多个其他模型时,您可以使用polymorphic associations,并且可以使用class_eval包含模块:

module MyModule  
  extend ActiveSupport::Concern  

  included do  
    has_many :comments, as: postable  

    Comment.class_eval do
      include Commentable
    end
  end 

  Module Commentable
    extend ActiveSupport::Concern

    included do
      belongs_to :postable, polymorphic: true
    end

    def ping
      p 'pong'
    end
  end 
end

class Article < ActiveRecord::Base
  include MyModule
end


class Post < ActiveRecord::Base
  include MyModule
end

class Comment < ActiveRecord::Base
end

以非多态方式,您可以定义包含如下:

def self.included(base)
  Comment.class_eval do
    belongs_to base.name.underscore # Will result in belongs_to :article and belongs_to :post in this case
  end
end

答案 1 :(得分:0)

我使用以下代码在我的一个项目中做类似的事情:

module MyModule
  extend ActiveSupport::Concern
  included do
    ...
  end

  def self.included(other)
    Comment.belongs_to(other.to_s.underscore.to_sym, {:options => 'whatever'})
  end

end