how rails delegate method works?

后端 未结 2 748
死守一世寂寞
死守一世寂寞 2021-02-05 12:50

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.

2条回答
  •  滥情空心
    2021-02-05 13:11

    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.

提交回复
热议问题