如何在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