Ruby constant search path problem in-depth research, ruby constant

Source: Internet
Author: User

Ruby constant search path problem in-depth research, ruby constant

The constant path search problem in Ruby has been a problem that has plagued me all the time. I have encountered several times in my work and have never thoroughly figured out why. I recently read a book "Ruby metaprogramming", I have a deeper understanding of the Ruby object model and read a blog titled Everything you ever wanted to know about constant lookup in Ruby. finally, let me figure out the path of Ruby constants.

The first problem I encountered was that I posted a post on Ruby-China.
Copy codeThe Code is as follows:
Module M1
CT = "OK"
End

Class C1
CK = "ck"
Include M1

Def self. method1
Puts self
Puts "# {CK} in method1"
Puts "# {CT} in method1"
End

Class <self
Def method2
Puts self
Puts "# {CK} in method1"
Puts "# {CT} in method2"
End
End
End

C1.method1
C1.method2

The output result is

Copy codeThe Code is as follows:
C1
Ck in method1
OK in method1
C1
Ck in method2
NameError: uninitialized constant Class: CT
From (irb): 16: in 'method2'

This is a problem I encountered when restructuring the mint net code. Both method1 and method2 are common class methods and definitions. I have always considered them equivalent and replaceable methods, but from the actual execution results, the constant search paths in them are different.

If I change the M1 definition to the following:
Copy codeThe Code is as follows:
Module M1
Def self. included (base)
Base. extend (self)
End
CT = "OK"
End

The execution result is:
Copy codeThe Code is as follows:
C1
Ck in method1
OK in method1
C1
Ck in method2
OK in method2

Another problem is also frequently encountered. Abstract The problem Code as follows:
Copy codeThe Code is as follows:
Module
Module M
Def a_method
#...
End
End
End

Class A: B
Include M
End

An exception is reported:
Copy codeThe Code is as follows:
NameError: uninitialized constant A: B: M
From (irb): 10: in '<class: B>'

Ruby constants are searched based on two paths.

A. Module. nesting
B. ancestors of open class/module

A has A higher priority than B. A cannot be found before it can be found in B.

A. module. the concept of nesting is easy to understand. It refers to the module nesting of code positions. It is an array, from the inner layer to the outermost layer. If no nesting exists, the array is empty. The Module. nesting value exists in any code position. You can print the Module. nesting value in each position using the following code.

Copy codeThe Code is as follows:
P Module. nesting

Module
Module B
P Module. nesting
Module C
P Module. nesting
End
End
End

Module A: B
P Module. nesting
End

The output is:
Copy codeThe Code is as follows:
[]
[A: B, A]
[A: B: C, A: B, A]
[A: B]

Have you noticed that A is not in the module due to the shortcut writing method Module A: B. in nesting, this is the root cause of the second problem, because M is A constant in module A, and module A: B does not search for A: M.

After talking about A Module. nesting, let's talk about the ancestors of B open class/module. This problem is much more complicated. Simply put, a self exists in any location of Ruby code, and an open class/module exists in the module and class definition, it is usually the corresponding module and Class. Inside the method, it is the class corresponding to the method. For ancestors, we can use the ancestors method of open class/module in the code position.

(Note: ancestors becomes a bit complicated after introducing the singleton_class concept. For details, refer to Ruby metaprogramming.)

The first problem above: In method1, A is [C1] open class/module is C1, so ancestors is [C1, M1, Object, Kernel, BasicObject] CK which can be found in, CT can be found in B.

In method2, A is [C1] open class/module is the singleton_class of C1, so ancestors is [Class, Module, Object, Kernel, BasicObject] CK which can be found in, CT cannot be found in both A and B.

For
Copy codeThe Code is as follows:
Module M1
Def self. included (base)
Base. extend (self)
End
CT = "OK"
End

It can be run because, in method2, singleton_class of open class/module C1 extends M1, so ancestors becomes [M1, Class, Module, Object, Kernel, BasicObject].

So far, these two problems that have plagued me for a long time have finally been thoroughly clarified. This process gives me an experience: in the face of some technical questions, if you just give it a taste, you will never be able to really master it. Only by in-depth research and thorough understanding of its principles, in order to truly master it and achieve real capability improvement.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.