This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does ##variable mean in Ruby?
What is the difference when I declare an object with double '#'
##lexicon = Lexicon.new()
and declaring object with single '#' in Ruby?
#lexicon = Lexicon.new()
The difference is that the first one is a class variable and the second one is an instance variable.
An instance variable is only available to that instance of an object. i.e.
class Yasin
def foo=(value)
#foo = value
end
def foo
#foo
end
end
yasin = Yasin.new
yasin.foo=1
yasin.foo #=> 1
yasin_2 = Yasin.new
yasin_2.foo #> nil
A class variable is available to all instances of the class (and subclasses, iirc) where the class variable was defined.
class Yasin
def foo=(value)
##foo = value
end
def foo
##foo
end
end
yasin = Yasin.new
yasin.foo=1
yasin.foo #=> 1
yasin_2 = Yasin.new
yasin_2.foo #=> 1
Related
This question already has an answer here:
Closures in Ruby with Module
(1 answer)
Closed 4 months ago.
I have a question about scopes in ruby, why the baz method cannot access the variable foo, it seems counter intuitive because the scope of baz is contained in that of create_B
class A
def self.create_B(foo)
Class.new do
def baz
p foo
end
end
end
end
A.create_B(4).new.baz
NameError: undefined local variable or method `foo' for #<#<Class:0x00007f3a31bddf18>:0x00007f3a31bdde28>
from (pry):23:in `baz'
The def keyword creates a new scope. In order to access variables that were defined outside, you can use the define_method method:
class A
def self.create_B(foo)
Class.new do
define_method(:baz) do
p foo
end
end
end
end
A.create_B(4).new.baz
#=> 4
This question already has an answer here:
Ruby looks for class variable in the Object instead of specific class
(1 answer)
Closed 6 years ago.
(Question already posted at Ruby Forum, but did not evoke any answer there).
This is my code:
class MC
def initialize
#x = 5
##y = 6
end
def f
puts #x
puts ##y
end
end
m = MC.new
m.f
m.f produces the expected output without an error:
5
6
But this:
def m.g
puts #x
puts ##y
end
m.g
produces:
5
warning: class variable access from toplevel
NameError: uninitialized class variable ##y in Object
Why can I access ##y from f, but not from g?
Mentioning of toplevel and Object in the warning and the error message is puzzling to me.
#x is printed as 5, so its environment is MC. This excludes the possibility that #x and ##y in the definition of m.g refer to the toplevel environment (Object) instead of MC.
Why did I get the error message?
All variants below work:
def m.g; puts self.class.send(:class_eval, '##y') end
def m.g; puts self.class.class_variable_get(:##y) end
class << m; def g; puts self.class.send(:class_eval, '##y') end end
class << m; puts class_variable_get(:##y) end
But these fail:
def m.g; puts ##y; end
class << m; puts class_eval('##y') end
I would consider this being a ruby parser glitch.
You do not create g in the class MC but in m's singleton class (a.k.a. eigenclass).
This is a class existing specifically for the object m to store the singleton methods that are defined just for m.
I understand class variables should start with ##. Now I have this class:
class C
#v = "my variable"
def self.get_v
#v
end
end
puts C.get_v #returns "my variable"
Is #v still a class variable? But its not having ##?
No, it is a class instance variable, i.e. an instance variable of the class object C.
The difference between the two is that the former is visible inside all the classes of a hierarchy, the latter is visible only inside the class that defines it. A simple example to (I hope) explain:
class A
#a = 0 # class instance variable
##b = 1 # class variable
end
class B < A
#a = 1
##b = 2
end
puts A.a # => 0
# the definition of ##b inside B have altered the value
# inside A. It's not the case for #a.
puts A.b # => 2
No, it's not a class variable. It's a regular instance variable. But it belongs to an instance of Class object. It's important not to confuse the two.
Do the introspection as below, you would get the answer:
class C
#v = "my variable"
def self.get_v
defined? #v
end
end
puts C.get_v #=> instance-variable
class C
#v = "my variable"
def self.get_v
self.instance_variables
end
end
puts C.get_v #=> #v
It means #v is class instance variable.
class C
#v = "my variable"
def self.get_v
self.new.instance_variables
end
end
p C.get_v #=> []
This is because #v is not instance variable of the instances of class C.
Same introspection you can do for the class variables also:
class C
##v = "my variable"
def self.get_v
defined? ##v
end
end
p C.get_v #=> "class variable
In summary I can say ask the question to your object as above, it has the answers for you.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Ruby.Metaprogramming. class_eval
I have this little project, the goal is to create a 'attr_accessor_with_history' method, that will keep a record of every single value assigned to variables created by it. Here's the code :
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name # create the attribute's getter
attr_reader attr_name+"_history" # create bar_history getter
a = %Q{
def initialize
##{attr_name}_history = [nil]
end
def #{attr_name}
##{attr_name}
end
def #{attr_name}=(new_value)
##{attr_name}=new_value
##{attr_name}_history.push(new_value)
end }
puts a
class_eval(a)
end
end
Now, when I test the script for one variable. It works fine. But when I try to create two or more variables (like this) ....
class Foo
attr_accessor_with_history :bar
attr_accessor_with_history :lab
end
a = Foo.new
a.bar = 45
a.bar = 5
a.bar = 'taat'
puts a.bar_history
b = Foo.new
b.lab = 4
b.lab = 145
b.lab = 'tatu'
puts b.lab_history
....Ruby gives out a "no-existing 'push' method for (class_eval) bar_history.push(new_value)". I think that 'initialize' method gets overriden on the second call of attr_accessor_with_history, so the record for the first variable gets destroyed.
I have no idea how to get around this. I already tried calling 'super' . Any clue ?
In your setter method just check if the the history instance variable is already initialized:
def #{attr_name}=(new_value)
##{attr_name}=new_value
##{attr_name}_history ||= [nil]
##{attr_name}_history.push(new_value)
end
You'll need another getter for your history variable that sets your default value if it was not set before:
def #{attr_name}_history
##{attr_name}_history ||= [nil]
end
Then you could remove your initialize method, that was btw vulnerable to be overwritten.
This question already has answers here:
When to use `self.foo` instead of `foo` in Ruby methods
(3 answers)
Closed 9 years ago.
When do you use self.property_name in Ruby?
Use self when calling a class's mutator. For example, this won't work:
class Foo
attr_writer :bar
def do_something
bar = 2
end
end
The problem is that 'bar = 2' creates a local variable named 'bar', rather than calling the method 'bar=' which was created by attr_writer. However, a little self will fix it:
class Foo
attr_writer :bar
def do_something
self.bar = 2
end
end
self.bar = 2 calls the method bar=, as desired.
You may also use self to call a reader with the same name as a local variable:
class Foo
attr_reader :bar
def do_something
bar = 123
puts self.bar
end
end
But it's usually better to avoid giving a local variable the same name as an accessor.
self references the current object. This lends itself to many uses:
calling a method on the current object
class A
def initialize val
#val = val
end
def method1
1 + self.method2()
end
def method2
#val*2
end
end
Here running A.new(1).method1() will return 3. The use of self is optional here - the following code is equivalent:
class A
def initialize val
#val = val
end
def method1
1 + method2()
end
def method2
#val*2
end
end
self is not redundant for this purpose though - operator overloading makes it neccessary:
class A
def initialize val
#val = val
end
def [] x
#val + x
end
def method1 y
[y] #returns an array!
end
def method2 y
self.[y] #executes the [] method
end
end
This shows how self must be used if you want to call the current object's [] method.
referencing attributes
You can generate the methods to read and write to instance variables using attr_accessor and co.
class A
attr_accessor :val
def initialize val
#val = val
end
def increment!
self.val += 1
end
end
Using self is redundant here because you can just reference the variable directly, eg. #val.
Using the previous class, A.new(1).increment! would return 2.
method chaining
You can return self to provide a form of syntactical sugar known as chaining:
class A
attr_reader :val
def initialize val
#val = val
end
def increment!
#val += 1
self
end
end
Here, because we are returning the current object, methods can be chained:
A.new(1).increment!.increment!.increment!.val #returns 4
creating class methods
You can define class methods using self:
class A
def self.double x
x*2
end
def self.quadruple x
self.double(self.double(x))
end
end
This will enable you to call A.double(2) #= 4 and A.quadruple(2) #=8. Note that in a class method, self references that class because the class is the current object.
how the value of self is determined
The current value of self in a particular method is set to the object that that method was called upon. Normally this uses the '.' notation. When you run some_object.some_method(), self is bound to some_object for the duration of some_method, meaning that some_method can use self in one of the ways mentioned above.
Using self is used will reference the current object accessible within a program. Therefore, self.property is used when accessing a variable through a attr_accessor of some sort. In must cases, it can be used in place of #property from within an object.