1require_relative '../spec_helper' 2require_relative '../fixtures/constants' 3require_relative 'fixtures/constants_sclass' 4require_relative 'fixtures/constant_visibility' 5 6# Read the documentation in fixtures/constants.rb for the guidelines and 7# rationale for the structure and organization of these specs. 8 9describe "Literal (A::X) constant resolution" do 10 describe "with statically assigned constants" do 11 it "searches the immediate class or module scope first" do 12 ConstantSpecs::ClassA::CS_CONST10.should == :const10_10 13 ConstantSpecs::ModuleA::CS_CONST10.should == :const10_1 14 ConstantSpecs::ParentA::CS_CONST10.should == :const10_5 15 ConstantSpecs::ContainerA::CS_CONST10.should == :const10_2 16 ConstantSpecs::ContainerA::ChildA::CS_CONST10.should == :const10_3 17 end 18 19 it "searches a module included in the immediate class before the superclass" do 20 ConstantSpecs::ContainerA::ChildA::CS_CONST15.should == :const15_1 21 end 22 23 it "searches the superclass before a module included in the superclass" do 24 ConstantSpecs::ContainerA::ChildA::CS_CONST11.should == :const11_1 25 end 26 27 it "searches a module included in the superclass" do 28 ConstantSpecs::ContainerA::ChildA::CS_CONST12.should == :const12_1 29 end 30 31 it "searches the superclass chain" do 32 ConstantSpecs::ContainerA::ChildA::CS_CONST13.should == :const13 33 end 34 35 it "searches Object if no class or module qualifier is given" do 36 CS_CONST1.should == :const1 37 CS_CONST10.should == :const10_1 38 end 39 40 it "searches Object after searching other scopes" do 41 module ConstantSpecs::SpecAdded1 42 CS_CONST10.should == :const10_1 43 end 44 end 45 46 it "searches Object if a toplevel qualifier (::X) is given" do 47 ::CS_CONST1.should == :const1 48 ::CS_CONST10.should == :const10_1 49 end 50 51 it "does not search the singleton class of the class or module" do 52 lambda do 53 ConstantSpecs::ContainerA::ChildA::CS_CONST14 54 end.should raise_error(NameError) 55 lambda { ConstantSpecs::CS_CONST14 }.should raise_error(NameError) 56 end 57 end 58 59 describe "with dynamically assigned constants" do 60 it "searches the immediate class or module scope first" do 61 ConstantSpecs::ClassB::CS_CONST101 = :const101_1 62 ConstantSpecs::ClassB::CS_CONST101.should == :const101_1 63 64 ConstantSpecs::ParentB::CS_CONST101 = :const101_2 65 ConstantSpecs::ParentB::CS_CONST101.should == :const101_2 66 67 ConstantSpecs::ContainerB::CS_CONST101 = :const101_3 68 ConstantSpecs::ContainerB::CS_CONST101.should == :const101_3 69 70 ConstantSpecs::ContainerB::ChildB::CS_CONST101 = :const101_4 71 ConstantSpecs::ContainerB::ChildB::CS_CONST101.should == :const101_4 72 73 ConstantSpecs::ModuleA::CS_CONST101 = :const101_5 74 ConstantSpecs::ModuleA::CS_CONST101.should == :const101_5 75 end 76 77 it "searches a module included in the immediate class before the superclass" do 78 ConstantSpecs::ParentB::CS_CONST102 = :const102_1 79 ConstantSpecs::ModuleF::CS_CONST102 = :const102_2 80 ConstantSpecs::ContainerB::ChildB::CS_CONST102.should == :const102_2 81 end 82 83 it "searches the superclass before a module included in the superclass" do 84 ConstantSpecs::ModuleE::CS_CONST103 = :const103_1 85 ConstantSpecs::ParentB::CS_CONST103 = :const103_2 86 ConstantSpecs::ContainerB::ChildB::CS_CONST103.should == :const103_2 87 end 88 89 it "searches a module included in the superclass" do 90 ConstantSpecs::ModuleA::CS_CONST104 = :const104_1 91 ConstantSpecs::ModuleE::CS_CONST104 = :const104_2 92 ConstantSpecs::ContainerB::ChildB::CS_CONST104.should == :const104_2 93 end 94 95 it "searches the superclass chain" do 96 ConstantSpecs::ModuleA::CS_CONST105 = :const105 97 ConstantSpecs::ContainerB::ChildB::CS_CONST105.should == :const105 98 end 99 100 it "searches Object if no class or module qualifier is given" do 101 CS_CONST106 = :const106 102 CS_CONST106.should == :const106 103 end 104 105 it "searches Object if a toplevel qualifier (::X) is given" do 106 ::CS_CONST107 = :const107 107 ::CS_CONST107.should == :const107 108 end 109 110 it "does not search the singleton class of the class or module" do 111 class << ConstantSpecs::ContainerB::ChildB 112 CS_CONST108 = :const108_1 113 end 114 115 lambda do 116 ConstantSpecs::ContainerB::ChildB::CS_CONST108 117 end.should raise_error(NameError) 118 119 module ConstantSpecs 120 class << self 121 CS_CONST108 = :const108_2 122 end 123 end 124 125 lambda { ConstantSpecs::CS_CONST108 }.should raise_error(NameError) 126 end 127 128 it "returns the updated value when a constant is reassigned" do 129 ConstantSpecs::ClassB::CS_CONST109 = :const109_1 130 ConstantSpecs::ClassB::CS_CONST109.should == :const109_1 131 132 -> { 133 ConstantSpecs::ClassB::CS_CONST109 = :const109_2 134 }.should complain(/already initialized constant/) 135 ConstantSpecs::ClassB::CS_CONST109.should == :const109_2 136 end 137 138 it "evaluates the right hand side before evaluating a constant path" do 139 mod = Module.new 140 141 mod.module_eval <<-EOC 142 ConstantSpecsRHS::B = begin 143 module ConstantSpecsRHS; end 144 145 "hello" 146 end 147 EOC 148 149 mod::ConstantSpecsRHS::B.should == 'hello' 150 end 151 end 152 153 it "raises a NameError if no constant is defined in the search path" do 154 lambda { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError) 155 end 156 157 it "sends #const_missing to the original class or module scope" do 158 ConstantSpecs::ClassA::CS_CONSTX.should == :CS_CONSTX 159 end 160 161 it "evaluates the qualifier" do 162 ConstantSpecs.get_const::CS_CONST2.should == :const2 163 end 164 165 it "raises a TypeError if a non-class or non-module qualifier is given" do 166 lambda { CS_CONST1::CS_CONST }.should raise_error(TypeError) 167 lambda { 1::CS_CONST }.should raise_error(TypeError) 168 lambda { "mod"::CS_CONST }.should raise_error(TypeError) 169 lambda { false::CS_CONST }.should raise_error(TypeError) 170 end 171end 172 173describe "Constant resolution within methods" do 174 describe "with statically assigned constants" do 175 it "searches the immediate class or module scope first" do 176 ConstantSpecs::ClassA.const10.should == :const10_10 177 ConstantSpecs::ParentA.const10.should == :const10_5 178 ConstantSpecs::ContainerA.const10.should == :const10_2 179 ConstantSpecs::ContainerA::ChildA.const10.should == :const10_3 180 181 ConstantSpecs::ClassA.new.const10.should == :const10_10 182 ConstantSpecs::ParentA.new.const10.should == :const10_5 183 ConstantSpecs::ContainerA::ChildA.new.const10.should == :const10_3 184 end 185 186 it "searches a module included in the immediate class before the superclass" do 187 ConstantSpecs::ContainerA::ChildA.const15.should == :const15_1 188 ConstantSpecs::ContainerA::ChildA.new.const15.should == :const15_1 189 end 190 191 it "searches the superclass before a module included in the superclass" do 192 ConstantSpecs::ContainerA::ChildA.const11.should == :const11_1 193 ConstantSpecs::ContainerA::ChildA.new.const11.should == :const11_1 194 end 195 196 it "searches a module included in the superclass" do 197 ConstantSpecs::ContainerA::ChildA.const12.should == :const12_1 198 ConstantSpecs::ContainerA::ChildA.new.const12.should == :const12_1 199 end 200 201 it "searches the superclass chain" do 202 ConstantSpecs::ContainerA::ChildA.const13.should == :const13 203 ConstantSpecs::ContainerA::ChildA.new.const13.should == :const13 204 end 205 206 it "searches the lexical scope of the method not the receiver's immediate class" do 207 ConstantSpecs::ContainerA::ChildA.const19.should == :const19_1 208 end 209 210 it "searches the lexical scope of a singleton method" do 211 ConstantSpecs::CS_CONST18.const17.should == :const17_1 212 end 213 214 it "does not search the lexical scope of the caller" do 215 lambda { ConstantSpecs::ClassA.const16 }.should raise_error(NameError) 216 end 217 218 it "searches the lexical scope of a block" do 219 ConstantSpecs::ClassA.const22.should == :const22_1 220 end 221 222 it "searches Object as a lexical scope only if Object is explicitly opened" do 223 ConstantSpecs::ContainerA::ChildA.const20.should == :const20_1 224 ConstantSpecs::ContainerA::ChildA.const21.should == :const21_1 225 end 226 227 it "does not search the lexical scope of qualifying modules" do 228 lambda do 229 ConstantSpecs::ContainerA::ChildA.const23 230 end.should raise_error(NameError) 231 end 232 end 233 234 describe "with dynamically assigned constants" do 235 it "searches the immediate class or module scope first" do 236 ConstantSpecs::ModuleA::CS_CONST201 = :const201_1 237 238 class ConstantSpecs::ClassB; CS_CONST201 = :const201_2; end 239 ConstantSpecs::ParentB::CS_CONST201 = :const201_3 240 ConstantSpecs::ContainerB::CS_CONST201 = :const201_4 241 ConstantSpecs::ContainerB::ChildB::CS_CONST201 = :const201_5 242 243 ConstantSpecs::ClassB.const201.should == :const201_2 244 ConstantSpecs::ParentB.const201.should == :const201_3 245 ConstantSpecs::ContainerB.const201.should == :const201_4 246 ConstantSpecs::ContainerB::ChildB.const201.should == :const201_5 247 248 ConstantSpecs::ClassB.new.const201.should == :const201_2 249 ConstantSpecs::ParentB.new.const201.should == :const201_3 250 ConstantSpecs::ContainerB::ChildB.new.const201.should == :const201_5 251 end 252 253 it "searches a module included in the immediate class before the superclass" do 254 ConstantSpecs::ParentB::CS_CONST202 = :const202_2 255 ConstantSpecs::ContainerB::ChildB::CS_CONST202 = :const202_1 256 257 ConstantSpecs::ContainerB::ChildB.const202.should == :const202_1 258 ConstantSpecs::ContainerB::ChildB.new.const202.should == :const202_1 259 end 260 261 it "searches the superclass before a module included in the superclass" do 262 ConstantSpecs::ParentB::CS_CONST203 = :const203_1 263 ConstantSpecs::ModuleE::CS_CONST203 = :const203_2 264 265 ConstantSpecs::ContainerB::ChildB.const203.should == :const203_1 266 ConstantSpecs::ContainerB::ChildB.new.const203.should == :const203_1 267 end 268 269 it "searches a module included in the superclass" do 270 ConstantSpecs::ModuleA::CS_CONST204 = :const204_2 271 ConstantSpecs::ModuleE::CS_CONST204 = :const204_1 272 273 ConstantSpecs::ContainerB::ChildB.const204.should == :const204_1 274 ConstantSpecs::ContainerB::ChildB.new.const204.should == :const204_1 275 end 276 277 it "searches the superclass chain" do 278 ConstantSpecs::ModuleA::CS_CONST205 = :const205 279 280 ConstantSpecs::ContainerB::ChildB.const205.should == :const205 281 ConstantSpecs::ContainerB::ChildB.new.const205.should == :const205 282 end 283 284 it "searches the lexical scope of the method not the receiver's immediate class" do 285 ConstantSpecs::ContainerB::ChildB::CS_CONST206 = :const206_2 286 class ConstantSpecs::ContainerB::ChildB 287 class << self 288 CS_CONST206 = :const206_1 289 end 290 end 291 292 ConstantSpecs::ContainerB::ChildB.const206.should == :const206_1 293 end 294 295 it "searches the lexical scope of a singleton method" do 296 ConstantSpecs::CS_CONST207 = :const207_1 297 ConstantSpecs::ClassB::CS_CONST207 = :const207_2 298 299 ConstantSpecs::CS_CONST208.const207.should == :const207_1 300 end 301 302 it "does not search the lexical scope of the caller" do 303 ConstantSpecs::ClassB::CS_CONST209 = :const209 304 305 lambda { ConstantSpecs::ClassB.const209 }.should raise_error(NameError) 306 end 307 308 it "searches the lexical scope of a block" do 309 ConstantSpecs::ClassB::CS_CONST210 = :const210_1 310 ConstantSpecs::ParentB::CS_CONST210 = :const210_2 311 312 ConstantSpecs::ClassB.const210.should == :const210_1 313 end 314 315 it "searches Object as a lexical scope only if Object is explicitly opened" do 316 Object::CS_CONST211 = :const211_1 317 ConstantSpecs::ParentB::CS_CONST211 = :const211_2 318 ConstantSpecs::ContainerB::ChildB.const211.should == :const211_1 319 320 Object::CS_CONST212 = :const212_2 321 ConstantSpecs::ParentB::CS_CONST212 = :const212_1 322 ConstantSpecs::ContainerB::ChildB.const212.should == :const212_1 323 end 324 325 it "returns the updated value when a constant is reassigned" do 326 ConstantSpecs::ParentB::CS_CONST213 = :const213_1 327 ConstantSpecs::ContainerB::ChildB.const213.should == :const213_1 328 ConstantSpecs::ContainerB::ChildB.new.const213.should == :const213_1 329 330 -> { 331 ConstantSpecs::ParentB::CS_CONST213 = :const213_2 332 }.should complain(/already initialized constant/) 333 ConstantSpecs::ContainerB::ChildB.const213.should == :const213_2 334 ConstantSpecs::ContainerB::ChildB.new.const213.should == :const213_2 335 end 336 337 it "does not search the lexical scope of qualifying modules" do 338 ConstantSpecs::ContainerB::CS_CONST214 = :const214 339 340 lambda do 341 ConstantSpecs::ContainerB::ChildB.const214 342 end.should raise_error(NameError) 343 end 344 end 345 346 it "raises a NameError if no constant is defined in the search path" do 347 lambda { ConstantSpecs::ParentA.constx }.should raise_error(NameError) 348 end 349 350 it "sends #const_missing to the original class or module scope" do 351 ConstantSpecs::ClassA.constx.should == :CS_CONSTX 352 ConstantSpecs::ClassA.new.constx.should == :CS_CONSTX 353 end 354 355 describe "with ||=" do 356 it "assigns a scoped constant if previously undefined" do 357 ConstantSpecs.should_not have_constant(:OpAssignUndefined) 358 module ConstantSpecs 359 OpAssignUndefined ||= 42 360 end 361 ConstantSpecs::OpAssignUndefined.should == 42 362 ConstantSpecs::OpAssignUndefinedOutside ||= 42 363 ConstantSpecs::OpAssignUndefinedOutside.should == 42 364 ConstantSpecs.send(:remove_const, :OpAssignUndefined) 365 ConstantSpecs.send(:remove_const, :OpAssignUndefinedOutside) 366 end 367 368 it "assigns a global constant if previously undefined" do 369 OpAssignGlobalUndefined ||= 42 370 ::OpAssignGlobalUndefinedExplicitScope ||= 42 371 OpAssignGlobalUndefined.should == 42 372 ::OpAssignGlobalUndefinedExplicitScope.should == 42 373 Object.send :remove_const, :OpAssignGlobalUndefined 374 Object.send :remove_const, :OpAssignGlobalUndefinedExplicitScope 375 end 376 377 end 378 379 describe "with &&=" do 380 it "re-assigns a scoped constant if already true" do 381 module ConstantSpecs 382 OpAssignTrue = true 383 end 384 suppress_warning do 385 ConstantSpecs::OpAssignTrue &&= 1 386 end 387 ConstantSpecs::OpAssignTrue.should == 1 388 ConstantSpecs.send :remove_const, :OpAssignTrue 389 end 390 391 it "leaves scoped constant if not true" do 392 module ConstantSpecs 393 OpAssignFalse = false 394 end 395 ConstantSpecs::OpAssignFalse &&= 1 396 ConstantSpecs::OpAssignFalse.should == false 397 ConstantSpecs.send :remove_const, :OpAssignFalse 398 end 399 end 400end 401 402describe "Constant resolution within a singleton class (class << obj)" do 403 it "works like normal classes or modules" do 404 ConstantSpecs::CS_SINGLETON1.foo.should == 1 405 end 406 407 it "uses its own namespace for each object" do 408 a = ConstantSpecs::CS_SINGLETON2[0].foo 409 b = ConstantSpecs::CS_SINGLETON2[1].foo 410 [a, b].should == [1, 2] 411 end 412 413 it "uses its own namespace for nested modules" do 414 a = ConstantSpecs::CS_SINGLETON3[0].x 415 b = ConstantSpecs::CS_SINGLETON3[1].x 416 a.should_not equal(b) 417 end 418 419 it "allows nested modules to have proper resolution" do 420 a = ConstantSpecs::CS_SINGLETON4_CLASSES[0].new 421 b = ConstantSpecs::CS_SINGLETON4_CLASSES[1].new 422 [a.foo, b.foo].should == [1, 2] 423 end 424end 425 426describe "top-level constant lookup" do 427 context "on a class" do 428 ruby_version_is "" ... "2.5" do 429 it "searches Object successfully after searching other scopes" do 430 ->() { 431 String::Hash.should == Hash 432 }.should complain(/toplevel constant Hash referenced by/) 433 end 434 end 435 436 ruby_version_is "2.5" do 437 it "does not search Object after searching other scopes" do 438 ->() { String::Hash }.should raise_error(NameError) 439 end 440 end 441 end 442 443 it "searches Object unsuccessfully when searches on a module" do 444 ->() { Enumerable::Hash }.should raise_error(NameError) 445 end 446end 447 448describe "Module#private_constant marked constants" do 449 450 it "remain private even when updated" do 451 mod = Module.new 452 mod.const_set :Foo, true 453 mod.send :private_constant, :Foo 454 -> { 455 mod.const_set :Foo, false 456 }.should complain(/already initialized constant/) 457 458 lambda {mod::Foo}.should raise_error(NameError) 459 end 460 461 ruby_version_is "2.6" do 462 it "sends #const_missing to the original class or module" do 463 mod = Module.new 464 mod.const_set :Foo, true 465 mod.send :private_constant, :Foo 466 def mod.const_missing(name) 467 name == :Foo ? name : super 468 end 469 470 mod::Foo.should == :Foo 471 end 472 end 473 474 describe "in a module" do 475 it "cannot be accessed from outside the module" do 476 lambda do 477 ConstantVisibility::PrivConstModule::PRIVATE_CONSTANT_MODULE 478 end.should raise_error(NameError) 479 end 480 481 it "cannot be reopened as a module from scope where constant would be private" do 482 lambda do 483 module ConstantVisibility::ModuleContainer::PrivateModule; end 484 end.should raise_error(NameError) 485 end 486 487 it "cannot be reopened as a class from scope where constant would be private" do 488 lambda do 489 class ConstantVisibility::ModuleContainer::PrivateClass; end 490 end.should raise_error(NameError) 491 end 492 493 it "can be reopened as a module where constant is not private" do 494 module ::ConstantVisibility::ModuleContainer 495 module PrivateModule 496 X = 1 497 end 498 499 PrivateModule::X.should == 1 500 end 501 end 502 503 it "can be reopened as a class where constant is not private" do 504 module ::ConstantVisibility::ModuleContainer 505 class PrivateClass 506 X = 1 507 end 508 509 PrivateClass::X.should == 1 510 end 511 end 512 513 it "is not defined? with A::B form" do 514 defined?(ConstantVisibility::PrivConstModule::PRIVATE_CONSTANT_MODULE).should == nil 515 end 516 517 it "can be accessed from the module itself" do 518 ConstantVisibility::PrivConstModule.private_constant_from_self.should be_true 519 end 520 521 it "is defined? from the module itself" do 522 ConstantVisibility::PrivConstModule.defined_from_self.should == "constant" 523 end 524 525 it "can be accessed from lexical scope" do 526 ConstantVisibility::PrivConstModule::Nested.private_constant_from_scope.should be_true 527 end 528 529 it "is defined? from lexical scope" do 530 ConstantVisibility::PrivConstModule::Nested.defined_from_scope.should == "constant" 531 end 532 533 it "can be accessed from classes that include the module" do 534 ConstantVisibility::PrivConstModuleChild.new.private_constant_from_include.should be_true 535 end 536 537 it "is defined? from classes that include the module" do 538 ConstantVisibility::PrivConstModuleChild.new.defined_from_include.should == "constant" 539 end 540 end 541 542 describe "in a class" do 543 it "cannot be accessed from outside the class" do 544 lambda do 545 ConstantVisibility::PrivConstClass::PRIVATE_CONSTANT_CLASS 546 end.should raise_error(NameError) 547 end 548 549 it "cannot be reopened as a module" do 550 lambda do 551 module ConstantVisibility::ClassContainer::PrivateModule; end 552 end.should raise_error(NameError) 553 end 554 555 it "cannot be reopened as a class" do 556 lambda do 557 class ConstantVisibility::ClassContainer::PrivateClass; end 558 end.should raise_error(NameError) 559 end 560 561 it "can be reopened as a module where constant is not private" do 562 class ::ConstantVisibility::ClassContainer 563 module PrivateModule 564 X = 1 565 end 566 567 PrivateModule::X.should == 1 568 end 569 end 570 571 it "can be reopened as a class where constant is not private" do 572 class ::ConstantVisibility::ClassContainer 573 class PrivateClass 574 X = 1 575 end 576 577 PrivateClass::X.should == 1 578 end 579 end 580 581 it "is not defined? with A::B form" do 582 defined?(ConstantVisibility::PrivConstClass::PRIVATE_CONSTANT_CLASS).should == nil 583 end 584 585 it "can be accessed from the class itself" do 586 ConstantVisibility::PrivConstClass.private_constant_from_self.should be_true 587 end 588 589 it "is defined? from the class itself" do 590 ConstantVisibility::PrivConstClass.defined_from_self.should == "constant" 591 end 592 593 it "can be accessed from lexical scope" do 594 ConstantVisibility::PrivConstClass::Nested.private_constant_from_scope.should be_true 595 end 596 597 it "is defined? from lexical scope" do 598 ConstantVisibility::PrivConstClass::Nested.defined_from_scope.should == "constant" 599 end 600 601 it "can be accessed from subclasses" do 602 ConstantVisibility::PrivConstClassChild.new.private_constant_from_subclass.should be_true 603 end 604 605 it "is defined? from subclasses" do 606 ConstantVisibility::PrivConstClassChild.new.defined_from_subclass.should == "constant" 607 end 608 end 609 610 describe "in Object" do 611 it "cannot be accessed using ::Const form" do 612 lambda do 613 ::PRIVATE_CONSTANT_IN_OBJECT 614 end.should raise_error(NameError) 615 end 616 617 it "is not defined? using ::Const form" do 618 defined?(::PRIVATE_CONSTANT_IN_OBJECT).should == nil 619 end 620 621 it "can be accessed through the normal search" do 622 PRIVATE_CONSTANT_IN_OBJECT.should == true 623 end 624 625 it "is defined? through the normal search" do 626 defined?(PRIVATE_CONSTANT_IN_OBJECT).should == "constant" 627 end 628 end 629 630 describe "NameError by #private_constant" do 631 it "has :receiver and :name attributes" do 632 lambda do 633 ConstantVisibility::PrivConstClass::PRIVATE_CONSTANT_CLASS 634 end.should raise_error(NameError) {|e| 635 e.receiver.should == ConstantVisibility::PrivConstClass 636 e.name.should == :PRIVATE_CONSTANT_CLASS 637 } 638 639 lambda do 640 ConstantVisibility::PrivConstModule::PRIVATE_CONSTANT_MODULE 641 end.should raise_error(NameError) {|e| 642 e.receiver.should == ConstantVisibility::PrivConstModule 643 e.name.should == :PRIVATE_CONSTANT_MODULE 644 } 645 end 646 647 it "has the defined class as the :name attribute" do 648 lambda do 649 ConstantVisibility::PrivConstClassChild::PRIVATE_CONSTANT_CLASS 650 end.should raise_error(NameError) {|e| 651 e.receiver.should == ConstantVisibility::PrivConstClass 652 e.name.should == :PRIVATE_CONSTANT_CLASS 653 } 654 655 lambda do 656 ConstantVisibility::PrivConstModuleChild::PRIVATE_CONSTANT_MODULE 657 end.should raise_error(NameError) {|e| 658 ruby_bug "#14853", ""..."2.5.2" do 659 e.receiver.should == ConstantVisibility::PrivConstModule 660 end 661 e.name.should == :PRIVATE_CONSTANT_MODULE 662 } 663 end 664 end 665end 666 667describe "Module#public_constant marked constants" do 668 before :each do 669 @module = ConstantVisibility::PrivConstModule.dup 670 end 671 672 describe "in a module" do 673 it "can be accessed from outside the module" do 674 @module.send :public_constant, :PRIVATE_CONSTANT_MODULE 675 @module::PRIVATE_CONSTANT_MODULE.should == true 676 end 677 678 it "is defined? with A::B form" do 679 @module.send :public_constant, :PRIVATE_CONSTANT_MODULE 680 defined?(@module::PRIVATE_CONSTANT_MODULE).should == "constant" 681 end 682 end 683 684 describe "in a class" do 685 before :each do 686 @class = ConstantVisibility::PrivConstClass.dup 687 end 688 689 it "can be accessed from outside the class" do 690 @class.send :public_constant, :PRIVATE_CONSTANT_CLASS 691 @class::PRIVATE_CONSTANT_CLASS.should == true 692 end 693 694 it "is defined? with A::B form" do 695 @class.send :public_constant, :PRIVATE_CONSTANT_CLASS 696 defined?(@class::PRIVATE_CONSTANT_CLASS).should == "constant" 697 end 698 end 699 700 describe "in Object" do 701 after :each do 702 ConstantVisibility.reset_private_constants 703 end 704 705 it "can be accessed using ::Const form" do 706 Object.send :public_constant, :PRIVATE_CONSTANT_IN_OBJECT 707 ::PRIVATE_CONSTANT_IN_OBJECT.should == true 708 end 709 710 it "is defined? using ::Const form" do 711 Object.send :public_constant, :PRIVATE_CONSTANT_IN_OBJECT 712 defined?(::PRIVATE_CONSTANT_IN_OBJECT).should == "constant" 713 end 714 end 715end 716