palkan / anyway_config

Configuration library for Ruby gems and applications
MIT License
778 stars 52 forks source link

local files not loaded in rake task #57

Closed AxelTheGerman closed 4 years ago

AxelTheGerman commented 4 years ago

By getting all details for this bug report I actually found the solution MyConfig.reload so maybe this is more of a documentation issue than functionality. But I was hoping that this would work out of the box in rake tasks.

What did you do?

I created a config class, i.e. StripeConfig and a local config file, i.e. config/stripe.local.yml containing product_id: prod_123.

Then I have a rake task to create a couple of available payment plans.

What did you expect to happen?

Rake task should be able to create plans for product with ID from the local config file.

What actually happened?

StripeConfig.product_id is nil and the rake task could not create plans for a product without an ID.

Additional context

I know that Anyway::Settings.use_local_files is only true in development/test environment. And it seems that neither RAILS_ENV nor RACK_ENV are set when I run my rake task.

Running the rake task with rails my_task or rake my_task didn't make any difference.

Running the rake task with RAILS_ENV=development rails my_task works.

Setting Anyway::Settings.use_local_files = true in my task, makes StripeConfig.new.product_id work but not StripeConfig.product_id. I don't mind setting use_local_files = true but maybe it's worth pointing out that users might want to StripeConfig.reload their config for this change to take affect. I can see this getting annoying with multiple configs too.

Environment

Ruby Version: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]

Framework Version (Rails, whatever): Rails 6.0.2.2

Anyway Config Version: 2.0.1

palkan commented 4 years ago

Setting Anyway::Settings.use_local_files = true in my task, makes StripeConfig.new.product_id work but not StripeConfig.product_id

It seems that the singleton config instance is loaded before you set the use_local_files option.

Running the rake task with RAILS_ENV=development rails my_task works.

I think, that should be the way of doing this. We need to add a note about that to the docs.

Alternatively, setting ENV["RAILS_ENV"] ||= "development" in the Rakefile should help (though I'm not sure about possible side effects).

Another idea is to allow enabling local files via the special env, say, ANYWAY_LOCAL=true. WDYT?

AxelTheGerman commented 4 years ago

Thanks for looking into this so quickly, great job on the gem btw - provides much needed convention on how to use Rails credentials etc (plus combines transparently with plain old yml config)

I thought a bit more about it and I agree, running it with RAILS_ENV=development seems to be the way to go. Seems more like a bug in rails/rake actually that it doesn't set it automatically where as rails c and rails s does. I am using task my_task: :environment so it does load the rails environment.

ENV["RAILS_ENV"] ||= "development" in the rake task would probably work too.

If I already need to provide an env then I'd rather specify the RAILS_ENV in this case. Not sure for use cases for ANYWAY_LOCAL.

Is Anyway::Settings.use_local_files = true documented and would there be a way to reload the singleton instances automatically? Probably not...

Again I see nothing wrong with ENV["RAILS_ENV"] ||= "development" (yet)

palkan commented 4 years ago

Is Anyway::Settings.use_local_files = true documented

Yeah, we have this:

Local configs are meant for using in development and only loaded if Anyway::Settings.use_local_files is true (which is true by default if RACK_ENV or RAILS_ENV env variable is equal to "development").

would there be a way to reload the singleton instances automatically? Probably not...

In theory, we can do that (doing something like ApplicationConfig.ancestors.map(&:instance).each(&:reload)) but that would likely bring more problems than benefits.