Parent class definition with arguments - ruby

I was browsing the camping documentation, and I ran into this example for defining a controller:
class Digits < R '/nuts/(\d+)'
def get(number)
"You got here by: /nuts/#{number}"
end
end
It looks like what this class definition is doing is that it's passing a string argument to the R superclass. However, I looked through the camping codebase and I didn't see R defined as a class anymore. It was defined as a method like this:
def R(c,*g)
p,h=/\(.+?\)/,g.grep(Hash)
g-=h
raise "bad route" if !u = c.urls.find{|x|
break x if x.scan(p).size == g.size &&
/^#{x}\/?$/ =~ (x=g.inject(x){|x,a|
x.sub p,U.escape((a.to_param rescue a))}.gsub(/\\(.)/){$1})
}
h.any?? u+"?"+U.build_query(h[0]) : u
end
and the method to actually handle the route:
def /(p); p[0] == ?/ ? #root + p : p end
I don't understand exactly how this works, because when I tried to make a class and define a method as a superclass, like this:
def doSomething(boo)
puts boo
end
class Someclass < doSomething 'boo'
end
I get this error:
(eval):60: (eval):60: superclass must be a Class (NilClass given) (TypeError)
Can someone point me to where in the ruby documentation this feature (using a method as a superclass) is covered? I don't know what to call this feature, so my googling efforts couldn't really find me anything.

You'll have to return a class from your method:
def doSomething(boo)
Class.new { define_method(:boo) { boo } }
end
class SomeClass < doSomething 'boo'
end
SomeClass.new.boo # => 'boo'
You're also looking at the wrong method. Camping has a class method on Controllers called R (that's the one used when defining controllers) and an instance method on Base called R (for generating routes). This is the actual definition: https://github.com/camping/camping/blob/ae5a9fabfbd02ba2361ad8831c15d723d3740b7e/lib/camping-unabridged.rb#L551

Related

How to output the Ruby class name wrapped around Singleton method

My goal is:
class Bermuda
class << self
def grass
puts self.superclass.name
end
end
end
# my goal is that this expression
Bermuda.grass
# will output a string of the class name it resides in
=> "Bermuda"
I cannot display the name of the class that holds a singleton method. I have tried a number of different stabs and standard library searches but haven't found an answer.
This is partially pointless because you would not need a class method to display the information that you would need in the first place to call that method. I'm curious if it's possible or I'm completely missing the scope.
Just call name on self
class Bermuda
class << self
def grass
puts self.name
end
end
end
This sort of an implementation isn't recommended since all you have to do to get the class name is call Bermuda.name
Please see the answer given below by #MatthewCliatt for more info.
It's as simple as:
self.class.name
But, the catch is that this isn't for class methods, it's for instance methods.
That means you don't declare it with self. This was your code:
class Bermuda
class << self
def grass
puts self.superclass.name
end
end
end
And that will make the grass method a class method. You would have to call it like Bermuda.grass.
But, if you can call class methods like the one above, you could just as easily write: Bermuda.name.
I'm assuming you can't call class methods, probably because you're working with an instance. So you want to write this method as such:
class Bermuda
def grass
puts self.class.name
end
end
You say you're creating a singleton method, but I don't think your method is a singleton method in the usual sense (i.e. a method on an object that is an instance of a class, but not itself a class).
I believe the class << self notation you use merely results in a class method being defined, identical to:
def self.grass
puts name
end
In irb:
2.3.0 :003 > class Bermuda; def self.grass; puts name; end; end
=> :grass
2.3.0 :004 > Bermuda.grass
Bermuda

Accessing the name of an anonymous class in superclass' self.inherited

I would like to access a class' name in its superclass MySuperclass' self.inherited method. It works fine for concrete classes as defined by class Foo < MySuperclass; end but it fails when using anonymous classes. I tend to avoid creating (class-)constants in tests; I would like it to work with anonymous classes.
Given the following code:
class MySuperclass
def self.inherited(subclass)
super
# work with subclass' name
end
end
klass = Class.new(MySuperclass) do
def self.name
'FooBar'
end
end
klass#name will still be nil when MySuperclass.inherited is called as that will be before Class.new yields to its block and defines its methods.
I understand a class gets its name when it's assigned to a constant, but is there a way to set Class#name "early" without creating a constant?
I prepared a more verbose code example with failing tests to illustrate what's expected.
Probably #yield has taken place after the ::inherited is called, I saw the similar behaviour with class definition. However, you can avoid it by using ::klass singleton method instead of ::inherited callback.
def self.klass
#klass ||= (self.name || self.to_s).gsub(/Builder\z/, '')
end
I am trying to understand the benefit of being able to refer to an anonymous class by a name you have assigned to it after it has been created. I thought I might be able to move the conversation along by providing some code that you could look at and then tell us what you'd like to do differently:
class MySuperclass
def self.inherited(subclass)
# Create a class method for the subclass
subclass.instance_eval do
def sub_class() puts "sub_class here" end
end
# Create an instance method for the subclass
subclass.class_eval do
def sub_instance() puts "sub_instance here" end
end
end
end
klass = Class.new(MySuperclass) do
def self.name=(name)
#name = Object.const_set(name, self)
end
def self.name
#name
end
end
klass.sub_class #=> "sub_class here"
klass.new.sub_instance #=> "sub_instance here"
klass.name = 'Fido' #=> "Fido"
kn = klass.name #=> Fido
kn.sub_class #=> "sub_class here"
kn.new.sub_instance #=> "sub_instance here"
klass.name = 'Woof' #=> "Woof"
kn = klass.name #=> Fido (cannot change)
There is no way in pure Ruby to set a class name without assigning it to a constant.
If you're using MRI and want to write yourself a very small C extension, it would look something like this:
VALUE
force_class_name (VALUE klass, VALUE symbol_name)
{
rb_name_class(klass, SYM2ID(symbol_name));
return klass;
}
void
Init_my_extension ()
{
rb_define_method(rb_cClass, "force_class_name", force_class_name, 1);
}
This is a very heavy approach to the problem. Even if it works it won't be guaranteed to work across various versions of ruby, since it relies on the non-API C function rb_name_class. I'm also not sure what the behavior will be once Ruby gets around to running its own class-naming hooks afterward.
The code snippet for your use case would look like this:
require 'my_extension'
class MySuperclass
def self.inherited(subclass)
super
subclass.force_class_name(:FooBar)
# work with subclass' name
end
end

how rails delegate method works?

After reading the answer by jvans below and looking at the source code a few more time I get it now :). And in case anyone is still wondering how exactly rails delegates works. All rails is doing is creating a new method with (module_eval) in the file/class that you ran the delegate method from.
So for example:
class A
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
At the point when delegate is called rails will create a hello method with (*args, &block) in class A (technically in the file that class A is written in) and in that method all rails do is uses the ":to" value(which should be an object or a Class that is already defined within the class A) and assign it to a local variable _, then just calls the method on that object or Class passing in the params.
So in order for delegate to work without raising an exception... with our previous example. An instance of A must already have a instance variable referencing to an instance of class B.
class A
attr_accessor :b
def b
#b ||= B.new
end
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
This is not a question on "how to use the delegate method in rails", which I already know. I'm wondering how exactly "delegate" delegates methods :D. In Rails 4 source code delegate is defined in the core Ruby Module class, which makes it available as a class method in all rails app.
Actually my first question would be how is Ruby's Module class included? I mean every Ruby class has ancestors of > Object > Kernel > BasicObject and any module in ruby has the same ancestors. So how exactly how does ruby add methods to all ruby class/modules when someone reopens the Module class?
My second question is.. I understand that the delegate method in rails uses module_eval do the actual delegation but I don't really understand how module_eval works.
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
end
prefix, allow_nil = options.values_at(:prefix, :allow_nil)
if prefix == true && to =~ /^[^a-z_]/
raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
end
method_prefix = \
if prefix
"#{prefix == true ? to : prefix}_"
else
''
end
file, line = caller.first.split(':', 2)
line = line.to_i
to = to.to_s
to = 'self.class' if to == 'class'
methods.each do |method|
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
definition = (method =~ /[^\]]=$/) ? 'arg' : '*args, &block'
# The following generated methods call the target exactly once, storing
# the returned value in a dummy variable.
#
# Reason is twofold: On one hand doing less calls is in general better.
# On the other hand it could be that the target has side-effects,
# whereas conceptually, from the user point of view, the delegator should
# be doing one call.
if allow_nil
module_eval(<<-EOS, file, line - 3)
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
_ = #{to} # _ = client
if !_.nil? || nil.respond_to?(:#{method}) # if !_.nil? || nil.respond_to?(:name)
_.#{method}(#{definition}) # _.name(*args, &block)
end # end
end # end
EOS
else
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
module_eval(<<-EOS, file, line - 2)
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
_ = #{to} # _ = client
_.#{method}(#{definition}) # _.name(*args, &block)
rescue NoMethodError => e # rescue NoMethodError => e
if _.nil? && e.name == :#{method} # if _.nil? && e.name == :name
#{exception} # # add helpful message to the exception
else # else
raise # raise
end # end
end # end
EOS
end
end
end
Ruby isn't reopening the module class here. In ruby the class Module and the class Class are almost identical.
Class.instance_methods - Module.instance_methods #=> [:allocate, :new, :superclass]
The main difference is that you can't 'new' a module.
Module's are ruby's version of multiple inheritance so when you do:
module A
end
module B
end
class C
include A
include B
end
behind the scenes ruby is actually creating something called an anonymous class. so the above is actually equivalent to:
class A
end
class B < A
end
class C < B
end
module_eval here is a little deceptive. Nothing from the code you're looking at is dealing with modules. class_eval and module_eval are the same thing and they just reopen the class that they're called on so if you want to add methods to a class C you can do:
C.class_eval do
def my_new_method
end
end
or
C.module_eval do
def my_new_method
end
end
both of which are equivalent to manually reopening the class and defining the method
class C
end
class C
def my_new_method
end
end
so when they're calling module_eval in the source above, they're just reopening the current class it's being called it and dynamically defining the methods that you're delegating
I think this will answer your question better:
Class.ancestors #=> [Module, Object, PP::ObjectMixin, Kernel, BasicObject]
since everything in ruby is a class, the method lookup chain will go through all of these objects until it finds what it's looking for. By reoping module you add behavior to everything. The ancestor chain here is a little deceptive, since BasicObject.class #=> Class and Module is in Class's lookup hierarchy, even BasicObject inherits behavior from repening module. The advantage of reopening Module here over Class is that you can now call this method from within a module as well as within a class! Very cool, learned something here myself.
After reading the answer by jvans below and looking at the source code a few more time I get it now :). And in case anyone is still wondering how exactly rails delegates works. All rails is doing is creating a new method with (module_eval) in the file/class that you ran the delegate method from.
So for example:
class A
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
At the point when delegate is called rails will create a hello method with (*args, &block) in class A (technically in the file that class A is written in) and in that method all rails do is uses the ":to" value(which should be an object or a Class that is already defined within the class A) and assign it to a local variable _, then just calls the method on that object or Class passing in the params.
So in order for delegate to work without raising an exception... with our previous example. An instance of A must already have a instance variable referencing to an instance of class B.
class A
attr_accessor :b
def b
#b ||= B.new
end
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end

What's the difference between self.generate and Invoice.generate?

class Invoice
def Invoice.generate(order_id, charge_amount, credited_amount = 0.0)
Invoice.new(:order_id => order_id, :amount => charge_amount, :invoice_type => PURCHASE, :credited_amount => credited_amount)
end
end
Why would you create Invoice.generate inside Invoice class rather than self.generate?
self.generate is easier to work with, whereas Invoice.generate is arguably more explicit. Other than that, there's no difference between the two.
Explanation
You can define a method on any instance using this form
def receiver.method(args)
end
Check this out
class Foo
end
def Foo.bar
"bar"
end
Foo.bar # => "bar"
And yes, I mean any instance. It's absolutely possible that one instance has some method while another doesn't
f = Foo.new
def f.quux
'quux'
end
f2 = Foo.new
f.quux # => "quux"
f2.quux # => # ~> -:20:in `<main>': undefined method `quux' for #<Foo:0x007fe4e904a6c0> (NoMethodError)
A reminder: inside of class definition (but outside of method definitions) self points to that class.
class Foo
# self is Foo
end
So, armed with this knowledge, the difference between self.generate and Invoice.generate should be obvious.
Under normal circumstances, it would practically have no difference from def self.generate.
The only edge case I can think of is if you have a nested class with the same name, then the explicit version would apply only to the nested class.
class A
def self.x
name
end
def A.y
name
end
class A
# nested class A::A
end
def self.p
name
end
def A.q
name
end
end
> A.x # => "A"
> A.y # => "A"
> A.p # => "A"
> A.q # => NoMethodError: undefined method `q' for A:Class
> A::A.q # => "A::A"
As you see, after a nested class with the same name is defined, subsequent explicit class method definitions made with the class name refer to the nested class, but explicit definitions made beforehand refer to the original.
Implicit definitions made with self always refer to the base class.
You have 2 ways for defining a class method.
1) You can use the name of the class directly
class Test #Test is now an instance of a built-in class named Class
def Test.class_method
"I'm a class method."
end
end
2) You can use the self variable, which is always pointing to the current object
class Test
def self.class_method
"I'm a class method."
end
end
Once you understand that classes are objects, this use of the self variable to define a class method finally makes sense.
The value of self
Not too surprinsingly, when you are inside a class method, the value of self refers to the object that holds the class structure (the instance of class Class). This means that :
class Test
def self.class_method
self.x
end
end
is equivalent to :
class Test
def self.class_method
Test.x
end
end
When you are inside an instance method, the value of self still refers to the current object. This time however, the current object is an instance of class Test, not an instance of class Class.
More info. : http://www.jimmycuadra.com/posts/self-in-ruby

Why does this Ruby method need to be a class level method?

Here's a classic fizzbuzz in Ruby:
class PrimeChecker
def print_em
1.upto 100 do |fizzbuzz|
if (fizzbuzz % 2) == 0 && (fizzbuzz % 5) == 0
puts "fizzbuzz: " + fizzbuzz.to_s
elsif (fizzbuzz % 5) == 0
puts "fizz: "+fizzbuzz.to_s
elsif (fizzbuzz % 2) == 0
puts 'buzz: ' + fizzbuzz.to_s
else
puts "-" + fizzbuzz.to_s
end
end
end
end
PrimeChecker.print_em
When I execute this, I get this error:
undefined method 'print_em'.
I change the method to self.print_em and it works. Does this mean it's a class method (I think so)? Was the method "not found" before because I can only call such methods in a class on actual instances of the object? If I wanted it to be a instance method what is the syntax for that? I'm trying to understand Ruby, classes and methods better.
Class methods are just that: called on the class. Whereas instance methods are called on an instance of that class. An example is more useful:
class Foo
def self.bar
"This is a class method!"
end
def bar
"This is an instance method!"
end
end
Foo.bar # => "This is a class method!"
foo = Foo.new # This creates "foo" to be a new instance of Foo
foo.bar # => "This is an instance method!"
Note that "class methods" in Ruby are actually methods on the class object's singleton. This is a rather difficult concept to explain, and you can read more about it if you'd like.
It's not a class method as written; you need to run it with an instance of PrimeChecker:
pc = PrimeChecker.new
pc.print_em
Using self. turns it into a class method, runnable with the syntax you show.
It doesn't need to be a class method, it's just that that's how you're trying to execute it.
Q: When I run ruby.rb I get undefined method 'print_em'. I change the method to self.print_em and it works. Does this mean it's a class method (I think so).
A: Yes. class Bar; ... def self.foo defines a class method foo for class Bar.
Q: Was the method "not found" before because I can only call such methods in a class on actual instances of the object?
A: You were first defining it as an instance method. In that case, it is only available to instances of the class.
Q: If I wanted it to be a instance method what is the syntax for that?
A: The way you had it originally: class Bar; def foo defines instance method foo for class Bar
Yes, you are completely correct. Currently, the way you define it, you can evaluate the method with:
PrimeChecker.new.print_em
The reason def self.my_awesome_method defines it on the class side is because the stuff inside
class MyAwesomeClass
end
is being executed in the context of MyAwesomeClass. It's all Ruby code, as you can see! This enables you to do things like this:
class MyAwesomeClass
puts "Hello from innards of #{self}!" #=> Hello from the innards of MyAwesomeClass!
end
Method definitions will also only work if you call them after the definition location, for example:
class MyAwesomeClass
my_awesome_method # produces a nasty error
def self.my_awesome_method
puts "Hello world"
end
my_awesome_method # executes just fine
end
Hope this clears some things up.

Resources