我想让多个模型具有常见的货币转换实现,并使用常见的常量名称 - 这里是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
我该怎么做?
答案 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