Skip to content

Instantly share code, notes, and snippets.

@charissa
Created March 18, 2011 04:23
Show Gist options
  • Save charissa/875615 to your computer and use it in GitHub Desktop.
Save charissa/875615 to your computer and use it in GitHub Desktop.
This makes a class_attr_accessor Class method a la email from Snuggs.
#!/opt/local/bin/ruby1.9
class Class
def self.class_attr_accessor *accessors
accessors.each do |accessor|
define_method(accessor) do
class_variable_get("@@#{accessor}")
end
define_method("#{accessor}=") do |val|
class_variable_set("@@#{accessor}", val)
end
end
end
end
class Customer
Class.class_attr_accessor "no_of_customers"
@@no_of_customers=0
def initialize
@@no_of_customers+=1
end
# def Customer.no_of_customers
# @@no_of_customers
# end
end
puts Class.methods(false).sort
#puts Customer.methods.sort
a=Customer.new
#puts Customer.methods.sort
puts Customer.no_of_customers
Customer.new
puts Customer.no_of_customers
@charissa
Copy link
Author

Here is the result:

class_attr_accessor
1
2

@charissa
Copy link
Author

If self inspection is useful, maybe the added comments will add some light to what is going on. Otherwise maybe some self -introspection would help....

In retrospect this seems obvious, but the define_method(accessor) seems only to be run when the accessor is is used on a Class, e.g., when I say Customer.no_of_customers. Does this mean that the syntax, etc. is only checked at that point? I think so, which means it is very important to have tests that test ALL the conditions/edge-conditions of your code, lest certain code remains un-exercised until someone goes there in production...

    class Class
      def self.class_attr_accessor *accessors

      puts "1: "+self.to_s
    # self is Class
        accessors.each do |accessor|
      puts "2: "+self.to_s
    # self is still Class
          define_method(accessor) do
      puts "3: "+self.to_s
    # now self is the class within which this method was called/just as it would be in a def accessor block in Class (e.g.,) foo although in that case I think it would be the instance....
            class_variable_get("@@#{accessor}")
          end
      puts "4: "+self.to_s
    # self is Class again
          define_method("#{accessor}=") do |val|
      puts "5: "+self.to_s
    # now self is again the class within which this method was called/just as it would be in a def accessor block in Class (e.g.,) foo 
            class_variable_set("@@#{accessor}", val)
          end
      puts "6: "+self.to_s
    # self is now Class again
        end
      end
    end     


    class Customer

    puts"starting Class Customer"
      Class::class_attr_accessor "no_of_customers"
       @@no_of_customers=0
       def initialize
          @@no_of_customers+=1
       end
    end

    puts Class.methods(false).sort

    #puts Customer.methods.sort
    a=Customer.new
    #puts Customer.methods.sort
    puts Customer.no_of_customers
    Customer.new
    puts Customer.no_of_customers
    Customer.no_of_customers = -99

and the result:

    starting Class Customer
    1: Class
    2: Class
    4: Class
    6: Class
    class_attr_accessor
    3: Customer
    1
    3: Customer
    2
    5: Customer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment