How do you find the namespace/module name programmatically in Ruby on Rails?
None of these solutions consider a constant with multiple parent modules. For instance:
A::B::C
As of Rails 3.2.x you can simply:
"A::B::C".deconstantize #=> "A::B"
As of Rails 3.1.x you can:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
This is because #demodulize is the opposite of #deconstantize:
"A::B::C".demodulize #=> "C"
If you really need to do this manually, try this:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
How to check if a class or module is namespaced?
Working from "How do you find the namespace/module name programatically in Ruby on Rails?" you can use the presence of ::
in the class name to test if there is an associated module.
def self.is_namespaced?
self.name.include? "::"
end
Find classes available in a Module
Classes are accessed through constants. Classes defined within a module are listed as constants in that module. So you just need to choose the constants that refer to classes.
MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}
ActiveRecord WHERE with namespaced models
Is that normal that AR can infere table name of namespaced models from
relations in includes but can't in where?
Yes. This is an example of a leaky abstraction.
Assocations are an objection oriented abstraction around SQL joins, to let you do the fun stuff while AR worries about writing the SQL to join them and maintaining the in memory couplings between the records. .joins
, .left_joins
.includes
and .eager_load
are "aware" of your assocations and go through that abstraction. Because you have this object oriented abstraction .includes
is smart enough to figure out how the module nesting should effect the class names and table names when writing joins.
.where
and all the other parts of the ActiveRecord query interface are not as smart. This is just an API that generates SQL queries programmatically.
When you do .where(foo: 'bar')
its smart enough to translate that into WHERE table_name.foo = 'bar'
because the class is aware of its own table name.
When you do .where(demands: {user_id: 1})
the method is not actually aware of your associations, other model classes or the schema and just generates WHERE demands.user_id = 1
because that's how it translates a nested hash into SQL.
And note that this really has nothing to do with namespaces. When you do:
.where(reverse_auction_demands: {user_id: 1})
It works because you're using the right table name. If you where using a non-conventional table name that didn't line up with the model you would have the exact same issue.
If you want to create a where clause based on the class without hardcoding the table name pass a scope to where:
.where(
ReverseAuction::Demand.where(user_id: 1)
)
or use Arel:
.where(
ReverseAuction::Demand.arel_table[:user_id].eq(1)
)
How to dynamically load class using namespaces/subdirectory in Ruby/Rails?
try using constantize
instead:
module Wtf
class Damm
end
end
#=> nil
'Wtf::Damm'.constantize
#=> Wtf::Damm
Object.const_get 'Wtf::Damm'
#=> Wtf::Damm
Related Topics
How to Make Instance Variables Private in Ruby
Sum the Value of Array in Hash
How to Debug in Rubymine 4.5 Using Ruby 1.9.3
Why Doesn't Minitest::Spec Have a Wont_Raise Assertion
Missing Symbol When Installing Ruby-2.3.0 on Os X 10.11.6 by Rvm
How to Sort a Ruby Hash by Number Value
How to Compare Versions in Ruby
How to Build a Rubygems Mirror Server
Contact Form Mailer in Rails 4
In Ruby on Rails, After Send_File Method Delete the File from Server
Return Index of All Occurrences of a Character in a String in Ruby
Why Isn't 'Method=' Treated the Same as Any Other Method
Ruby Craziness: Class VS Object
How to Pass a Parameter for Gem Installation When I Run Bundle Install