views:

254

answers:

6

If I have some config for web admin to set e.g. number of post per page, some enum showing choice. How should I keep this settings in db ? Should I serialize it and save as blob.

Thanks,


I using rails and I want it to dynamically change this setting through web interface, so I think environment.rb would not fit this situation. So I should have a extra table with two tuples as name, value ?

A: 

If you are using asp.net you can use the Web.Config file.

See Asp .net Web.config Configuration File

astander
A: 

You could to create a single table in your database to store key-value pairs.

Rubens Farias
+1  A: 

Most languages/frameworks have a config file of sorts. such as the web.config in ASP or the environment.rb files in RoR. You could use one of these.

Or failing that have a key value pair table in your database.

If you're wanting to do this dynamically through the website I would definitely go for the key value pair table.

mjmcloug
+1  A: 

For the dynamic config values, you should create a model called Configuration with keys and values. I generally have multiple value columns (for number, string, and date) and then call the appropriate method for the configuration.

For "enums" you should create lookup tables with foreign key relationships to where they attach. For example if you have a Post model and you want an enumeration of Category, you should make the Post belong_to :category and Category has_many :posts.

MattMcKnight
+1  A: 

Use a YAML file. YAML is way simpler than XML.

Make a file called "config.yml" in "config" directory. And load the file using YAML::load(). You can make a setting for each environment by naming the first level as environment (e.g., production, development, test).

See this episode of RailsCasts for details.

TK
A: 

This is what I use. Got the idea from elsewhere, but the implementation is mine. Pulled from a production project of mine:

class AppConfig
  # Loads a YAML configuration file from RAILS_ROOT/config/. The default file
  # it looks for is 'application.yml', although if this doesn't match your
  # application, you can pass in an alternative value as an argument 
  # to AppConfig.load.
  # After the file has been loaded, any inline ERB is evaluated and unserialized
  # into a hash. For each key-value pair in the hash, class getter and setter methods
  # are defined i.e., AppConfig.key => "value" 
  # This allows you to store your application configuration information e.g., API keys and 
  # authentication credentials in a convenient manner, external to your application source
  #
  # application.yml example
  #
  # :defaults: &defaults
  #  :app_name: Platform
  #  :app_domain: dev.example.com
  #  :admin_email: [email protected]
  # :development:
  #  <<: *defaults
  # :test:
  #  <<: *defaults
  # :production:
  #  <<: *defaults
  #  :app_domain: example.com
  #
  # For example will result in AppConfig.app_domain => "dev.example.com"
  # when Rails.env == "development" 
  #

  class << self
    def load(file='application.yml')
      configuration_file = File.join Rails.root, 'config', file
      File.open(configuration_file) do |configuration|
        configuration = ERB.new(configuration.read).result
        configuration = YAML.load(configuration)[Rails.env.to_sym]
        configuration.each do |key, value|
          cattr_accessor key
          send "#{key}=", value
        end
      end if File.exists? configuration_file
    end
  end
end
AppConfig.load

Create config/initializers/app_config.rb and paste the above code into it. I'm going to make this into a gem. I figure other people will find it useful.

EDIT: Just saw you wish to edit the config as the app runs via a web based interface. You could do this with this method as both getter and setter methods are defined for each attribute.

in your controller:

def update
  params[:configuration].each { |k,v| AppConfig.send "#{k}=", v }
  …
end

I don't find a model is the right solution here. Forget about the DB overheard, the idea of being able to instantiate something that controls app configuration doesn't make sense. What's more how you implement it? An instance for each tuple?! It should be a singleton class.

Steve Graham