I'm having a trouble figuring out how to access a variable in a class << self from another class. I've searched and found many questions close to this but not exactly:
class << self
##var="foo"
end
class A
puts ##var
end
I've even tried creating class A within class << self with no luck either.
How can I access ##var?
You can do this:
class << self
##var="foo"
end
self.class.class_variable_get :##var
But I'm really skeptical that you actually need to use a class variable in a singleton class. It seems complicated. Maybe you could ask another question explaining what you're really trying to do.
Related
I know how you can add class methods and class-behaviour using self << class (eigenclass). But, when reading some source code, I saw another use:
class LetterAvatar
class << self
class Identity
end
end
end
How does this work? What does it do and when should one use it? What would be a (possibly more recognised) alternative way to write this?
I think they did so because they did not need this class anywhere else.
Without opening the singleton class the flow would look as following (assuming every method defined in metaclass from original code would be prefixed with self.):
They could have defined the Identity as
class LetterAvatar
class Identity
end
end
and then use the class in self.generate method as follows:
class LetterAvatar
# code omitted
def self.generate
identity = LetterAvatar::Identity.from_username(username)
# code omitted
end
# other class level methods defined with `self.`
end
But why doing so if the Identity class is actually used only (and need not to be accessed anywhere else) in the singleton class (in generate)?
The solution is IMO very elegant, haven't seen anything like this before.
I'm going through the Ruby Koans Ruby Koans and I'm at a place in "about_class_methods.rb" where there is a discussion of setting up class methods, and the Koans talk about three ways.
The two major ways to write class methods are:
1:
class Demo (define/open class)
def self.method
end
2:
class << self
def class_methods
end
end
The koans also talk about a third method, I've never seen (that I remember):
def Demo.class_method_third_way
end
Q1 This third way is actually clearer to me than any other. Is there a reason I don't understand about why no one uses it?
Q2 Why am I wrong in thinking the syntax for 2 should be "self << def name end"? That is "Why is the syntax the way it is?" Does the class Object hold a reference to all Classes and this sticks in the method for the self class?
As always, thanks for your help and patience!
In (early) development classes get renamed as insight grows (not Person but Employee, not Job but one or more Roles etc.) This renaming is prone to errors if the class name is hardcoded in the class itself.
In class body, self refers exactly the class object being defined. That's why def self.some_method works the same as def Demo.some_method.
class Demo
puts self.object_id == Demo.object_id
end
#=> true
class << some_obj is the syntax to access the singleton class of some_obj. Refer to the Ruby doc:
The singleton class (also known as the metaclass or eigenclass) of an object is a class that holds methods for only that instance. You can access the singleton class of an object using class << object ... Most frequently you’ll see the singleton class accessed like this:
class C
class << self
# ...
end
# or
class << C
end
end
I'm working on this tutorial here:
http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/39-ruby-s-object-model/lessons/131-singleton-methods-and-metaclasses
The lesson is on classes/metaclasses, but they are using a syntax that I'm not familiar with. Please see the use of << below
class Object
def metaclass
class << self
self
end
end
end
a=Object.new
p a.metaclass.new
I know def metaclass is a method, but what is meant by class << self? It has a corresponding end block, but I'm still very unclear what this is exactly doing
(Note: The point of the above exercise is just showing that you cannot instantiate a metaclass -- which I understand, I'm just having trouble wrapping my head around that << operator in this context.
Thanks!
class << self opens up self's singleton class, so that methods can be redefined for the current self object.
Let's look at a particular example:
s = String.new("abc")
s.metaclass
=> "#<Class:#<String:0x0000010117e5d8>>"
Let's have a closer look at what happens here:
Inside the definition of metaclass, self refers to the current instance, in this example the string "abc".
class << self in this example is equivalent to class << "abc" which opens up the singleton-class of that given instance , in this case String "abc".
It then returns self inside the opened-up class of the current instance -- the opened-up class is in the example the class String.
In general, the definition of metaclass opens up the class definition of the class of the given instance/object, and then returns that class name.
A more detailed look at 'self' can be found in Yehuda Katz's article "Metaprogramming in Ruby: It’s All About the Self".
I also recommend the screen-cast series by the Pragmatic Programmers on The Ruby Object Model and Metaprogramming.
I can't seem to grasp the exact difference between these two "constructs". To my mind, the following small script should output the same thing three times:
class Example
puts self
class << self
puts self
end
instance_eval do
puts self
end
end
However, the output is:
Example
#<Class:Example>
Example
Here's my rationale:
Example is an instance of Class, so self in the class body refers to that;
class << obj sets self to whatever obj is in the given block, which in my case is the instance of Class that is Example (this is where I'm probably wrong);
instance_eval runs the block in the given instance, so, in my case it's pretty much the same as putting the code in the block directly in the class body.
My current guess is that class << self inserts a ghost class between Example and Class and sets self to that, but the output of #<Class:Example> is not confirming that at all.
So what is wrong with my rationale?
class << obj sets self to whatever obj is in the given block, which in my case is the instance of Class that is Example (this is where I'm probably wrong);
No, class << obj opens up the singleton class of obj. As you correctly pointed out, inside of a class declaration, self refers to the class itself, so, in this case, the "inner" self (i.e. the one being passed to puts) refers to the singleton class of Example.
In my opinion, class << self has been one of the most obnoxious bits of syntax in Ruby. People new to the language have little idea what it means, apart from cargo-cult conventions, and even those intimately familiar with the language have only a hazy understanding of what differentiates it from instance_method, as the two do seem to be remarkably similar.
Here's an example of two different ways of defining a class method:
class Example
class << self
def class_def
:class_def
end
end
instance_eval do
def instance_def
:instance_def
end
end
end
You can check that these work by calling the methods:
puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => :instance_def
The difference is when you're dynamically creating methods using define_method since the binding does appear to be incorrect on the instance_eval version:
class Example
class << self
define_method(:class_def) do
:class_def
end
end
instance_eval do
define_method(:instance_def) do
:instance_def
end
end
end
This results in the instance_def method being defined, but not being bound to the class itself:
puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => NoMethodError: undefined method ‘instance_def’ for Example:Class
The only reliable way to create dynamic methods is with class << self. The method instance_def appears to be created and discarded as it doesn't show up in Example.methods even inside that block.
I'm trying to learn ruby by building a basic Campfire bot to screw around with at work. I've gotten pretty far (it works!) and learned a lot (it works!), but now I'm trying to make it a bit more complex by separating the actions to be performed out into their own classes, so that they can be easier to write / fix when broken. If you're interested in seeing all the (probably crappy) code, it's all up on GitHub. But for the sake of this question, I'll narrow the scope a bit.
Ideally, I would like to be able to create plugins easily, name them the same as the class name, and drop them into an "actions" directory in the root of the project, where they will be instantiated at runtime. I want the plugins themselves to be as simple as possible to write, so I want them all to inherit some basic methods and properties from an action class.
Here is action.rb as it currently exists:
module CampfireBot
class Action
#handlers = {}
def initialize(room)
#room = room
end
class << self
attr_reader :handlers
attr_reader :room
def hear(pattern, &action)
Action.handlers[pattern] = action
end
end
end
end
Where #room is the room object, and #handlers is a hash of patterns and blocks. I kind of don't understand why I have to do that class << self call, but that's the only way I could get the child plugin classes to see that hear method.
I then attempt to create a simple plugin like so (named Foo.rb):
class Foo < CampfireBot::Action
hear /foo/i do
#room.speak "bar"
end
end
I then have my plugins instantiated inside bot.rb like so:
def load_handlers(room)
actions = Dir.entries("#{BOT_ROOT}/actions").delete_if {|action| /^\./.match(action)}
action_classes = []
# load the source
actions.each do |action|
load "#{BOT_ROOT}/actions/#{action}"
action_classes.push(action.chomp(".rb"))
end
# and instantiate
action_classes.each do |action_class|
Kernel.const_get(action_class).new(room)
end
#handlers = Action.handlers
end
The blocks are then called inside room.rb when the pattern is matched by the following:
handlers.each do |pattern, action|
if pattern.match(msg)
action.call($~)
end
end
If I do puts #room inside the initialization of Action, I see the room object printed out in the console. And if I do puts "foo" inside Foo.rb's hear method, I see foo printed out on the console (so, the pattern match is working). But, I can't read that #room object from the parent class (it comes out as a nil object). So obviously I'm missing something about how this is supposed to be working.
Furthermore, if I do something to make the plugin a bit cleaner (for larger functions) and rewrite it like so:
class Foo < CampfireBot::Action
hear /foo/i do
say_bar
end
def say_bar
#room.speak "bar"
end
end
I get NoMethodError: undefined method 'say_bar' for Foo:Class.
The definition of hear can be pulled out of the class << self block and changed to:
def self.hear(pattern, &action)
Action.handlers[pattern] = action
end
to yield the exact same result. That also immediately explains the problem. hear Is a class method. say_bar is an instance method. You can't call an instance method from a class method, because there simply isn't an instance of the class available.
To understand the class << self bit, you'll have to do your own reading and experiments: I won't try to improve on what has already been said. I'll only say that within the class << self .. end block, self refers to the eigenclass or metaclass of the CampfireBot::Action class. This is the instance of the Class class that holds the definition of the CampfireBot::Action class.