# Suggestions for common/global data in app (cli)

**URL:** <https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450>\
**Category:** Ruby\
**Created:** [October 8, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450 "2008-10-08T19:00:06Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 8, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/1 "2008-10-08T19:00:06Z")

</div>

I am writing a (my first) client side ruby app. Many programs use the  
same data such as db login, logger etc. Is there a standard ruby way of  
doing this? Some suggestions would be useful.

- I have used YAML for config data for single scripts earlier
- I am aware of 'load’ing a ruby file which could have config data in  
it.
- A module with global constants

Would these files (yaml, load) have to loaded in each program?

Have I missed any approach? I have heard of global vars but never used.

I would appreciate a link to any ruby application best practices, too.  
Thanks.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 8, 2008, 7:45pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/2 "2008-10-08T19:45:16Z")

</div>

Nit K. wrote:

> Have I missed any approach? I have heard of global vars but never used.
> 
> I would appreciate a link to any ruby application best practices, too.  
> Thanks.

One suggestion (based on yaml):

[http://redshift.sourceforge.net/preferences/](http://redshift.sourceforge.net/preferences/)

It also provides a utility method to find the right user dir to store  
prefs in, based on env vars.

It may be overkill for a simple program though.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 8, 2008, 7:52pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/3 "2008-10-08T19:52:17Z")

</div>

Joel VanderWerf wrote:

> One suggestion (based on yaml):
> 
> [Preferences](http://redshift.sourceforge.net/preferences/)
> 
> It also provides a utility method to find the right user dir to store  
> prefs in, based on env vars.
> 
> It may be overkill for a simple program though.  
> Thanks, looks good. My app should become pretty large. I like the idea  
> of config being saved too (easily), so next execution takes the new  
> config.

Btw, I am aware of Configatron, too.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 8, 2008, 8:54pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/4 "2008-10-08T20:54:29Z")

</div>

Nit K. wrote:

> I am writing a (my first) client side ruby app. Many programs use the  
> same data such as db login, logger etc. Is there a standard ruby way of  
> doing this? Some suggestions would be useful.
> 
> - I have used YAML for config data for single scripts earlier

This is very common.

> - I am aware of 'load’ing a ruby file which could have config data in  
> it.
> - A module with global constants

That’s a possibility too.

> Would these files (yaml, load) have to loaded in each program?

Yes, assuming these programs are separate (e.g. separate commands  
invoked from the command line) as they will get a fresh Ruby interpreter  
instance.

> Have I missed any approach?

You may be able to combine this with the “dependency injection” pattern.  
This sounds complicated but is actually very simple.

Jim W. wrote an excellent depinj.rb which was published on  
[onestepback.org](http://onestepback.org); unfortunately he is in the process of reorganising his  
blog and the download is not currently available.

You basically write Ruby code to configure each of your objects:

container = DI::Container.new  
container.register(:db\_host) { “localhost” }  
container.register(:db\_user) { “root” }  
container.register(:db\_pass) { “xyzzy” }  
container.register(:db) { |c|  
DataBaseAdapter.new(c.db\_host, c.db\_user, c.db\_pass)  
}

When you first reference container.db then the database connection is  
instantiated for you. The nice thing is that all the interdependencies  
between objects is sorted out for you.

> I have heard of global vars but never used.

That would be just another way to refer to the loaded data. You could  
write:

require “yaml”  
$config = YAML.load(“/etc/myapp.conf”)

and then anywhere else in your program you could say

$config[“db\_user”]

or whatever.

Remember that YAML allows nesting, so you could have

db:  
host: localhost  
user: root  
pass: xyzzy  
logger:  
level: 2  
file: /var/log/stuff

then you could refer to $config[“db”][“host”] etc.

B.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 9, 2008, 5:42am UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/5 "2008-10-09T05:42:02Z")

</div>

Nit K. wrote:

> Brian C. wrote:
> 
> >

Thanks for the tip on dependency injection. Did some reading up last  
night - there’s [needle.soureforge.net](http://needle.soureforge.net) (based on Jim W), and also an  
article on onestepback:  
[http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc](http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc)  
.

Perhaps, not what I need at present, but good to know for the future.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 8, 2008, 9:06pm UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/6 "2008-10-08T21:06:46Z")

</div>

Brian C. wrote:

> > Would these files (yaml, load) have to loaded in each program?
> 
> Yes, assuming these programs are separate (e.g. separate commands  
> invoked from the command line) as they will get a fresh Ruby interpreter  
> instance.
> 
> > I have heard of global vars but never used.
> 
> That would be just another way to refer to the loaded data. You could  
> write:
> 
> require “yaml”  
> $config = YAML.load("/etc/myapp.conf")
> 
> and then anywhere else in your program you could say
> 
> $config[“db\_user”]

Small question. The app is not separate programs loaded from the command  
line. The main menu loads, then other classes available in other files  
are required and instantiated.

So there are many separate files, but one ruby interpreter. Will  
"$config[“XXX”] work through all the programs ? That seems fairly easy.  
Will look into dep inj soon - thanks for the tip.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 9, 2008, 6:15am UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/7 "2008-10-09T06:15:17Z")

</div>

On Oct 8, 2008, at 10:57 AM, Nit K. wrote:

> Would these files (yaml, load) have to loaded in each program?
> 
> Have I missed any approach? I have heard of global vars but never  
> used.
> 
> ## I would appreciate a link to any ruby application best practices, too. Thanks.
> 
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

gem install configuration

NAME  
configuration.rb

SYNOPSIS  
pure ruby scoped configuration files

DESCRIPTION  
configuration.rb provides a mechanism for configuring ruby programs  
with  
ruby configuration files. a configuration.rb file, for example  
‘config/app.rb’, can be written simply as

```
   Configuration.for('app'){
     key 'value'
     foo 'bar'
     port 42
   }

```

and loaded via the normal ruby require/load mechanism

```
   Kernel.load 'config/app.rb'

```

or with a slightly augmented loading mechnanism which simply  
searches an  
extra set of paths in _addition_ to the standard ones

```
   Configuration.path = %w( config configuration )

   Configuration.load 'app'

```

configurations are completely open

```
   Configuration.for('app'){
     object_id 'very open'
   }

```

support arbitrarily nested values

```
   Configuration.for('app'){
     a { b { c { d 42 } } }
   }

   c = Configuration.for 'app'

   p c.a.b.c.d #=> 42

```

allow POLS scoped lookup of vars

```
 Configuration.for('config'){
   outer 'bar'

   inner {
     value 42
   }
 }

 c = Configuration.for 'config'

 p c.outer #=> 'bar'
 p c.inner.value #=> 42
 p c.inner.outer #=> 'bar'

```

and not a whole lot else - configuration.rb is s very small library  
consisting of one file and \< 150 loc

SAMPLES

\<========\< samples/a.rb \>========\>

~ \> cat samples/a.rb

```
 #
 # basic usage is quite, simple, load the config and use it's

```

values. the  
# config syntax is fairly obvious, i think, but note that it _is_  
ruby and any  
# ruby can be included. also note that each config is named,  
allowing  
# multiple configs to be places in one file  
#  
require ‘configuration’

```
   c = Configuration.load 'a'

   p c.a + c.b - c.c

```

~ \> cat config/a.rb

```
 Configuration.for('a'){
   a 40
   b 4
   c 2
 }

```

~ \> ruby samples/a.rb

```
 42

```

\<========\< samples/b.rb \>========\>

~ \> cat samples/b.rb

```
 #
 # configuration.rb supports a very natural nesting syntax. note

```

how values  
# are scoped in a POLS fashion  
#  
require ‘configuration’

```
   c = Configuration.for 'b'

   p c.www.url
   p c.db.url
   p c.mail.url

```

~ \> cat config/b.rb

```
 Configuration.for('b'){
   host "codeforpeople.com"

   www {
     port 80
     url "http://#{ host }:#{ port }"
   }

   db {
     port 5342
     url "db://#{ host }:#{ port }"
   }

   mail {
     host "gmail.com"
     port 25
     url "mail://#{ host }:#{ port }"
   }
 }

```

~ \> ruby samples/b.rb

```
 "http://codeforpeople.com:80"
 "db://codeforpeople.com:5342"
 "mail://gmail.com:25"

```

\<========\< samples/c.rb \>========\>

~ \> cat samples/c.rb

```
 #
 # configuration.rb let's you keep code very dry.
 #

   require 'configuration'

   Configuration.load 'c'

   p Configuration.for('development').db
   p Configuration.for('production').db
   p Configuration.for('testing').db

```

~ \> cat config/c.rb

```
 %w( development production testing ).each do |environment|

   Configuration.for(environment){
     adapter "sqlite3"
     db "db/#{ environment }"
   }

 end

```

~ \> ruby samples/c.rb

```
 "db/development"
 "db/production"
 "db/testing"

```

\<========\< samples/d.rb \>========\>

~ \> cat samples/d.rb

```
 #
 # configuration.rb makes use of an external blank slate dsl, this

```

means that  
# you Configuration objects do, in fact, have all built-in ruby  
methods such  
# as #inspect, etc, _unless_ you configure over the top of them.  
the effect  
# is a configuration object that behaves like a nice ruby object,  
but which  
# allows _any_ key to be configured  
#  
require ‘configuration’

```
   c = Configuration.for 'd'

   p c.object_id
   p c.inspect
   p c.p

```

~ \> cat config/d.rb

```
 Configuration.for('d'){
   object_id 42
   inspect 'forty-two'
   p 42.0
 }

```

~ \> ruby samples/d.rb

```
 42
 "forty-two"
 42.0

```

\<========\< samples/e.rb \>========\>

~ \> cat samples/e.rb

```
 #
 # configuration.rb uses a totally clean slate dsl for the block.

```

if you need  
# to access base Object methods you can do this  
#

```
   require 'configuration'

   c = Configuration.for 'e'

   p c.foo
   p c.bar
   p c.foobar

```

~ \> cat config/e.rb

```
 Configuration.for('e'){
   foo 42

   if Send('respond_to?', 'foo')
     bar 'forty-two'
   end

   respond_to = Method('bar')

   if respond_to.call('bar')
     foobar 42.0
   end
 }

```

~ \> ruby samples/e.rb

```
 42
 "forty-two"
 42.0

```

AUTHOR  
removed\_email\_address@domain.invalid

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [October 9, 2008, 10:09am UTC](https://www.ruby-forum.com/t/suggestions-for-common-global-data-in-app-cli/150450/8 "2008-10-09T10:09:15Z")

</div>

Nit K. wrote:

> Small question. The app is not separate programs loaded from the command  
> line. The main menu loads, then other classes available in other files  
> are required and instantiated.
> 
> So there are many separate files, but one ruby interpreter. Will  
> "$config[“XXX”] work through all the programs ?

Yes. Your apps will be written in such a way that they’re somewhat tied  
to the global data structure, but if there’s no intention of re-using  
the component objects elsewhere that’s no problem.

Otherwise you could do something like this:

[config file]  
thing1:  
x: abc  
y: def  
thing2:  
a: xyz  
b: tuv

[library]  
class Thing1  
def initialize(params)  
x = params[“x”]  
y = params[“y”]  
end  
end

[initialisation]  
$config = YAML.load("/etc/myapp.conf")  
o1 = Thing1.new($config[“thing1”])

You can of course put object instances in global variables too. They can  
be named:

$logger ||= Logger.new(…)

Or you can use the “object locator” pattern, which is a fancy way of  
saying an object containing the other objects.

$locator ||= {}  
$locator[:logger] ||= Logger.new(…)

Taking this one step further you get to dep inj, since creation of each  
object can make use of other objects in the container.

> Will look into dep inj soon - thanks for the tip.

I see you already found the page. I had a copy of the code lying around,  
so I’ll attach it to this message.

Personally I’d load the $config and then use depinj to set up the  
individual objects. This code is very easy to re-use, since any objects  
in the container which you don’t access don’t get created.
