-1

My method takes an argument. I prefer to avoid directly passing the object like so:

def print_error(Loggers::MyLogger.new, error)
  ...
end

Instead, I would like to pass a symbol like so:

def print_error(:my_logger, error)
  ...
end

Is there an elegant way to convert :my_logger symbol into a MyLogger instance? Or do I have to build a factory mechanism for that?

sawa
  • 165,429
  • 45
  • 277
  • 381
Okiba
  • 219
  • 3
  • 13

3 Answers3

2

In Rails there is a helper ready for that constantize:

:my_logger.to_s.camelize.constantize
#⇒ MyLogger

In Ruby one might do it using Module#const_get:

klazz = :my_logger.to_s.gsub(/(\A|_)(.)/) { |m| m[-1].upcase }
const_get(klazz) if const_defined?(klazz)
#⇒ MyLogger
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • 2
    What is the reason for looking up the constant in `Kernel` instead of, say, `Object` or the current scope or the `Logger` module? – Jörg W Mittag May 19 '16 at 10:24
  • @JörgWMittag No reason, I just put it for clarity. If you think it messes things up, I will remove it. – Aleksei Matiushkin May 19 '16 at 10:25
  • You should remove the Rails part. The OP is asking for a non-Rails solution (and it doesn't work anyway). – Stefan May 19 '16 at 10:30
  • @Stefan what exactly does not work? I think that `Inflector` might be used in non-rails projects, and it is a good reference to take a look at how it was implemented. – Aleksei Matiushkin May 19 '16 at 10:44
  • Thank you mudasobwa, It work :-) (at least the Ruby method of doing so, I don't use rails do I wasn't able to test `constantize`). – Okiba May 19 '16 at 11:31
  • @mudasobwa `constantize` expects a proper constant name, it doesn't automatically convert to camel case. – Stefan May 19 '16 at 11:51
  • @Stefan indeed, thanks, updated. I decided to leave the [corrected] rails answer as well for the sake of consistency for the future visitors who might be interested in rails way as well. – Aleksei Matiushkin May 21 '16 at 04:38
1

First, we transform :my_logger into a string "MyLogger" (ref : Converting string from snake_case to CamelCase in Ruby ) :

camel_str = :my_logger.to_s.camelize  

Then we use the string with the name of the class to create the object (ref : How do I create a class instance from a string name in ruby? ):

obj = Object.const_get(camel_str)

So putting everything together :

camel_str = :my_logger.to_s.camelize  
obj = Object.const_get(camel_str)
Community
  • 1
  • 1
Pholochtairze
  • 1,836
  • 1
  • 14
  • 18
-1

Well, if it's about converting a symbol into it's corresponding class (if exists!), how about this one:

class Symbol
  def to_ob
    eval(self.to_s)
  end
end

:String.to_ob        #=>String
Mash97
  • 1
  • 1