How is continuous availability determined?

It seems that Ruby has undergone changes several times with regard to continuous availability. For Ruby 1.9.2, there is a description regarding continued availability in the question and answer here , but what is written there is no longer true.

In Ruby 2.3, if I have a constant defined in a class:

class A Foo = :a end 

I cannot access it through instance_eval or class_eval :

 A.new.instance_eval{Foo} # => error A.class_eval{Foo} # => error A.instance_eval{Foo} # => error 

although I can access it from the class body:

 class A; Foo end # => :a 

How does persistence work with Ruby 2.3? If possible, explain the historical changes to persistent availability in Ruby and the arguments that led to them.

+6
source share
2 answers

Constant search in Ruby uses a lexical region that intersects the current region and contains modules. The search path can be viewed using Module.nesting

 > module Out > module In > puts Module.nesting > end > end Out::In # gets searched for a given constant first Out 

The search remains unchanged inside the block to enable closure behavior, even for class_eval .

However, in Ruby 1.9, the receiver for instance_eval , instance_exec , class_eval and class_exec was added to the search path, which means that all constant references will first be detected in the receiver area.

Yehuda Katz raised a question with reference to a significant breakdown:

Consider the RSpec case:

 describe "Date" do it "equals itself" do Date.today.should == Date.today end end 

If you use the dynamic scope first, then if RSpec adds Spec :: Date, it will suddenly break this specification. The lexical area is more intuitive, and expected today by many normal needs.

The behavior subsequently returned to 1.8.

+2
source

Note. Below answer is based on Ruby 2.2, not tested on 2.3

According to Module#class_eval

Computes a string or block in the context of a mod, except that when a block is specified, the search for variables in a variable / class is not affected.

Although the code is below the error,

 A.class_eval{Foo} # uninitialized constant Foo (NameError) 

work is done where the line is eval ed.

 A.class_eval("Foo") #=> :a 

It also seems that Constant requires a module name or class name for a proper evaluation. Below work:

 A.class_eval{self::Foo} #=> :a 

So this is:

 A.new.instance_eval {self.class::Foo} #=> :a A.instance_eval {self::Foo} #=> :a 
+2
source

All Articles