Reputation: 30256
I'm trying to enforce a boundary in a Rails app: only code within the namespace Boundary
should be able to access the class Boundary::Blackbox
.
This works alright when it's defined outside of an autoloaded path:
# app/lib/boundary/blackbox.rb
module Boundary
module Blackbox
def self.foo
"from foo"
end
end
private_constant :Blackbox
end
# app/lib/boundary.rb
module Boundary
def self.bridge
"from bridge > " + Blackbox.foo
end
end
# app/lib/outside.rb
module Outside
def self.violation
"from violation > " + Boundary::Blackbox.foo
end
end
I expect the ruby code to make Boundary::Blackbox
private, and indeed it is private except when Boundary::Blackbox
is defined where the autoloader expects to find it.
Suppose I define it in example.rb
instead:
load "example.rb"
Boundary.bridge # => "from bridge > from foo"
Outside.violation # => NameError uninitialized constant Boundary::Blackbox
Boundary::Blackbox.foo # => NameError uninitialized constant Boundary::Blackbox
Now let's test it using app/lib/boundary/blackbox.rb
:
load "app/lib/boundary/blackbox.rb"
Boundary.bridge # => "from bridge > from foo"
Outside.violation # => "from violation > from foo"
Boundary::Blackbox.foo # => "from foo"
Now I get no NameError; Boundary::Blackbox
is completely accessible.
How can I make my Boundary::Blackbox
module private but also keep it in a location where the autoloader expects to find it?
(TMI: I do want it autoloaded so that Boundary.bridge
can access it automatically, but I don't want to put it into app/lib/boundary.rb
because that file would grow prohibitively unwieldy with the various modules/classes which need to go into the Boundary
namespace. And I'm loath to put it into a file that falls outside the autoloader's pattern because I need to uphold conventions in a very large application.)
Upvotes: 0
Views: 65