Reading in variables from a file in Ruby

It sounds like you should provide a file example for the user/admin to modify for their personal environment, and then populate the environment from that, while avoiding, perhaps, having that file with the sensitive information in a repository. Note: per file security is going to be addressed by where the file is located and your operating system, and server software.

If this is the case, then you can provide a file that holds a template of the kind of things that you would require from the administrator/user of the program you are configuring.

Ruby has the ENV constant that acts like a Hash and holds the environment of the shell you are using.

As an example, there is a file called environment.rb.sample that gets shared with anyone, publicly. It has instructions and holds the template that users can modify freely, with instructions to copy the file to environment.rb. The sample file looks like this:

# environment.rb.sample
# Copy this file to environment.rb and change the name and password to your credentials
ENV['temp_user_name'] = 'Foo Bar'
ENV['temp_password'] = 'Dazz Kezz

The file is then copied to this, perhaps:

# environment.rb
ENV['temp_user_name'] = 'Joe Admin'
ENV['temp_password'] = 'Super Secure Password'

The file that loads this and uses it is just a Ruby file that is freely modified by the user/administrator of the software, and looks like this and is also shared publicly.

# load_environment
require './environment'
puts ENV['temp_user_name']
puts ENV['temp_password']

This loads the file and uses the ENV that is a globally scoped constant for the application.

The file permissions are then managed by the user/administrator of the system and secured like any other sensitive information on their system. The sensitive file should also be listed in the repository's ignore mechanism. It should never be made public.


Yes, there is, and if for some bizzare, arcane reason you must use it, it's eval:

WARNING: Never use this on a user-supplied file

And, unless you have a very, very specific need, don't use it in production code.

eval(File.read("name_of_var_file"), binding)

If what you're really trying to do is write a configuration file, use YAML. A file like this:

config.yaml:

foo: "bar"

Can be accessed like this:

require 'yaml'
conf = YAML.loads(File.read("config.yaml"))
conf['foo'] #=> 'bar'

This is secure and manageable, not to mention standard practice.


As for making the file inaccessible, that is an operating system level problem that can't be solved without information on the environment, OS, setup, etc.


The purpose of a local variable is to be used temporally within a method definition or a block. Using it outside of such environments, particularly across files defeats the purpose of it. You should not need to do it, and Ruby does not have a simple way to do it.

If you are using variables correctly, and want to share variables between files, that should be other types of variables such as instance, class, or global variables. Or, for the purpose of setting environments, you should be using constants. Among them, global variables and constants can be written in a file, loaded in a different file, and be used.

file-a.rb

$foo = 1
FOO = 2

file-b.rb

load "file-a.rb"
$foo # => 1
FOO # => 2

As for instance and class variables, they belong to a class or an instance of it, so they should be defined in such environment. And you can reopen the same class within a different file, and load it in another file.

file-a.rb

class Bar
  @@foo = 1
  def initialize; @foo = 2 end
end

file-b.rb

load "file-a.rb"
Bar.class_variable_get("@@foo") # => 1
Bar.new.instance_variable_get("@foo") # => 2