I'm trying to understand how the Rails 'rack-mini-profiler' actually dumps out environment variables when you append the ?pp=env on the base URL of a request. Right now my Gemfile has the gem 'dotenv-rails configured and I'm using .env.local to populate some test variables. My question is, where is the rack-mini-profiler getting the environment variables from? There are many different ways to populate env variables within a rails app, dotenv being one of them. I've been perusing the source code of rack-mini-profiler and can't seem to find it. I see the dump_env function in 'profiler.rb' but I can't see where or how these environment variables are getting pulled from within the code. It is only showing the printing of them by using a do loop of key/value pairs. Here is the example application I'm playing with and you can see the environment variables at this URL: https://preprod.rtcfingroup.com/?pp=env
Appreciate any insight. Really trying to understand this at a low level.
Miniprofiler does not actually have do anything since Ruby exposes the environmental variables through the ENV constant which is a hash like class.
dump_env just iterates over them:
body << "\n\nEnvironment\n---------------\n"
ENV.each do |k, v|
body << "#{k}: #{v}\n"
end
Related
I need to implement a feature that sets some Env vars conditionally based on current environment(dev,test,prod). I know in rails this can be accomplished with rails.env. Is there a similar method for Ruby?
No, vanilla ruby doesn't have a concept of "environment". You will have to build this yourself. One simple way is to use an environment variable and read it.
For example, you can require a MYAPP_ENVIRONMENT environment variable. Then you read it with myapp_environment = ENV['MYAPP_ENVIRONMENT']. Then you might have hashes or some other data structure to determine values that are specific to that environment:
ENDPOINT_A = {
prod: 'https://prod.my_company.com',
stage: 'https://stage.my_company.com'
}
Similarly for other variables. Note that the endpoint string is a ruby variable, not an environment variable. You should NOT set environment variables from the ruby code that uses them. The whole point of environment variables is that they are set externally to your app and your app takes them as input to configure how it behaves.
If you want to specify the endpoint through an environment variable, you should set it in the operating system where your ruby app runs. You can do this manually on the machine or through a deployment pipeline or script.
Question
There are many ways to achieve that goal but I would like to know what is the best way to tests the presence of the environmental variables inside a Ruby on Rails project.
Context
We recently had a production issue related to a missing environment variable in one of our Rails project.
To prevent this from happening again, I would like to test the presence of the environments variable in the application.yml configuration file.
I am using Ruby 2.5, Rails 4.2, Spring 2.
Unless checking this specifically in application.yml is an absolute requirement (why?), here is my take. Make a config/initializers/env.rb and put in there something like
%i[FOO BAR BAZ].each do |var|
ENV[var] = ENV.fetch(var)
end
What this does is reads all of your required environment variables (FOO, BAR, BAZ etc.) and Hash#fetch them which will 'raise' if this variable is not set at boot time.
I have an environment variable that I'm using in two places, one is in a rake task, the other is in a model method. When I call it from the rake task, everything is fine and the variable loads, but when I call it from the model it doesn't find anything. It's not a nil error or any other error, it just returns an empty string.
Is there any reason the environment variables would be overridden or inaccessible to the model?
It's being used to build a url:
http://#{AppEnv['env_var_1']}/this/is/#{AppEnv['env_var_2']}/a/path
--one more thing, myabe it's relevant, the model method is called after_create
EDIT:
thanks for the responses, but my question isn't how to access or use env vars, as you can see I'm already using them above. My question is why they are not loading in my model.
EDIT 2:
I have 4 relevant AppEnv variables, and [this is really weird so bear with me] when I check them on running the rake task (puts all 4 of them to the log), they are as expected. When I run the exact same class method, but called after_create in a model, 3 of the variables are empty, and one of them holds the value of a different variable. That is:
AppEnvVar1 is empty
AppEnvVar2 has the value of AppEnvVar4
AppEnvVar3 is empty
AppEnvVar4 is empty
If I change the method to self.method (allowing me to run it from the console), and run it, it works. So I'm pretty sure I've narrowed this down to an issue with the AppEnv during an after filter.
any ideas on where to dig?
Rails sets a global constant hash ENV that should be available anywhere in your app after it's initialized, including in your models. So you should be able to refer to any enviroment variable like this (assuming the relevant env variables has been set):
"http://#{ENV['ROOT_DOMAIN']}/this/is/#{ENV['SECONDARY_DOMAIN']}/a/path"
I restarted the server and everything worked fine. Mysterious...
I use the following code in one of my models
def jasper_amount
ActionController::Base.helpers.number_to_currency(amount)
end
I know that it breaks MVC. However, in this case it is the best solution. I have to pass data to Jasper via the Ruby Java Bridge and formatting in Jasper would be much more complicated.
Calling object.jasper_amount from the rails console works fine and prints the expected results. This works fine in development and production.
Now, to pass the data to Jasper I first have to create an xml version of the object's attributes using object.to_xml(methods: [:jasper_amount]).to_s This works in development but not in production. In production the value for jasper_amount that is passed to Jasper is "0.00 €". However, if I remove number_to_currency from def jasper_amount (just returning unformatted amount) it works. What's even more confusing is the fact that calling jasper_amount from the rails console in productions works. I guess the culprit must be to_xml, but I have no idea why it works in development and not in production.
The problem was with Ruby Java Bridge (rjb) and BigDecimal. If you use BigDecimal with rjb, you have to include the "BigDecimal" gem in your Gemfile. Otherwise all your BigDecimals will be 0 (and that all over your app!)
I have a rails 2.2.2 app. I'd like to be able to start the console by passing in a custom variable, which i can then retrieve inside my environment. Something like
#i start console like so
rails/console production -uid 1182
Then, anywhere in my code, i would be able to access this "uid" variable in the same sort of way that i can access ENV['HOME'] or things like that. (it doesn't need to be in ENV, just so long as i can access it reliably).
Anyone know how i can do this? thanks, max
Try this:
uid=1182 rails/console production
This way you set env variable, accessible from Ruby with:
ENV['uid']