# Lessons learned from failing to access an environment variable in YMAL file

***Note: The following was tested with Ruby 2.6.6 / Rails 5.2.6.***

## Situation

I tried to add an environment variable in the `application.yml` file.

```yaml
# config/application.yml

default:
  #...
  API_TOKEN: ABC123456
```

And I expected when executing `ENV['API_TOKEN']` in Rails console, I would get `ABC123456`. But I got nil.

```ruby
$ rails console
$ ENV['API_TOKEN']
#=> nil
```

To see if I can figure out what's going on, I tried to do something below.

---

## Problem-solving process

* If we edit any files which were used to start the application, like configs or initializers, the application needs to be restarted. So, I thought that `reload!` in Rails console might reload the new code and solve this problem. However, I got the nil result the same.
    
* Next, I google the keyword: 'rails console nil ymal env'. Not a good keyword, but I got another important keyword: `spring stop`.
    

### What's Spring?

> Spring is a Rails application **preloader**. It speeds up development by keeping your application running in the background so you don't need to boot it every time you run a test, rake task or migration. ([Source](https://github.com/rails/spring/blob/master/README.md))

#### Spring's Feature

* Totally automatic; no need to explicitly start and stop the background process
    
* Reloads your application code on each run
    
* Restarts your application when configs / initializers / gem dependencies are changed
    

### What was the result I got in Rails console after executing `spring stop` ?

I succeeded in accessing the environment variable!

```ruby
# In the terminal
$ spring stop
#=> Spring stopped.

$ rails console
$ ENV['API_TOKEN']
#=> ABC123456
```

### So, why `spring stop` can solve this problem?

According to the Spring's README:

> But if we edit any of the files which were used to start the application (configs, initializers, your gemfile), the application needs to be fully restarted. **This happens automatically**.

After I change the config file, Spring should re-run. That means Spring will reload the application code.

But the result seemed not as I expected. Even though I have changed the YAML file and restarted Rails console, but Spring didn't re-run automatically. I guessed that Spring saw that my YMAL file didn't change.

So, I stopped Spring running first and then re-ran it by restarting Rails console.

We can check out the following block:

```ruby
$ spring stop
#=> Spring stopped.

$ bin/spring status
#=> Spring is not running.

$ rails console
#=> ...Running via Spring preloader in process 1182
#=> Loading development environment (Rails 5.2.6)
$ ENV['API_TOKEN']
#=> ABC123456
$ exit

$ bin/spring status
#=> Spring is running:

# 1171 spring server | backme | started 14 secs ago
# 1172 ruby -I /Users/yuchu/.rvm/rubies/ruby-2.6.6/lib/ruby/site_ruby/2.6.0 -I # /Users/yuchu/.rvm/gems/ruby-2.6.6/gems/spring-2.1.1/lib -e require 'spring/application/boot'
```

Rails console ran via Spring preloader and Spring started 14 secs ago. Spring has reloaded the application's newest code now.

I thought that was the exact reason why the environment variable `ENV['API_TOKEN']` could be accessed successfully.

---

### Reference

* [https://stackoverflow.com/questions/8686215/failing-to-access-environment-variables-within-database-yml-file](https://stackoverflow.com/questions/8686215/failing-to-access-environment-variables-within-database-yml-file?ref=lynnbright.com)
    
* [https://ithelp.ithome.com.tw/articles/10223709](https://ithelp.ithome.com.tw/articles/10223709?ref=lynnbright.com)
    
* [https://github.com/rails/spring/blob/main/README.md](https://github.com/rails/spring/blob/main/README.md)
