Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: Convert Constant to String

Tags:

ruby

I'd like to convert the constant FOO::BAR to the string "BAR".

This is the opposite of what constantize does and is very similar to demodulize, except I expect a string instead of the actual Module reference.

I was thinking I could make my own helper to do this, but I'm not able to get the "stringified" version of FOO::BAR.

Ideally, I'd like to avoid any 3rd party gems.

Example:

class FOO
  BAR = {}
end

# this works
FOO            #=> FOO
FOO.name       #=> "FOO"    

# this doesn't
FOO::BAR       #=> {} 
FOO::BAR.name  #=> NoMethodError: undefined method `name' for {}:Hash
like image 686
doremi Avatar asked Oct 19 '25 16:10

doremi


1 Answers

You can't pass constants, you can only pass objects. If you pass FOO::BAR to a method, you're not passing the constant, but the object that has been assigned to FOO::BAR, i.e. the hash.

In order to retrieve the constant's name an object has been assigned-to from the object itself, the object has to store the name somehow.

Modules do store the constant name they have been assigned-to (Ruby sets the name when a module is assigned to a constant for the first time). And because FOO is a module (classes are modules), you can call FOO.name and it returns "FOO". But that only works because the object "knows" its name.

From the built-in objects, only Module (and therefore Class) has a name method that works this way.

You could add a name method to the hash instance FOO::BAR is referring to, although this is probably not what you want:

def (FOO::BAR).name
  'FOO::BAR'
end

FOO::BAR.name #=> "FOO::BAR"

Another way is to pass both, the constant (the object actually) and its module to a method:

def find_const(mod, obj)
  mod.constants.find { |c| mod.const_get(c).equal?(obj) }
end

find_const(FOO, FOO::BAR) #=> :BAR

The method traverses the module's constants and returns the (first) constant that refers to the passed object.

like image 82
Stefan Avatar answered Oct 22 '25 06:10

Stefan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!