Ruby namespacing
When you use
#The code in question
module Api
module V1
class UserController < ApplicationController
end
end
end
ApplicationController
definition will be searched in Api::V1
then if not found in Api
then if not found in the root namespace.
I agree it could be confusing, that's why I tend to use absolute paths like so: ::ApplicationController
If ever I'd need Api::ApplicationController
, I'd write ::Api::ApplicationController
Basically the ::
tells ruby to start from the root namespace and not from where the code lives.
Sidenote
Be aware that there are vicious cases in Rails development mode. In order to gain speed, the strict minimum is loaded. Then Rails looks for classes definitions when needed.
But this sometimes fails big time example, when you have say ::User
already loaded, and then look for ::Admin::User
. Rails would not look for it, it will think ::User
does the trick.
This can be solved using require_dependency
statements in your code. Speed has a cost :)
Ruby Class namespacing with modules: Why do I get NameError with double colons but not module blocks?
It may seem counter-intuitive, but constant lookup in Ruby is done using current lexical scope, i.e. the current lexical nesting level (location in the source code), not the semantic nesting level.
This can be tested by inspecting Module.nesting
, which prints the current lexical scope:
class Foo::SecondClass
pp Module.nesting # -> [Foo::SecondClass]
end
module Foo
class SecondClass
pp Module.nesting # -> [Foo::SecondClass, Foo]
end
end
Since Ruby uses this nesting level for symbol lookup, it means in the situation where you try to look up FirstClass
within nesting [Foo::SecondClass]
, Ruby will not find it.
However when you try to look it up within nesting [Foo::SecondClass, Foo]
, it will find FirstClass
under Foo
, just like you expect.
To get around this, you could do:
class Foo::SecondClass
def meth
Foo::FirstClass.new.meth
end
end
Which will now work as you expect, since you provided the necessary lookup hint for FirstClass
, and told Ruby it is inside Foo
.
How to add module namespace to a ruby class/module?
It seems like what you're asking is kinda multi-faceted, but if you just want to use the class in another file without having to type out the namespace each time then a simple solution would just be to redefine it in the file you want to use it in
ClassName = A::B::C::D::ClassName
Then you can just do ClassName.method
just fine
Ruby namespacing with a class vs. module?
The most immediate benefit to using modules for namespacing is that you can use include
to import the namespace, and use the constants declared within it unqualified:
module Foo; class Bar; end; end
module Elsewhere
include Foo
Bar.new
end
What are implications of namespacing classes under same namespace/under the same name as a module
As mentioned in the comment, namespacing as described in the question is just namespacing, and so the above are completely separate modules/classes.
Proper rails model namespacing
Indeed, if you do that, Ruby will complain because Party
can't be a module and a class at the same time. So at least, Party
would need to remain a class.
Now as the "Rails way" is concerned, we don't usually subclass our associations (ie. your Chat
will probably belong_to
a Party
), we just put all our models in the root namespace (unless one has a good reason to). So you'd have Party
at app/models/party.rb
and Chat
at app/models/chat.rb
.
I'm guessing one would make a namespaced subclass Party::Chat
only if there's a different ::Chat
already present, and even that could lead to trouble with Ruby's constant lookup which is sometimes counter-intuitive.
Namespacing in Ruby require
You will want to wrap your code in an actual module
or class
something like
class Foo
def self.bar
"quxx"
end
end
This way, you will be able to call Foo.bar
to access your method.
How do I un-namespace a ruby constant?
At first you can add the constant you need and assign the Class/Module to it (remember both are just objects). You should duplicate it to reset the name:
Posts = TableEngine::Posts.dup
Afterwards remove the source constant name:
Object.send :remove_const, :TableEngine
Then:
Posts
# => Posts
TableEngine
# => NameError: uninitialized constant TableEngine
TableEngine::Posts
# => NameError: uninitialized constant TableEngine
UPDATE. Why dup
is needed:
Notice, the class SomeClass
is a shortcut for creating an object of type Class
and assigning it to some constant:
SomeClass = Class.new
When you create a class, its name value isn't set:
klass = Class.new
# => #<Class:0x00000001545a28>
klass.name
# => nil
When you assign it to the constant for the first time, the name is assigned and memoized:
Klass = klass
# => Klass
klass.name
# => "Klass"
When you later assign the object of type Class
to another constant, it remains just the same object, referred by both constants:
NewKlass = Klass
# => Klass
Klass.name
# => "Klass"
NewKlass.name
# => "Klass"
That's why even if the initial constant will be removed, the object will keep carrying the old name.
Object.send :remove_const, :Klass
# => Klass
NewKlass
# => Klass
NewKlass.name
# => "Klass"
Klass
# => NameError: uninitialized constant Klass
The object by itself hasn't been changed. What has been changed is the list of constants, carried by the Object
object.
When you duplicate the object of type Class
it is created without any name (it is the new object):
new_klass = NewKlass.dup
# => #<Class:0x000000016ced90>
new_klass.name
# => nil
And when you assing it to the new constant, the name is set. That is how in the very first example above it receives the new name:
Posts = TableEngine::Posts.dup
# => Post
What's the difference between these Ruby namespace conventions?
The difference lies in nesting.
In the example below, you can see that the former method using class Foo, can get the outer scope's constant variables BAR_A without errors.
Meanwhile, class Baz will bomb with an error of uninitialized constant A::B::Baz::BAR_A. As it doesn't bring in A::* implicitly, only A::B::*explicitly.
module A
BAR_A = 'Bar A!'
module B
BAR_B = 'Bar B!'
class Foo
p BAR_A
p BAR_B
end
end
end
class A::B::Baz
p BAR_A
p BAR_B
end
Both behaviors have their place. There's no real consensus in the community in my opinion as to which is the One True Ruby Way (tm). I personally use the former, most of the time.
Related Topics
How to Enable Tls V1.2 in Ruby? If So, How
Ruby Gems Returns "Command Not Found"
Homebrew Installation on MAC Os X Failed to Connect to Raw.Githubusercontent.Com Port 443
How to Easily Parse a Url with Parameters in a Rails Test
No Such File or Directory - Git Ls-Files -- Windows
Handling a JavaScript Popup Occurring on a Keyup Event
What Does &: Mean in Ruby, Is It a Block Mixed with a Symbol
How Is a Local Variable Created Even When If Condition Evaluates to False in Ruby
How to Use Savon Nested Attributes! Hash
Parse Email Addresses for "From" and "To" Fields in Ruby
In Ruby, Is There No Way to Dynamically Define a Local Variable in the Current Context
Dry Way to Assign Hash Values to an Object
What Does ::Myclass Ruby Scope Operator Do
How to Handle a Thread Issue in Zeromq + Ruby