Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby, inheritance, self.inherited and instance_methods()

I'm working on rails app (3.2.11), and i'm implementing services as singleton, using the Ruby Library's one. I was trying to avoid calling :instance method every time I need it (SomethingService.instance.get(some_id)), solving my problem like this

class SomethingService
    include Singleton
    class << self
        extend Forwardable
        def_delegators :instance, *ShoppingListService.instance_methods(false)
    end
end

So this solution was working perfectly fine but i've got a lot of services, and i don't want to add this code to all my classes! Instead i was trying to put in in a super class like this :

class ServiceBase
    include Singleton
    def self.inherited(subclass)
        super(subclass) # needed because inherited is override by Singleton

        class << subclass
            extend Forwardable
            def_delegators :instance, *self.instance_methods(false)
        end
    end

end

But this is giving me a stack level too deep error... Any ideas guys?

like image 552
dvxam Avatar asked Feb 21 '26 17:02

dvxam


1 Answers

It's probably a better idea to use method_missing here. def_delegators is executed when the class is evaluated, and may happen before your methods are even defined, simply because you are inheriting from that base class.

You could try something like this instead, which forwards any undefined message onto the instance:

class ServiceBase
  class << self
    def method_missing(name, *args, &block)
      instance.send(name, *args, &block)
    end
  end
end

It may look like a bit of a scattershot approach when compared to delegation. You could do a check to see if the instance method exists first, but I don't think that's necessary - you're simply transferring the undefined method handling to the instance rather than the class.

One final point/question - can you elaborate on what benefit you get from the Singleton class in the first place?

like image 119
Zach Kemp Avatar answered Feb 23 '26 06:02

Zach Kemp