So, cattr_accessor doesn’t work like it should?

Posted by Dr Nic on August 27, 2006 and blessed with 6 comments

Rails’ active_support library adds some wonderful functions into standard Ruby classes. Some we all use day-in-day out are attr_accessor and its class-level equivalent, cattr_accessor.

But cattr_accessor doesn’t work the way you (read, “me”) thought at first glance when you use subclasses. I thought if I declared a class accessor in the superclass, then I would have independent class attributes for all my subclasses. Apparently not…

>> class Parent; cattr_accessor :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 5

Child1.val and Child2.val seem to be the same value. Not very independent at all. Internally, the classes share a common class attribute. This is useful in certain circumstances, but not what I was looking for.

Instead, I found class_inheritable_accessor.

>> class Parent; class_inheritable_accessor :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val = 4
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 4

Lovely. Each subclass will have an independent value once you’ve assigned it a value explicitly, else it will pick up the value from its superclass.

UPDATE: class_inheritable_accessor and co. actually clone the superclass’s inherited attributes, rather than just referencing them.

Related posts:

  1. Magic Multi-Connections: A “facility in Rails to talk to more than one database at a time” At this point in time there’s no facility in Rails...
  2. Turn-based game DSL Late in the night, whilst the baby feeds, I continue...
  3. Extending _why’s Creature class Many Rubist’s first explanation of metaprogramming is by why the...
  4. [BTS] Magic Models vs ActiveRecords – Efficiency Dr Nic’s Magic Models are magical, that goes without saying....
  5. [BTS] Magic Models – Class creation [BTS] = Behind the Scenes; also a news-like TV show...
Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. choonkeat Sun, 27 Aug 2006 19:20:39 UTC

    hmm, correction. attr_accessor comes from ruby, not from active_support.

  2. Dr Nic Sun, 27 Aug 2006 19:23:36 UTC

    Yeah, sorry. cattr* and mattr* are added by rails.

  3. Chris Sun, 27 Aug 2006 22:40:46 UTC

    Nice find!

  4. Ramble On - Don’t Do That Thu, 05 Apr 2007 21:58:46 UTC

    [...] There’s a bit of discussion this on a separate, but related problem at Evan Weaver’s blog (pay special attention to that threading issue for those playing along with the home game). And of course, your friendly neighborhood reminder of what happens with class variables at Nic Williams’ blog (I recommend reading that twice and breaking out the home game version of irb) [...]

  5. [...] 节选了部分代码,调用流程为process -> perform_action => action || method_missing || template || raise UnknownAction 其中需要注意的几点: 1,@@default_charset = “utf-8″ 2,attr_internal的属性有request、params、response、session、headers 3,cattr_accessor的属性有default_charset、logger、consider_all_requests_local等 catter_accessor标识的是Class Attributes,见这篇BlogSo, cattr_accessor doesn’t work like it should? catter_accessor方法的定义在active_supportcore_extclassattribute_accessors.rb: 代码 class Class def cattr_reader(*syms) syms.flatten.each do |sym| next if sym.is_a?(Hash) class_eval(<< render_file 2):text -> render_text 3):file -> render_file 4):template -> render_file 5):inline -> render_template 6):action -> render_action 7):xml -> render_xml 8):json -> render_json 9):partial -> render_partial || render_partial_collection 10):update -> render_javascript 11):noting -> render_text 5,redirect_to方法的参数有: 1)Hash -> redirect_to(url_for(options)) [code] redirect_to :action => “show”, :id => 5 [...]

  6. Andy Goundry Tue, 17 Jul 2007 11:22:38 UTC

    Wonderful post! Is the exact solution to my needs. I was (and still am) baffled that this stuff isn’t available in Ruby.

    Thanks!

Comments