Get the name of the class in a Singleton method - ruby

I want a class to return its own name, pluralized, using e.g. "active_support/inflector":
describe "self.resource" do
it "should be databases" do
Database.resource.should equal "databases"
end
end
class Database
def self.resource
self.class.to_s.tableize
end
end
This fails with:
expected #<String:84017460> => "databases"
got #<String:84018030> => "classes"
How can I access the name of the class a singleton method is being called on?

This should work:
class Database
def self.resource
to_s.tableize
end
end
The problem is you call to_s on the class Database belongs to, and it's Class class. You should call to_s on local self instead, which is Database itself. Since self is default receiver of the message, it's okay to leave simply to_s.tableize.

You shouldn't call class method on self. Singleton class already belongs to the class, not the instance.
In your case:
self.to_s.tableize
should work as intended.

Related

What does 'self.class.class_method_name' in the initialize method do?

Do I need to put it in context or can someone give me a general overview? I've tried to do my own googling but am not coming up with enough info.
The part that confuses me is the "class" part. I understand self.class_method_name but not
self.class_method_name.
self refers to the current instance of the class, self.class refers to the class of the instance.
For example:
class Person
def initialize
p self
p self.class
end
end
Person.new
This code would show:
#<Person:0x0000558351934020>
Person the class
The first line is the instance of Person, the second is the class per se.
Normally, when you define a method in class, it's instance of class, it mean you can only call it by object, ex:
class a
define method_x
end
end
, if you want to call method_x, you can only call by:
obj = a.new
obj.method_x
and you can not call : a.method_x
but when you define self.method_x, you can call it by class
class a
define self.method_x
end
end
a.method_x
, you can try as above and see result

Calling Singleton Class Methods Inside Open Singleton Class

I'm trying to understand why I can't call methods defined on the singleton class from within the open class but I can from the actual class.
Can someone explain why the first example fails and the second one doesn't?
class One
class << self
def one; end
one
end
end
NameError (undefined local variable or method 'one' for #<Class:One>)
class Two
class << self
def one; end
end
self.one
end
=> nil
Your example is more confusing than it needs to be. It doesn't require a singleton class at all:
class Foo
def bar; end
bar # NameError
end
Foo.new.bar
Here, we have a class Foo with an instance method bar. A singleton class is still just a class, so this is actually the exact same example as yours.
def without an explicit definee defines an instance method of the closest lexically enclosing class definition, in this case Foo. A message send without an explicit receiver like bar sends the message to self. Inside the class definition body, self is the class itself.
So, def bar defines an instance method in Foo, i.e. a method you can call on instances of Foo.
bar inside the class definition body sends a message to self, which is Foo. Since Foo is not an instance of itself, it does not have a method named bar, ergo, the method call fails.
This works exactly the same with a singleton class, since it is still just a class.
You made the wrong assumption about where the method belongs to, in the first place. The call to the instance method one from inside class context should not succeed. In your first snippet, you try to call method one from the singleton class of the singleton class of One (because it’s called from singleton_class context).
Example with normal class / instance methods to clarify:
class One
def self.one()
puts :class
end
def one
puts :instance
end
one()
end
#⇒ class
So, the expected behavior would be to raise NameError. Now the answer is simple: it raises NameError because this method does not exist.

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

Create property as method on class in Ruby

Rails has these cool properties that seem to be actually methods. For example:
class SomeController < ApplicationController
before_filter :authenticate!
end
What are these actually called and how would you create your own? For example, in one of my models I want to be able to have a dynamic property that selects an internal method for processing some results:
class MyModel < ActiveRecord::Base
active_method :some_class_method
end
How would I set this up so I can set active_method like that and be able to access the active_method symbol as an instance var?
Edit for elaboration:
So give this starter below, I need to figure out how to define "selected_method" so that it defines a accessor or instance variable so "called_selected_method" calls "method_b".
class MyClass
selected_method :method_b
def call_selected_method
end
private
def method_a
puts 'method_a'
end
def method_b
puts 'method_b'
end
end
c = MyClass.new
c.call_selected_method # should put 'method_b'
It's actually just a method call to a method defined on the class. before_filter is provided by a ruby Module, which is mixed in to ActionController.
Creating your own methods similar to before_filter is as easy as:
Define a class method on your Class
Call that method in any concrete implementations of your class.
Some example code:
class MyClass
class << self
def some_function(*args)
# your code here
end
end
some_function "foo"
end
If you wanted to abstract it further, you can put the class method in to a Module, and then include that module in to your class(es).
UPDATE:
In relation to your asking of how to get a call of some_function to set an instance variable on your class, you can't, as class methods cannot affect specific instances of that class.
I have to wonder, though... you're writing a method that will just act as a proxy to your other method, and would be hard-coded in to the class definition. That offers no benefit to you, and would just make your code redundantly complicated.

Mocking the initialize method on a ruby class?

How can I mock the initialize method on a ruby class?
I'm doing some testing and want to mock out the object that is created from a new call.
I tried to write a few things and none of them seemed to get the mock class to return from the new call. It just keeps returning the normal, expected object.
EDIT:
one attempt -
class MockReminderTimingInfoParser < ReminderTimingInfoParser
def new(blank)
ReminderTimingInfoParserForTest.new
end
end
describe ReminderParser do
parser = ReminderParser.new(MockReminderTimingInfoParser)
it "should parse line into a Reminder" do
parser.parse(" doesnt matter \"message\"").should == Reminder.new('message', ReminderTimingInfo.new([DaysOfWeek.new([:sundays])], [1]))
end
end
class ReminderTimingInfoParserForTest
include TimingInfoParser
def parse_section(section); [DaysOfWeek.new([:sundays]), 1] end
def reminder_times_converter(times); times end
end
class MockReminderTimingInfoParser < ReminderTimingInfoParser
def new(blank)
ReminderTimingInfoParserForTest.new
end
end
Here, you are defining a method called new for all instances of the class MockReminderTimingInfoParser. In your question, you mention that you want to hook into instance creation. However, in Ruby, instance creation is not done by instance methods. Obviously, this cannot work, since in order to call an instance method, you'd need to have an instance first!
Instead, instances are created by calling a factory method (commonly called new) on the class.
In other words, in order to create an instance of MockReminderTimingInfoParser, you would call MockReminderTimingInfoParser.new, but you have defined a method MockReminderTimingInfoParser#new. In order to call the method you have defined, you would have to call MockReminderTimingInfoParser.new.new.
You need to define a method on MockReminderTimingInfoParser's singleton class. There's several ways to do that. One way would be just mimicking the way you would call the method:
def MockReminderTimingInfoParser.new(blank)
ReminderTimingInfoParserForTest.new
end
Another would be opening up MockReminderTimingInfoParser's singleton class:
class << MockReminderTimingInfoParser
def new(blank)
ReminderTimingInfoParserForTest.new
end
end
However, in both of these cases, MockReminderTimingInfoParser obviously has to exist first. Given that you need to define the class anyway, here's the most idiomatic way of defining methods on a class's (or module's) singleton class:
class MockReminderTimingInfoParser < ReminderTimingInfoParser
def self.new(blank)
ReminderTimingInfoParserForTest.new
end
end
Could you inherit the class and then supply your own initialize?

Resources