Venkat D.
Venkat D.

Reputation: 3029

Clean way in rails to have different behavior depending on the environment

I am looking for a clean way to have different behavior depending on whether we are in the test, development, staging, or production environment.

My question is general but the best specific example I have is sending notifications. Let's say I have a function in my User model object called notify

def notify(message)
  #send a notification to the user (differs depending on the environment)
end

In the test environment I would like to use a mock object that just saves the notifications to a file. In the staging and production environments I would like to use a PushNotification object which actually sends API requests to a third party service. I need to use a different api key for each environment.

I was thinking I would create a folder at lib/notifiers and create a file_notifier.rb and a push_notifier.rb. I don't know where (what files) and how I would initialize the right notifier. Any ideas?

Thanks!

Upvotes: 0

Views: 166

Answers (1)

coreyward
coreyward

Reputation: 80140

For starters, I'm going to be a bit of a whiny bitch — you don't have a function, but a method. A method, you see, is invoked on a receiver object. Why does this matter? Because if you think hard about it, it reveals the culprit of the difficulty you're having:

A user object has no business toggling the output location of a "notification" object.

So the first step to solving your problem is to create an object that handles notifications and can be independently configured to behave appropriately based on the environment. Note that this object should not itself know about or care about the environment, but should be configurable such that you can easily mock it in development, which could happen either in your development.rb file or in an initializer (perhaps called configure_notifier.rb that will configure it for whichever environment).

As far as using different API keys, well, that's a separate issue entirely — you really don't want to store these in your repository, and the generally-accepted way of doing this is to configure the environment you're running in to maintain them. For Heroku, as a popular example, you could run heroku config:add SOMESERVICE_API_KEY=abcdefg12345 and then access this in your configuration via ENV['SOMESERVICE_API_KEY'].

Upvotes: 2

Related Questions