Skip to content
jorgefuertes edited this page Mar 14, 2013 · 1 revision

Yaml configurations from padrino

How to have our own yaml files containing aplication-wide values to be used from controllers or templates.

Yaml config files example

Any files with the needed data:

/project/config/my_main_config.yml

main:
    enterprise:
        name: War Games Limited
        tax_id: X01020304
        phone: 34-555-112233
        address: Camino del Cedro Alto, SN
        city: Ghost's Island
        state: Oregon
    contact:
        sender: [email protected]
        email:  [email protected]

/project/config/my_other_config.yml

web:
    author: [email protected]
    keywords: 'Falken, Maze, IA, computers, war, tic-tac-toe'
    description: 'The better Falken's Mazes all over the World!'

Loading it at Padrino's start

We want these files being readed only at once, at the padrino's start.

/project/config/apps.rb

Padrino.configure_apps do
    ...
    begin
        logger.info "Opening: #{Padrino.root}/config/my_main_config.yml"
        set :mainConfigYml, YAML::load(File.open("#{Padrino.root}/config/main.yml"))["main"]
        logger.info "Opening: #{Padrino.root}/config/my_other_config.yml"
        set :webConfigYml, YAML::load(File.open("#{Padrino.root}/config/my_other_config.yml"))["web"]
    rescue
        logger.fatal "ERROR: Cannot open config files!"
        exit
    end
    ...
end

Padrino reads it for every mounted app... ToDo: Read only one time, work for all apps, or read only for an app.

A helper to read nodes:

/project/Myapp/helpers/front_helper.rb

Myapp.helpers do
  def config_get(path)
    if !path.match /^\/(main|web).*/
      logger.fatal "Config path must start with /main or /web"
      error 500, "Config path must start with /main or /web!"
    else
      if path.match /^(\/[[:alnum:]\-\_\.]{1,32}){1,10}$/
        logger.info "Getting config path: " + path
        partial_config = nil
        for node in path.split('/').each do
          if node.length > 0
            if partial_config.nil?
              if node == "web"
                partial_config = @webConfig
              elsif node == "main"
                partial_config = @mainConfig
              end
            else
              if partial_config[node].nil?
                logger.fatal "Undefined node '" + node + "' in path '" + path + "'"
                error 500, "Undefined node!"
              else
                partial_config = partial_config[node]
              end
            end
          end
        end
        logger.info "ConfigPath '" + path + "' --> '" + partial_config.to_s + "'"
        return partial_config.to_s
      else
        logger.fatal "Invalid config path: " + path
        error 500, "Invalid config path!"
      end
    end
  end
end

I'm new to ruby, new to Padrino and Sinatra, I think this code can be maded very better, but now works.

Front controller BEFORE

Pass it on front controler, filter if needed, based on hostname o request parameters, for example. To pass it as is:

/project/myapp/controllers/front.rb

Shop.controllers :front do
  before do
    ...
    @webConfig = settings.webConfigYml
    @mainConfig = settings.mainConfigYml
    ...
  end
...

Use it from helper

/project/myapp/views/index.haml

%h1= config_get '/main/enterprise/name'
%h2  Call us at: #{config_get '/main/enterprise/phone'}
%h2  Or send mail to: #{config_get '/main/contact/email'}

Other example, in your main layout:

!!! 5
%html
  %head
    %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
    %meta{:author => "#{config_get '/main/enterprise/name'}"}
    %meta{:keywords => "#{config_get '/web/keywords'}"}
    %meta{:description => "#{config_get '/web/description'}"}
    %title= config_get '/web/title'

That's all. I hope you enjoy and please, give me any idea to improve it.