How do I replicate class_inheritable_accessor's behavior in Rails 3.1?

Beginning with Rails 3.1, class_inheritable_accessor produces deprecation warnings, telling me to use class_attribute instead. But class_attribute behaves differently in an important way which I will demonstrate.

A typical use of class_inheritable_attribute would be a presenter class, like so:

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 < Presenter::Base
  presents :user, :person
end

Presenter::Base.presented => {}
PresenterTest.presented => {:user => User, :person => Person}

But using class_attribute, subclasses will pollute their parents:

Presenter::Base => {:user => User, :person => Person}

Which is not desired behavior at all. Is there another type of accessor that behaves the correct way, or do I need to switch to another pattern altogether? How should I replicate the same behavior without class_inheritable_accessor?

  • EventMachine gem workaround causes missing dll file ruby error, Windows 7
  • Ruby on Rails User interface Gems
  • Is it possible to update from an action/method other than the update action/method in Ruby on rails?
  • Is saving current users id to db via controllers create action a bad choice in ruby on rails?
  • Creating a new rails 3 project over a proxy in windows
  • Why am I getting Gem::LoadError when requiring the clockwork gem?
  • How can I connect to MySQL in Ruby on Rails?
  • Caching Issue with thumbs_up gem
  • 2 Solutions collect form web for “How do I replicate class_inheritable_accessor's behavior in Rails 3.1?”

    class_attribute won’t pollute its parent if it’s used as intended. Make sure you’re not changing the mutable items in-place.

    types_and_classes.keys.each do |t|
      self.presented = presented.merge({t => types_and_classes[t]})
    end
    

    Give this a try, a great way to have attributes set on the class, and not polluted by inheritance or instances.

    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
    
    Ruby is the best programming language in the world - Ruby on Rails.