在活动模型关注中使用公共类常量名称

时间:2015-07-13 08:07:28

标签: ruby-on-rails ruby-on-rails-4 activemodel

我想让多个模型具有常见的货币转换实现,并使用常见的常量名称 - 这里是PRICE_ATTR

module Priceable
  extend ActiveSupport::Concern

  def value_for(attr, rate)
    (self.send(attr) / rate).round(2)
  end

  PRICE_ATTR.each do |attribute|
    method_name = "#{attribute}_currency".to_sym
    define_method(method_name) do |rate|
      value_for(attribute, rate)
    end
  end
end

class Design
  PRICE_ATTR = [:discount_price, :price]
  include Priceable
end

class Cart
  PRICE_ATTR = [:snapshot_price]
  include Priceable
end

我该怎么做?

2 个答案:

答案 0 :(得分:2)

这是Module#included的用途!

module Priceable
  extend ActiveSupport::Concern

  def value_for(attr, rate)
    (self.send(attr) / rate).round(2)
  end

  def self.included(othermod)
    othermod::PRICE_ATTR.each do |attribute|
      method_name = "#{attribute}_currency".to_sym
      othermod.send :define_method, method_name do |rate|
        value_for(attribute, rate)
      end
    end
  end
end

class Design
  PRICE_ATTR = [:discount_price, :price]
  include Priceable
end

class Cart
  PRICE_ATTR = [:snapshot_price]
  include Priceable
end

将Priceable包含到另一个模块中时会运行,该模块作为参数othermod传递。在该模块中,您可以遍历包含模块的PRICE_ATTR数组并在其上定义方法。

答案 1 :(得分:0)

您可以使用如下

module Priceable
  extend ActiveSupport::Concern
  included do
    class_variable_set(:@@price_attrs , [])
  end

  module ClassMethods
    def has_prizes(attrs)
      class_variable_set(:@@price_attrs, attrs)
    end
  end

  def value_for(attr, rate)
    (self.send(attr) / rate).round(2)
  end

  class_variable_get(:@@price_attrs).each do |attribute|
    method_name = "#{attribute}_currency".to_sym
    define_method(method_name) do |rate|
      value_for(attribute, rate)
    end
  end
end

class Design
  PRICE_ATTR = [:discount_price, :price]
  include Priceable
  has_prizes PRICE_ATTR
end

class Cart
  PRICE_ATTR = [:snapshot_price]
  include Priceable
  has_prizes PRICE_ATTR

end

或者您可以使用cattr_accessor代替class_variable_get和class_variable_get