Having a module singleton extending a class - ruby

I have a singleton in my application that gets reused across applications. I want that singleton to get some default methods from my class, but also be able to customize the module/eigenclass. Most of all, I don't want to call up instance on every call the the utility singleton.
Here's an example. Let's say my default class is Universe::Earth. Then I want an Earth module in my application that "extends" that class.
module Universe
class Earth
def self.grow!
#grown = true
end
end
end
module Earth
class < Universe::Earth << self; end
grow!
end
When that's run, grow! is a NoMethodError.
Tried those approaches:
Class.new(Goodluck::Contest) << self
class < Universe::Earth << self; end
extend Universe::Earth
How do I make it work?

Is this the sort of thing you are looking for?
module Universe
class Earth
def self.grow!
#grown = true
end
end
end
module Earth
Universe::Earth.class_eval do
define_method(:instance_howdy) do
puts "instance_howdy!"
end
end
def (Universe::Earth).class_howdy
puts "class_howdy!"
end
end
Universe::Earth.methods(false) #=> [:grow!, :class_howdy]
Universe::Earth.instance_methods(false) #=> [:instance_howdy]
Universe::Earth.new.instance_howdy #=> instance_howdy!
Universe::Earth.class_howdy #=> class_howdy!
[Edit: If you just want to set #grown => true, and retrieve it's value, you merely need:
module Earth
Universe::Earth.grow! #=> true
end
Verify:
Universe::Earth.instance_variable_get("#grown") #=> true
If you wish to also add an accessor for the class instance variable, you could do this:
def add_class_accessor(c, accessor, var)
c.singleton_class.class_eval("#{accessor} :#{var}")
end
Universe::Earth.methods(false)
#=> [:grow!]
module Earth
Universe::Earth.grow! #=> true
add_class_accessor(Universe::Earth, "attr_accessor", "grown")
end
Universe::Earth.methods(false)
#=> [:grow!, :grown, :grown=]
Universe::Earth.grown
#=> true
Universe::Earth.grown = "cat"
#=> "cat"
Universe::Earth.grown
#=> "cat"
Object#singleton_class was added in Ruby 1.9.2. For earlier versions you could do this:
def add_class_accessor(c, accessor, var)
eigenclass = class << c; self; end
eigenclass.class_eval("#{accessor} :#{var}")
end
You might consider putting add_class_accessor in a module to be included as needed. Other methods you might add to the same module might be:
add_instance_method(klass, method, &block)
add_class_method(klass, method, &block)
add_instance_accessor(klass, accessor, var)
:tidE

Related

Insert code into the beginning of each method of a class

How can I dynamically and easily insert code into the beginning of each method of a class and subclasses without actually inserting it manually? I want something like a macros.
class C1
def m1
#i_am = __method__
end
def m2
#i_am = __method__
end
end
This is one of the examples where I want to avoid repetition.
I initially misinterpreted the question (but have left my original answer after the horizontal line below). I believe the following may be what you are looking for.
class C1
[:m1, :m2].each do |m|
define_method(m) do |name|
#i_am = __method__
puts "I'm #{name} from method #{#i_am}"
end
end
end
C1.instance_methods(false)
#=> [:m1, :m2]
c1 = C1.new
#=> #<C1:0x007f94a10c0b60>
c1.m1 "Bob"
# I'm Bob from method m1
c1.m2 "Lucy"
# I'm Lucy from method m2
My original solution follows.
class C1
def add_code_to_beginning(meth)
meth = meth.to_sym
self.class.send(:alias_method, "old_#{meth}".to_sym, meth)
self.class.send(:define_method, meth) do
yield
send("old_#{meth}".to_sym)
end
end
end
Module#alias_method
and Module#define_method are private; hence the need to use send.
c = C1.new
#=> #<C1:0x007ff5e3023650>
C1.instance_methods(false)
#=> [:m1, :m2, :add_code_to_beginning]
c.add_code_to_beginning(:m1) do
puts "hiya"
end
C1.instance_methods(false)
#=> [:m1, :m2, :add_code_to_beginning, :old_m1]
c.m1
# hiya
#=> :m1
You can use a rails like class decorators to that. The piece of code below is rendering a method called before_action defined in the Base class of the ActiveRecord module. The Test class is inherited from the ActiveRecord. The define_method is used if we want to call something explicitly from the Base class.
module ActiveRecord
class Base
def self.before_action(name)
puts "#{name}"
puts "inside before_action of class Base"
define_method(name) do
puts "Base: rendering code from Base class"
end
end
end
end
class Test < ActiveRecord::Base
before_action :hola
def render()
puts "inside render of class Test"
end
end
test = Test.new
test.render
test.hola
It has the output
hola
inside before_action of class Base
inside render of class Test
Base: rendering code from Base class
So, before running the render method it runs the before_action method in the Base class. It can be applied to all other methods in the Test class. This is a way of representing macros in ruby.
Assuming that the function is the same, you could create a module and include it in your classes.
Example:
module MyModule
def test_method
puts "abc"
end
end
class MyClass
include MyModule
def my_method
puts "my method"
end
end
inst = MyClass.new
inst.test_method # => should print "abc"
inst.my_method # => should print "my method"

Ruby class << abcd syntax

I know there have been other questions about the syntax class << self. Still, I did not find those answers clear enough. I have a background in Java/C#, C, so Ruby is kinda strange to me. I read that class << self refers to the singleton class. I find this kinda complex so I would like to understand what does the operator << do in this context and what is possible to put on both ends. I tried to write a simple code to help me understand this syntax (my questions are in the code):
class Self
def Self.selfTest
end
def onSelf
class << Self #I know this might be strange.
self
end
end
def onself
class << self
self
end
end
end
s = Self.new
onSelf = s.onSelf
onself = s.onself
#Here, i wanna know what kind of references are returned.
puts "onSelf responds to onSelf:#{onSelf.respond_to?(:onSelf)}"
puts "onSelf responds to selfTest:#{onSelf.respond_to?(:selfTest)}"
puts "onself responds to onSelf:#{onself.respond_to?(:onSelf)}"
puts "onself responds to selfTest:#{onself.respond_to?(:selfTest)}"
#Output:
#onSelf responds to onSelf:false
#onSelf responds to selfTest:false
#onself responds to onSelf:false
#onself responds to selfTest:true
#So, i conclude that the second one is a reference to a class. What is the first one???????
puts onSelf
puts onself
#Output
#<Class:Self>
#<Class:#<Self:0x007f93640509e8>>
#What does this outputs mean???????
def onSelf.SelfMet
puts 'This is a method defined on base class'
end
def onself.selfMet
puts 'This is a method defined on metaclass'
end
puts "Does Self Class respond to SelfMet? : #{Self.respond_to?(:SelfMet)}"
puts "Does Self Class respond to selfMet? : #{Self.respond_to?(:selfMet)}"
puts "Does Self instance respond to SelfMet? : #{s.respond_to?(:SelfMet)}"
puts "Does Self instance respond to selfMet? : #{s.respond_to?(:selfMet)}"
#Output
#Does Self Class respond to SelfMet? : false
#Does Self Class respond to selfMet? : false
#Does Self instance respond to SelfMet? : false
#Does Self instance respond to selfMet? : false
#Why won't they respond to defined methods????
Thanks
UPDATED:
Thank you all very much. I have read and tested a lot, so will leave a few considerations. I leave this for future reference and as so, i hope the Ruby experts can correct me if i am wrong. I realised that class << Self refers to the Self singleton class. So, the idiomatic class << abcd, starts the abcd singleton class context. I realised also that the hierarchy of a class singleton class is different from an object singleton class. The hierarchy of a class singleton class follows all singleton classes on a hierarchy. In this case:
singleton Self->singleton Object->Singleton basicobject ->class->module->object->kernel->basicObject
The object singleton class lies in a different kind of hierarchy:
Object singleton->Self->Object->kernel->basicObject
This explains this outputs.
In Ruby, every object has a singleton class. This singleton class has only one instance: the object it belongs to.
Since the singleton class has only ever one instance, and every object has its own singleton class, methods that are defined in this class can only be called on that specific object. Those methods are typically called singleton methods, although that is misleading: there's nothing special about those methods, they are just normal standard instance methods.
Here's an example:
foo, bar, baz = Object.new, Object.new, Object.new
class << foo; def quux; :foo end end
class << bar; def quux; :bar end end
foo.quux # => :foo
bar.quux # => :bar
baz.quux # NoMethodError
Classes are just objects like any other object. So, just like any other object, they have singleton classes. Methods defined in the singleton class of an object that happens to be a class are typically called class methods, although again, there's nothing special about them, they are just singleton methods of an object which happens to be a class, which in turn means they are just regular instance methods of a singleton class which belongs to an object which happens to be a class.
So, if you compare this to something like Java, you can see a duality: in Java, there is only one kind of class but there are two kinds of methods (instance and static). In Ruby, there is only one kind of method (instance) but it can be defined in different kinds of classes (regular and singleton).
I find this kinda complex so I would like to understand what does the operator << do in this context
That's just the syntax for opening up a singleton class as opposed to opening up a class.
and what is possible to put on both ends.
Well, on the left has to be the keyword class and on the right any expression that returns an object.
Perhaps this will help. If you add the following statements you will get the indicated results:
puts onSelf #=> #<Class:Self>
puts Self.singleton_class #=> #<Class:Self>
puts onSelf == Self.singleton_class #=> true
puts onself #=> #<Class:#<Self:0x007fe6330aab10>>
puts s.singleton_class #=> #<Class:#<Self:0x007fe6330aab10>>
puts onself == s.singleton_class #=> true
I see no point in defining a method whose receiver is a metaclass, but that is what you have done:
puts onSelf.SelfMet
#=> This is a method defined on Self's metaclass
puts onself.selfMet
#=> This is a method defined on s's metaclass
Obviously, onSelf (Self.singleton_class) responds to SelfMet (but not to selfmet), and onself (s.singleton_class) responds to selfmet (but not to Selfmet).
For Self to respond to SelfMet, the latter would have to be defined def Self.SelfMet... or def self.SelfMet.. (or one of a few other ways), but it is not.
Similiarly, for s to respond to selfMet, the latter would have to be defined as a normal instance method def selfMet... (in which case all other instances of Self would also respond to it) or defined in s's singleton class: def s.selfMet... (in which case other instances of Self would not respond to it).
In sum, the class Self responds to its singleton methods, as does the instance s respond to its singleton methods; the singleton classes of Self and s do not respond to those respective singleton methods.
The following may help you understand what's going on here. Each p self followed by #=> displays what follows #=> when the statement is executed by Ruby. Notice how the various statements, such as class Dog, class << self and others are used to change the value of self to what we want.
p self is your best friend when metaprogramming.
p self #=> main
class Dog
p self #=> Dog
def self.woof1
p self
end
def Dog.woof2
p self
end
p self #=> Dog
class << self
p self #=> #<Class:Dog>
p Dog.singleton_class #=> #<Class:Dog>
def woof3
p self
end
end
p self #=> Dog
def woof4
p self
end
end
p self #=> main
def Dog.woof5
p self
end
Dog.instance_eval do
p self #=> Dog
def woof6
p self
end
end
dog = Dog.new #=> #<Dog:0x007fe17b08cf00>
def dog.woof7
p self
end
dog.instance_eval do
p self #=> #<Dog:0x007fe17b08cf00>
def woof8
p self
end
end
p self #=> main
Dog.woof1 #=> Dog
Dog.woof2 #=> Dog
Dog.woof3 #=> Dog
Dog.woof5 #=> Dog
Dog.woof6 #=> Dog
dog.woof4 #=> #<Dog:0x007fe17b08cf00>
dog.woof7 #=> #<Dog:0x007fe17b08cf00>
dog.woof8 #=> #<Dog:0x007fe17b08cf00>
puppy = Dog.new #=> #<Dog:0x007fe17ba93a08>
puppy.woof4 #=> #<Dog:0x007fe17ba93a08>
puppy.woof7 #=> undefined method `woof7' for #<Dog:0x007fe5fb3e1d48>
puppy.woof8 #=> undefined method `woof8' for #<Dog:0x007fe5fb3e1d48>
It takes awhile to sort everything out. Even then, most of us need a refresher from time-to-time. Here's an excellent article on the subject. Also, look at some of the references in the comments there, especially Dave Thomas' presentation.
Lastly, have a look at Ruby's naming convention.

Creating class methods from a module

Given the simple example here:
class Base
#tag = nil
def self.tag(v = nil)
return #tag unless v
#tag = v
end
end
class A < Base
tag :A
end
class B < Base
tag :B
end
class C < Base; end
puts "A: #{A.tag}"
puts "B: #{B.tag}"
puts "A: #{A.tag}"
puts "C: #{C.tag}"
which works as expected
A: A
B: B
A: A
C:
I want to create a module that base will extend to give the same functionality but with all the tag information specified by the class. Eg.
module Tester
def add_ident(v); ....; end
end
class Base
extend Tester
add_ident :tag
end
I've found i can do it with a straight eval, so:
def add_ident(v)
v = v.to_s
eval "def self.#{v}(t = nil); return ##{v} unless t; ##{v} = t; end"
end
but i really dislike using eval string in any language.
Is there a way that i can get this functionality without using eval? I've gone through every combination of define_method and instance_variable_get/set i can think of and i can't get it to work.
Ruby 1.9 without Rails.
You want to define a dynamic method on the singleton class of the class you're extending. The singleton class of a class can be accessed with expression like this: class << self; self end. To open the scope of a class's class, you can use class_eval. Putting all this together, you can write:
module Identification
def add_identifier(identifier)
(class << self; self end).class_eval do
define_method(identifier) do |*args|
value = args.first
if value
instance_variable_set("##{identifier}", value)
else
instance_variable_get("##{identifier}")
end
end
end
end
end
class A
extend Identification
add_identifier :tag
end
If you're using recent versions of Ruby, this approach can be replaced with Module#define_singleton_method:
module Identification
def add_identifier(identifier)
define_singleton_method(identifier) do |value = nil|
if value
instance_variable_set("##{identifier}", value)
else
instance_variable_get("##{identifier}")
end
end
end
end
I don't believe you want to use self.class.send(:define_method), as shown in another answer here; this has the unintended side effect of adding the dynamic method to all child classes of self.class, which in the case of A in my example is Class.
module Tester
def add_ident(var)
self.class.send(:define_method, var) do |val=nil|
return instance_variable_get("##{var}") unless val
instance_variable_set "##{var}", val
end
end
end
My favourite ruby book Metaprogramming Ruby solved these questions like the following way:
module AddIdent
def self.included(base)
base.extend ClassMethods # hook method
end
module ClassMethods
def add_ident(tag)
define_method "#{tag}=" do |value=nil|
instance_variable_set("##{tag}", value)
end
define_method tag do
instance_variable_get "##{tag}"
end
end
end
end
# And use it like this
class Base
include AddIdent
add_ident :tag
end
Bah isn't it always the way that once you get frustrated enough to post you then find the answer :)
The trick seems to be in (class << self; self; end) to give you the class instance without destroying the local scope. Referencing: How do I use define_method to create class methods?
def add_ident(v)
var_name = ('#' + v.to_s).to_sym
(class << self; self; end).send(:define_method, v) do |t = nil|
return instance_variable_get(var_name) unless t
instance_variable_set(var_name, t)
end
end
I'll accept better answers if them come along though.

Ruby Singleton methods for class and objects

I am learning Ruby Singletons and i found some ways to define and get list of Class and Object singleton methods.
Class Singleton Methods
Ways to define class singleton methods:
class MyClass
def MyClass.first_sing_method
'first'
end
def self.second_sing_method
'second'
end
class << self
def third_sing_method
'third'
end
end
class << MyClass
def fourth_sing_method
'fourth'
end
end
end
def MyClass.fifth_sing_method
'fifth'
end
MyClass.define_singleton_method(:sixth_sing_method) do
'sixth'
end
Ways to get list of class singletons methods:
#get singleton methods list for class and it's ancestors
MyClass.singleton_methods
#get singleton methods list for current class only
MyClass.methods(false)
Object Singleton Methods
Ways to define object singleton methods
class MyClass
end
obj = MyClass.new
class << obj
def first_sing_method
'first'
end
end
def obj.second_sing_method
'second'
end
obj.define_singleton_method(:third_sing_method) do
'third'
end
Way to get list of object singleton methods
#get singleton methods list for object and it's ancestors
obj.singleton_methods
#get singleton methods list for current object only
obj.methods(false)
Are there other ways to do this?
First of all, the way to list singleton methods is with singleton_methods. The methods method returns a list of the names of public and protected methods of the object. Also, it is defined in the Object class. Try extending an instance. It is one of the most elegant ways, as it supports code reuse and seems to me very object-oriented:
class Foo
def bar
puts "Hi"
end
end
module Bar
def foo
puts "Bye"
end
end
f = Foo.new
f.bar
#=> hi
f.extend Bar
f.foo
#=> bye
f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected
f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly
g = Foo.new
g.foo
#=> NoMethodError
Edit: In the comment you asked why methods(false) returns nothing in this case. After reading through the C code it seems that:
methods returns all the methods available for the object (also the ones in included modules)
singleton_methods returns all the singleton methods for the object (also the ones in included modules) (documentation)
singleton_methods(false) returns all the singleton methods for the object, but not those declared in included modules
methods(false) supposedly returns the singleton methods by calling singleton_methods, but it also passes the parameter false to it; whether this is a bug or a feature - I do not know
Hopefully, this clarifies the issue a little. Bottom line: call singleton_methods, seems more reliable.
Some more ways:
Class singleton methods
class << MyClass
define_method :sixth_sing_method do
puts "sixth"
end
end
class MyClass
class << self
define_method :fourth_sing_method do
puts "seventh"
end
end
end
Object singleton methods
class << obj
define_method :fourth_sing_method do
puts "fourth"
end
end
Next, you can use define_method and define_singleton_method in combination with send, e.g.
obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }
and all possible combinations thereof. To use define_method, you need to capture the singleton class first as in this (the same works for class objects, too)
singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }
Another ways is using class_eval on the singleton class objects:
singleton_class.class_eval do
def nth_sing_method
puts "nth"
end
end
And then you once again may combine send with class_eval...
There are myriads of ways, I guess :)
Object singleton methods
instance_eval
class A
end
a = A.new
a.instance_eval do
def v
"asd"
end
end
a.singleton_methods
=> [:z, :v]

Best Way to Abstract Initializing Attributes

What's the best way to abstract this pattern:
class MyClass
attr_accessor :foo, :bar
def initialize(foo, bar)
#foo, #bar = foo, bar
end
end
A good solution should take superclasses into consideration and be able to handle still being able to have an initializer to do more things. Extra points for not sacrificing performance in your solution.
A solution to that problem already (partially) exists, but if you want a more declarative approach in your classes then the following should work.
class Class
def initialize_with(*attrs, &block)
attrs.each do |attr|
attr_accessor attr
end
(class << self; self; end).send :define_method, :new do |*args|
obj = allocate
init_args, surplus_args = args[0...attrs.size], args[attrs.size..-1]
attrs.zip(init_args) do |attr, arg|
obj.instance_variable_set "##{attr}", arg
end
obj.send :initialize, *surplus_args
obj
end
end
end
You can now do:
class MyClass < ParentClass
initialize_with :foo, :bar
def initialize(baz)
#initialized = true
super(baz) # pass any arguments to initializer of superclass
end
end
my_obj = MyClass.new "foo", "bar", "baz"
my_obj.foo #=> "foo"
my_obj.bar #=> "bar"
my_obj.instance_variable_get(:#initialized) #=> true
Some characteristics of this solution:
Specify constructor attributes with initialize_with
Optionally use initialize to do custom initialization
Possible to call super in initialize
Arguments to initialize are the arguments that were not consumed by attributes specified with initialize_with
Easily extracted into a Module
Constructor attributes specified with initialize_with are inherited, but defining a new set on a child class will remove the parent attributes
Dynamic solution probably has performance hit
If you want to create a solution with absolute minimal performance overhead, it would be not that difficult to refactor most of the functionality into a string which can be evaled when the initializer is defined. I have not benchmarked what the difference would be.
Note: I found that hacking new works better than hacking initialize. If you define initialize with metaprogramming, you'd probably get a scenario where you pass a block to initialize_with as a substitute initializer, and it's not possible to use super in a block.
This is the first solution that comes to my mind. There's one big downside in my module: you must define the class initialize method before including the module or it won't work.
There's probably a better solution for that problem, but this is what I wrote in less than a couple of minutes.
Also, I didn't keep performances too much into consideration. You probably can find a much better solution than me, especially talking about performances. ;)
#!/usr/bin/env ruby -wKU
require 'rubygems'
require 'activesupport'
module Initializable
def self.included(base)
base.class_eval do
extend ClassMethods
include InstanceMethods
alias_method_chain :initialize, :attributes
class_inheritable_array :attr_initializable
end
end
module ClassMethods
def attr_initialized(*attrs)
attrs.flatten.each do |attr|
attr_accessor attr
end
self.attr_initializable = attrs.flatten
end
end
module InstanceMethods
def initialize_with_attributes(*args)
values = args.dup
self.attr_initializable.each do |attr|
self.send(:"#{attr}=", values.shift)
end
initialize_without_attributes(values)
end
end
end
class MyClass1
attr_accessor :foo, :bar
def initialize(foo, bar)
#foo, #bar = foo, bar
end
end
class MyClass2
def initialize(*args)
end
include Initializable
attr_initialized :foo, :bar
end
if $0 == __FILE__
require 'test/unit'
class InitializableTest < Test::Unit::TestCase
def test_equality
assert_equal MyClass1.new("foo1", "bar1").foo, MyClass2.new("foo1", "bar1").foo
assert_equal MyClass1.new("foo1", "bar1").bar, MyClass2.new("foo1", "bar1").bar
end
end
end
class MyClass < Struct.new(:foo, :bar)
end
I know this is an old question with perfectly acceptable answers but I wanted to post my solution as it takes advantage of Module#prepend (new in Ruby 2.2) and the fact that modules are also classes for very simple solution. First the module to make the magic:
class InitializeWith < Module
def initialize *attrs
super() do
define_method :initialize do |*args|
attrs.each { |attr| instance_variable_set "##{attr}", args.shift }
super *args
end
end
end
end
Now let's use our fancy module:
class MyClass
prepend InitializeWith.new :foo, :bar
end
Note that I left our the attr_accessible stuff as I consider that a separate concern although it would be trivial to support. Now I can create an instance with:
MyClass.new 'baz', 'boo'
I can still define an initialize for custom initialization. If my custom initialize take an argument those will be any extra arguments provided to the new instance. So:
class MyClass
prepend InitializeWith.new :foo, :bar
def initialize extra
puts extra
end
end
MyClass.new 'baz', 'boo', 'dog'
In the above example #foo='baz', #bar='boo' and it will print dog.
What I also like about this solution is that it doesn't pollute the global namespace with a DSL. Objects that want this functionality can prepend. Everybody else is untouched.
This module allows an attrs hash as an option to new(). You can include the module in a class with inheritance, and the constructor still works.
I like this better than a list of attr values as parameters, because, particularly with inherited attrs, I wouldn't like trying to remember which param was which.
module Attrize
def initialize(*args)
arg = args.select{|a| a.is_a?(Hash) && a[:attrs]}
if arg
arg[0][:attrs].each do |key, value|
self.class.class_eval{attr_accessor(key)} unless respond_to?(key)
send(key.to_s + '=', value)
end
args.delete(arg[0])
end
(args == []) ? super : super(*args)
end
end
class Hue
def initialize(transparent)
puts "I'm transparent" if transparent
end
end
class Color < Hue
include Attrize
def initialize(color, *args)
p color
super(*args)
p "My style is " + #style if #style
end
end
And you can do this:
irb(main):001:0> require 'attrize'
=> true
irb(main):002:0> c = Color.new("blue", false)
"blue"
=> #<Color:0x201df4>
irb(main):003:0> c = Color.new("blue", true, :attrs => {:style => 'electric'})
"blue"
I'm transparent
"My style is electric"

Resources