<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>RealityForge.org: Flexible Application Configuration in Rails</title>
    <link>/articles/2006/02/28/flexible-application-configuration-in-rails</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>A little short for a storm trooper</description>
    <item>
      <title>Flexible Application Configuration in Rails</title>
      <description>&lt;p&gt;Most of my rails application have required some form of application specific configuration. When the configuration varies depending on where I deploy it I prefer to externalize the configuration in a &lt;span class="caps"&gt;YAML&lt;/span&gt; file similar to the way database configuration is handled.&lt;/p&gt;


	&lt;p&gt;I remember reading a blog somewhere that suggested the use of &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/ostruct/rdoc/classes/OpenStruct.html"&gt;OpenStruct&lt;/a&gt; and have since started using the following code placed at the bottom of my &lt;code&gt;config/environment.rb&lt;/code&gt; file.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;ostruct&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;yaml&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="constant"&gt;ConfigFile&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{RAILS_ROOT}&lt;/span&gt;/config/config.yml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exist?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;ConfigFile&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
 &lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OpenStruct&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;YAML&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_file&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;ConfigFile&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Consider the scenario where &lt;code&gt;config/config.yml&lt;/code&gt; contains;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="key"&gt;proxy_config&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
  &lt;span class="key"&gt;host&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; proxy.cs.latrobe.edu.au
  &lt;span class="key"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 8080&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I could then access the the configuration data using&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;proxy_config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;host&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; 
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;proxy.cs.latrobe.edu.au&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;proxy_config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;8080&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;To make your code more robust in the scenario where either the proxy configuration is missing or the whole configuration file is missing I generally add in extra guards. Below is an example of the code I use to instantiate a Net:HTTP object. If the configuration file is present and it contains a proxy_config section then the code will attempt to instantiate a Net::HTTP::Proxy object. Otherwise the code will instantiate a plain old Net::HTTP that will not attempt to go via a proxy server.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;http&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;Module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
      &lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;respond_to?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:proxy_config&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;host&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;proxy_config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;host&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
    &lt;span class="ident"&gt;port&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ApplicationConfig&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;proxy_config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
    &lt;span class="constant"&gt;Net&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HTTP&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Proxy&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;host&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="constant"&gt;Net&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HTTP&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 28 Feb 2006 21:37:00 +1100</pubDate>
      <guid isPermaLink="false">urn:uuid:9924932f-61de-49a9-8b08-ede10d6c4eb2</guid>
      <author>Peter Donald</author>
      <link>http://www.realityforge.org/articles/2006/02/28/flexible-application-configuration-in-rails</link>
      <category>Rails</category>
      <category>ruby</category>
      <category>rails</category>
      <category>configuration</category>
      <trackback:ping>http://www.realityforge.org/articles/trackback/27</trackback:ping>
    </item>
  </channel>
</rss>
