How to Find the Namespace/Module Name Programmatically in Ruby on Rails

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



Leave a reply



Submit