如何在Rails 3.1中复制class_inheritable_accessor的行为?
从Rails 3.1开始, class_inheritable_accessor
产生弃用警告,告诉我改为使用class_attribute
。 但是class_attribute
在一个重要的方面表现不同,我将演示。
class_inheritable_attribute
的典型用法是presenter类,如下所示:
module Presenter class Base class_inheritable_accessor :presented self.presented = {} def self.presents(*types) types_and_classes = types.extract_options! types.each {|t| types_and_classes[t] = t.to_s.tableize.classify.constantize } attr_accessor *types_and_classes.keys types_and_classes.keys.each do |t| presented[t] = types_and_classes[t] end end end end class PresenterTest {} PresenterTest.presented => {:user => User, :person => Person}
但是使用class_attribute
,子类会污染他们的父母:
Presenter::Base => {:user => User, :person => Person}
这根本不是理想的行为。 是否有其他类型的访问器行为正确,或者我是否需要完全切换到另一种模式? 如果没有class_inheritable_accessor
我应该如何复制相同的行为?
如果按预期使用, class_attribute
将不会污染其父级。 确保您没有就地更改可变项目。
types_and_classes.keys.each do |t| self.presented = presented.merge({t => types_and_classes[t]}) end
试试这个,这是在类上设置属性并且不会被inheritance或实例污染的好方法。
class Class private # Sets Unique Variables on a resource def inheritable_attr_accessor(*attrs) attrs.each do |attr| # Class Setter, Defining Setter define_singleton_method "#{attr}=".to_sym do |value| define_singleton_method attr do value end end # Default to nil self.send("#{attr}=".to_sym, nil) # Instance Setter define_method "#{attr}=".to_sym do |value| eval("@_#{attr} = value") end # Instance Getter, gets class var if nil define_method attr do eval("defined?(@_#{attr})") ? eval("@_#{attr}") : self.class.send(attr) end end end end