Giter Club home page Giter Club logo

app_config's Introduction

AppConfig Build Status Donate

An easy to use, customizable library to easily store and retrieve application configuration; basically anything in 'key/value' pairs.

AppConfig requires at least Ruby 1.9.

Usage

Usage is simple. Just pass either a hash of options, or a block, to AppConfig.setup!.

In it's simplest form, you can use it like so:

AppConfig.setup!(admin_email: '[email protected]')
# ..or..
AppConfig.setup! do |config|
  config.admin_email = '[email protected]'
end

AppConfig.admin_email  # => '[email protected]'

AppConfig also supports many different 'storage methods', such as YAML and MongoDB, allowing you to tailor AppConfig to many different use cases. For example, storing your configuration in the same database as your development/production environment.

YAML

Given this YAML file:

---
admin_email: '[email protected]'
api_name:    'Supr Webz 2.0'
api_key:     'SUPERAWESOMESERVICE'

Use it like so:

AppConfig.setup!(yaml: '/path/to/app_config.yml')

# Later on...
AppConfig.admin_email  # => '[email protected]'
AppConfig.api_name     # => 'Supr Webz 2.0'
AppConfig.api_key      # => 'SUPERAWESOMESERVICE'

Mongo

You can pass a :mongo options hash to AppConfig.setup! which should contain configuration values for a Mongo database. Check the AppConfig::Storage::Mongo::DEFAULTS constant for the default Mongo connection options.

The 'mongo' gem is required in order to use Mongo storage.

# These are the defaults.
mongo_opts = {
  host:       'localhost',
  database:   'app_config',
  collection: 'app_config'
}

AppConfig.setup!(mongo: mongo_opts)

AppConfig.admin_email  # => '[email protected]'

# Override an existing value and save to the database:
AppConfig.admin_email = '[email protected]'
AppConfig.save!

The values are read/saved (by default) to the app_config database and app_config collection. These defaults can be overridden, however, which might lend well to versioned configurations; collection names such as app_config_v1, app_config_v2, etc.

AppConfig.setup!(mongo: { collection: 'app_config_v2' })

PostgreSQL

Using PostgreSQL is similar to a Mongo setup. The only current requirement is that the table have a primary key named id. All other columns are used as configuration keys.

The 'pg' gem is required in order to use Postgres storage.

Note: The database and schema must exist prior to calling AppConfig.setup!.

Given this schema:

CREATE TABLE app_config (
  id bigserial NOT NULL PRIMARY KEY,
  admin_email character varying(255) DEFAULT '[email protected]'::character varying,
  api_key character varying(255) DEFAULT 'SOME_API_KEY'::character varying
);

Setup AppConfig:

# These are the defaults.
postgres_opts = {
  host:     'localhost',
  port:     5432,
  dbname:   'app_config',
  table:    'app_config',

  # If these are nil (or omitted), the PostgreSQL defaults will be used.
  user:     nil,
  password: nil,
}

AppConfig.setup!(postgres: postgres_opts)

AppConfig.admin_email  # => '[email protected]'

# Override an existing value and save to the database:
AppConfig.admin_email = '[email protected]'
AppConfig.save!

MySQL

Using MySQL is similar to Postgres, including the required primary key named id. All other columns are used as configuration keys.

The 'mysql2' gem is required in order to use MySQL storage.

Note: The database and schema must exist prior to calling AppConfig.setup!.

Given this schema:

CREATE TABLE app_config (
 id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
 admin_email VARCHAR(255) DEFAULT "[email protected]",
 api_key VARCHAR(255) DEFAULT "SOME_API_KEY",
 true_option BOOLEAN DEFAULT true,
 false_option BOOLEAN DEFAULT false
);

Setup AppConfig:

# These are the defaults:
mysql_opts = {
  host: 'localhost',
  port: 3306,
  database: 'app_config',
  table: 'app_config',
  username: nil,
  password: nil,
}

AppConfig.setup!(mysql: mysql_opts)

AppConfig.admin_email  # => '[email protected]'

# Update an existing value and save changes:
AppConfig.admin_email = '[email protected]'
AppConfig.save!

SQLite

SQLite storage works the same as the other SQL storage methods, including the mandatory primary key id column.

The 'sqlite3' gem is required in order to use SQLite storage.

Note: The database schema must exist prior to calling AppConfig.setup!.

# These are the defaults:
sqlite_opts = {
  database: File.join(Dir.home, '.app_config.sqlite3'),
  table: 'app_config',
}

AppConfig.setup!(sqlite: sqlite_opts)

Using Storage Defaults

All storage options accept true as a value, which uses the default options for that storage.

For example, to use the Mongo defaults:

AppConfig.setup!(mongo: true)

Storage Defaults

Environment Mode

The YAML storage method provides an :env option where you can organize the config like Rails database.yml:

# Rails.root/config/app_config.yml
development:
  title: 'Development Mode'

production:
  title: 'Production Mode'

Pass a string or symbol to the :env option.

# Rails.root/config/initializers/app_config.rb
AppConfig.setup!({
  yaml: "#{Rails.root}/config/app_config.yml",
  env: Rails.env
})

# Uses the given environment section of the config.
AppConfig.title  # => 'Production Mode'

Deprecation Note

Version 2.x is not backwards compatible with the 1.x branch.

See the wiki for current usage instructions.

app_config's People

Contributors

dependabot[bot] avatar dzhlobo avatar mhfs avatar oshuma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

app_config's Issues

OStruct like access

given a setting: some_key

Instead of AppConfig[:some_key] I'd like to be able to access it as AppConfig.some_key

For AppConfig[:location][:city] I'd like to be able to access it as AppConfig.location.city

What do you think?

AppConfig.reset!

Should clear out the options (basically undo AppConfig.setup).

Bug: Allow ' in the values in the postgres backend (sqli)

Seeing this:

set_attrs = data_hash.map { |k, v| "#{k} = '#{v}'" }.join(', ')
save_query = "UPDATE #{@table} SET #{set_attrs} WHERE id = #{@id}"
else # Creating a new row.
if data_hash.empty?
save_query = "INSERT INTO #{@table} DEFAULT VALUES"
else
columns = data_hash.keys.join(', ')
values = data_hash.map { |_, v| "'#{v}'" }.join(', ')
save_query = "INSERT INTO #{@table} (#{columns}) VALUES (#{values})"

I know end-user input is not expected to be stored in a configuration backend, but the code as it stands is classic SQL injection.

This might be relevant: http://deveiate.org/code/pg/PG/Connection.html#method-c-escape_string

No access by symbols

Input:

require "app_config"

config = AppConfig.setup do |config|
  config[:first] = 1
  config[:name] = "NAME"
end

p config[:first], config[:name]
p config["first"], config["name"]
p config.first, config.name

Ouput:

nil
nil
1
"NAME"
./config.rb:13:in `<main>': undefined method `name' for {"first"=>1, "name"=>"NAME"}:Hash (NoMethodError)

I'd like to access values by symbols and strings. You implemented this in your class Hashish, right? I tested it and it was correct, but if I use your class AppConfig I don't have access by symbols.

What is my problem? Thank's for help.

Multiple Storage Engines

I'd like to implement a feature on app_config that allows multiple storage engines. So I could define any number of yaml, mongo, or memory settings.

The trick here is the deep merge. It should work with deeply embedded configuration options and merge settings properly.

I'll spec out the feature first before implementing.

License missing from gemspec

Some companies will only use gems with a certain license.
The canonical and easy way to check is via the gemspec,

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Even for projects that already specify a license, including a license in your gemspec is a good practice, since it is easily
discoverable there without having to check the readme or for a license file. For example, it is the field that rubygems.org uses to display a gem's license.

For example, there is a License Finder gem to help companies ensure all gems they use
meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough
issue that even Bundler now generates gems with a default 'MIT' license.

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), github has created a license picker tool.

In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :).

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue and let me know. In either case, I'll follow up. Thanks!

p.s. I've written a blog post about this project

When writing to initially NULL value, PG::Error is thrown.

In this example, AppConfig has been setup with the Postgres defaults and a column named api_key however, there are currently no rows in the configured database.

irb(main):004:0> AppConfig.api_key
=> nil
irb(main):006:0> AppConfig.api_key = 'foobar'
=> "foobar"
irb(main):007:0> AppConfig.save!
PG::Error: ERROR:  syntax error at or near "WHERE"
LINE 1: UPDATE app_config SET  WHERE id =
                               ^

This is happening because the initial call to fetch_data! returns no results.

Recursively create sub config keys

Only top-level keys get saved. Currently, this doesn't work:

config[:database][:user] = 'luser'

Doesn't create the embedded hash/array.

Can't set array value

When setting a variable to an array like this:

AppConfig.BLACKLIST = ['foo', 'bar']

I get the following error:

lib/ruby/2.1.0/ostruct.rb:170:in `block in new_ostruct_member'
app_config-2.5.3/lib/app_config/storage/base.rb:17:in `method_missing'
app_config-2.5.3/lib/app_config.rb:66:in `method_missing'

Happens in base.rb#17.

Setting a non-array value AppConfig.BLACKLIST= 'foo' does not give an error, but obviously does the wrong thing.

Feature: Rails3 Support

AppConfig rocks! I'd like to provide better support with Rails (not a dependency, just provide support if Rails exists)

  • Add Railtie to automatically load config/app_config.yml and config/app_config/#{Rails.env}.yml
  • Add rails generator to create an app_config.yml

This will all be in a railtie so if Rails3 isnt being used, it wont be loaded in. No rails3 gem dependencies will need to be added to app_config.

I can help maintain the fixes. I'm currently changing my own app_config plugin to use yours (http://github.com/railsjedi/app_config/tree/old)

Just want to make sure this fix is welcome. Are you cool with it?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.