Looking through the sourcecode of the redis-store RubyGem, I stumbled upon this syntax I hadn't seen before:
class Foo < self
# ...
end
My Google-Fu apparently isn't powerful enough, because I've been able to find nothing that describes what this does.
What I'm guessing this does, is somehow reopening Foo, extending it with itself as superclass, thereby making it possible to override methods that can call the original definition as super. Am I close?
class Foo < Bar
end
Is how you tell Ruby that Foo inherits from Bar.
Within a class definition, self refers to the class itself:
# prints Foo
class Foo
puts self
end
So
class Foo
class Bar < self
end
end
Just says that Bar is nested under Foo and it inherits from it.
The main thing that you seem to be messing is just this: the superclass portion of a Ruby class definition is an arbitrary Ruby expression.
So, something like this is perfectly legal:
class Foo < if rand < 0.5 then Bar else Qux end end
Obviously, this doesn't make sense, but for example, in _why the lucky stiff's brilliant little web micro framework Camping, routes are defined like this:
class Edit < R '/post/(\d+)/edit'
and Migrations are defined like this:
class BlogInitialSchemaCreation < V 1.0
In ActiveRecord, migrations are defined like this:
class CreateProducts < ActiveRecord::Migration[5.0]
All of this simply uses the fact that whatever is to the right of the < in a class definition can by any arbitrary Ruby expression which is evaluated when the class definition is evaluated.
Related
When creating models for the sequel database gem in ruby a syntax like this is used:
class Users < Sequel::Model(:users) # <= what method is getting called here?
# other stuff...
end
Where :users is the name of the table.
I would like to pass an argument to the base class like this when the child class is defined for one of my own classes, but I can't work out how to do it. I don't know what this syntax is called, and I couldn't find any examples of it in my googling. I tried looking at the source for Sequel::Model as well, but its such a big class I couldn't find the relevant section.
Does anyone how what this syntax is and how it works?
It's a common trick to make a normal class/module method call look like a parameterized type.
There is actually a module method Sequel::Model which takes a single argument and returns a class (see the source code).
Have you considered using the #inherited hook of Class?
http://ruby-doc.org/core-2.0.0/Class.html#method-i-inherited
From the docs in the link above:
class Foo
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
class Bar < Foo
end
class Baz < Bar
end
In one of my projects, I need to put two class definitions in one file, and their parent class in another. After I required the parent file, it's still giving uninitialized constant Foo. Checkout the code below. The problem is: How to make it work(run from file2)?
#file1.rb
require_relative './file2.rb'
class Bar < Foo
get('/bar') { 'bar' }
end
class Car < Foo
end
#file2.rb
require_relative './file1.rb'
class Foo
get('/foo') { 'foo' }
end
class Dar < Foo
Bar.new
Car.new
end
Define your parent classes first and your derived ones second. This also makes your code a lot easier to navigate since it's in a predictable order, prerequisites first, specializations later.
Defining it last is impossible, Ruby absolutely needs to know what Foo is first. You can get away with stubbing it in, though:
class Foo
end
class Bar < Foo
end
class Foo
# Re-open class and add functionality
get('...)
end
I'd recommend steering away from this approach whenever possible. It usually ends up accumulating code in both places and nasty duplication errors can occur.
I'm not sure if it is about circular dependency in this problem, but I do figure out a way to avoid the bug. Use another file require both files, and execute from the new file.
#file1.rb
class Bar < Foo
get('/bar') { 'bar' }
end
class Car < Foo
end
#file2.rb
class Foo
get('/foo') { 'foo' }
end
class Dar < Foo
Bar.new
Car.new
end
#file_root.rb
require './file1'
require './file2'
FYI, you probably already figured out I'm using Sinatra from the 'get' method. So the file_root.rb file will actually be the config.ru.
How come in Ruby it's possible to directly have an if statement directly in the class declaration? AKA:
class ApplicationController < ActionController::Base
if foo
bar = "x"
end
end
I know there is some class instance variables, since the Class inherits from Object, is it the same thing?
I just need some clarification about this whole thing :)
Thanks!
How come in Ruby it's possible to directly have an if statement directly in the class declaration
Because it's not a class "declaration", it's a class body, i.e. it's executable code just like a method body, a block body, a loop body or a script body.
The body of a class declaration is code just like everything else in Ruby. That's how you can use methods like attr_accessor, private and include — those are all just methods of the class. It's part of Ruby's philosophy of pervasive object orientation.
Without any problem. Class declaration code normally gets executed, with self = class itself, no problem defining local variables such as foo. Just remember that you are not in the class instance, but in the class itself.
class ApplicationController < ActionController::Base
foo = true
if foo
bar = "x"
end
puts bar
end
Should print "x"
I have two classes A, and B. Class B overrides the foo method of class A. Class B has a bar method where I want to call the foo method of the super class. What is the syntax for such a call?
class A
def foo
"hello"
end
end
class B < A
def foo
super + " world"
end
def bar
# how to call the `foo` method of the super class?
# something similar to
super.foo
end
end
For class methods I can call the methods up the inheritance chain by explicitly prefixing the class name. I wonder if there is a similar idiom for instance methods.
class P
def self.x
"x"
end
end
class Q < P
def self.x
super + " x"
end
def self.y
P.x
end
end
Edit
My use case is general. For a specific case I know I can use alias technique. This is a common feature in Java or C++, so I am curious to know if it is possible to do this without adding extra code.
In Ruby 2.2, you can use Method#super_method now
For example:
class B < A
def foo
super + " world"
end
def bar
method(:foo).super_method.call
end
end
Ref: https://bugs.ruby-lang.org/issues/9781#change-48164 and https://www.ruby-forum.com/topic/5356938
You can do:
def bar
self.class.superclass.instance_method(:foo).bind(self).call
end
In this particular case you can just alias :bar :foo before def foo in class B to rename the old foo to bar, but of course you can alias to any name you like and call it from that. This question has some alternative ways to do it further down the inheritance tree.
You can alias old_foo foo before redefining it to keep the old implementation around under a new name. (Technically it is possible to take a superclass's implementation and bind it to an instance of a subclass, but it's hacky, not at all idiomatic and probably pretty slow in most implementation to boot.)
Based on #Sony's answer.
In case when you want to call the method method on some my_object and it's already overriden somewhere several classes higher (like for the Net::HTTPRequest#method), instead of doing .superclass.superclass.superclass use the:
Object.instance_method(:method).bind(my_object)
Like this:
p Object.instance_method(:method).bind(request).call(:basic_auth).source_location
class << self
attr_accessor :n, :totalX, :totalY
end
The syntax above is used for defining class instance variables. But when I think about what syntax implies, it doesn't make any sense to me, so I'm wondering if this type of syntax is used for any other types of definitions. My point of confusion here is this:
class << self
The append operator normally means "add what's on the right to the object on the left". But in the context of this block, how does that add up to "put the contents of this block into the definition of the class instance rather than the instance"?
For the same reason I'm confused as to why in one context class << self can define class instance variables while in another it seems to create class variables such as here:
class Point
# Instance methods go here
class << self
# Class methods go here
end
end
in Ruby you can reopen existing classes and add methods. That is, you can say:
class Foo
def bob
return "hello from bob"
end
end
these methods get stored somewhere in an internal dictionary (maybe an instance variable) of the Foo-class (which is just an instance of the Class-class and therefore has instance variables)
But the suprising thing is, that you can also add methods to instances of existing objects
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
but Where is this method actually stored?
Turns out Ruby creates a new class behind the scenes (sometimes called singleton class, metaclass or eigenclass) which gets inserted in the inheritance heirarchy between the Foo-class and its instance.
So the inheritance relationship looks like that:
foo < (eigenclass of foo) < Foo < Class
(if you say foo.superclass you will not see the singleton class)
the class << X-syntax is a way to get to this special class, so that you can manipulate it directly. The following code blocks are exactly equivalent:
def foo.bar
return "xy"
end
# is exactly the same as
class << foo
def bar
return "xy"
end
end
So the similarity between class Foo < Bar and class << Foo is not accidental, there is inheritance going on in both.
Think of class << X as "open up the metaclass of X"
The thing to remember in Ruby is that classes themselves are just objects. (Instances of the class Class) so if you say:
class Foo
class << self
def k
return "x"
end
end
end
(self is bound to Foo in this code block) so k is an instance method of the eigenclass of Foo, which makes it a class method for Foo
all this is explained more clearly in the chapter about classes of the Pickaxe (the web version does not contain the diagrams, unfortunately) and _whys Seeing Metaclasses Clearly
Think of the class as containing a dictionary of members including all the accessors and instance variables. When you tell the class to "append" to "itself", you're saying "add these to the dictionary of class members."
I'll grant the notation is a little hinky, though.
it's actually confusing to think of it in terms of an "append" operator. a better way to look at it is that just as class Foo opens up class Foo, that is, it sets 'self' to the class object Foo, creating it if necessary, so class << self opens up the eigenclass of the current 'self' object. note that it is not limited to self - for any object bar, you can say class << bar to open up the eigenclass of that object.
class A
def hello
print "hello world"
end
end
a = A.new
b = A.new
class << a
def goodbye
print "goodbye cruel world"
end
end
a.hello
b.hello
a.goodbye
b.goodbye