Reputation: 2804
Our application uses a number of environments so we can experiment with settings without breaking things. In a typical controller action, I have something like this:
def some_action
...
if @foo.development_mode == 'Production'
@settings = SomeHelper::Production.lan(bar)
elsif @foo.development_mode == 'Beta'
@settings = SomeHelper::Beta.lan(nas)
elsif @foo.development_mode == 'Experimental'
@settings = SomeHelper::Experimental.lan(nas)
end
...
end
Since we have dozens of these, I figured I could try and dry things up with something like this:
@settings = "SomeHelper::#{@foo.development_mode}.lan(bar)"
Which obviously doesn't work - I just get:
"NasHelper::Production.lan(bar)"
How can I reduce this down or do I have to stick with what I've got??
Upvotes: 1
Views: 91
Reputation: 4471
If your concern is that you're ending up with a String rather than the object, you can use String.constantize
(Rails only, with standard Ruby you'd have to implement this; it uses Object.const_get(String))
Another option would be .const_get
(e.g. Object.const_get(x)
where x is your string), you it doesn't, on its own, nest correctly, so you would have to split at "::", etc.
Also, there's the option of using eval
to evaluate the String.
But note: eval
should be used with great care (it's powerful), or not at all.
Edit:
This means that instead of:
@settings = "SomeHelper::#{@foo.development_mode}.lan(bar)"
You could run:
@settings = "SomeHelper::#{@foo.development_mode}".constantize.lan(bar)
Useful Sources:
http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize
http://www.ruby-forum.com/topic/183112
http://blog.grayproductions.net/articles/eval_isnt_quite_pure_evil
Upvotes: 1
Reputation: 14018
In the first case, @settings
receives the result of the method SomeHelper::Production.lan(bar)
; in the second, @settings
just gets a string. You could use the send
method of Object
linked here to fire the method, or eval
, but this wouldn't be my first choice.
It looks like you might be reinventing a wheel -- Rails already has the concept of "environments" pretty well wired into everything -- they are defined in app/config/environments
. You set the environment when you launch the server, and can test like Rails.env.production?
. To create new environments, just copy the existing environment file of the one closest to the new one, e.g. copy production.rb
to beta.rb
and edit as necessary, then test Rails.env.beta?
, for example.
But this still leaves you testing which one all over the place. You can add to the config
hash (e.g. config.some_helper.lan = 'bar'
), which value you can assign to @settings
directly. You have to make sure there's either a default or it's defined in all environments, but I think this is probably the right approach ... not knowing exactly what you aim to accomplish.
Upvotes: 0