rails_app_config 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2010 Jacques Crocker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+
23
+ Deep Merge (deep_merge.rb) code Copyright (c) 2008 Steve Midgley, released under the MIT license
data/README ADDED
@@ -0,0 +1,73 @@
1
+ == Summary
2
+ Application level configuration.
3
+
4
+ == Author
5
+ Jacques Crocker
6
+ Modified from Original Project (AppConfig by Christopher J. Bottaro)
7
+
8
+ === Compatibility
9
+ Rails 3.0
10
+
11
+ === Installing on Rails 3
12
+
13
+ add this to your Gemfile
14
+
15
+ gem "rails_app_config"
16
+
17
+ === Accessing the AppConfig object
18
+ After installing this plugin, the AppConfig object will be global available. Entries are accessed via object member notation:
19
+ AppConfig.my_config_entry
20
+ Nested entries are supported:
21
+ AppConfig.my_section.some_entry
22
+
23
+ === Common config file
24
+ Config entries are compiled from
25
+ config/app_config.yml
26
+ config/app_config/settings.yml
27
+ config/app_config/#{environment}.yml
28
+ config/environments/#{environment}.yml
29
+
30
+ settings defined in files that are lower in the list override settings higher
31
+
32
+ === Reloading config files
33
+ You can reload the AppConfig from file at any time by running AppConfig.reload!
34
+
35
+ === Environment specific config files
36
+ You can have environment specific config files. Environment specific config entries take precedence over common config entries.
37
+
38
+ Example development environment config file:
39
+ RAILS_ROOT/config/environments/development.yml
40
+
41
+ Example production environment config file:
42
+ RAILS_ROOT/config/environments/production.yml
43
+
44
+ === Embedded Ruby (ERB)
45
+ Embedded Ruby is allowed in the configuration files. See examples below.
46
+
47
+ === Accessing Configuration Settings
48
+ Consider the two following config files.
49
+
50
+ RAILS_ROOT/config/app_config.yml:
51
+ size: 1
52
+ server: google.com
53
+
54
+ RAILS_ROOT/config/environments/development.yml:
55
+ size: 2
56
+ computed: <%= 1 + 2 + 3 %>
57
+ section:
58
+ size: 3
59
+ servers: [ {name: yahoo.com}, {name: amazon.com} ]
60
+
61
+ Notice that the environment specific config entries overwrite the common entries.
62
+ AppConfig.size -> 2
63
+ AppConfig.server -> google.com
64
+
65
+ Notice the embedded Ruby.
66
+ AppConfig.computed -> 6
67
+
68
+ Notice that object member notation is maintained even in nested entries.
69
+ AppConfig.section.size -> 3
70
+
71
+ Notice array notation and object member notation is maintained.
72
+ AppConfig.section.servers[0].name -> yahoo.com
73
+ AppConfig.section.servers[1].name -> amazon.com
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |s|
6
+ s.name = "rails_app_config"
7
+ s.summary = "provides an AppConfig for rails3 that reads config/app_config.yml"
8
+ s.email = "railsjedi@gmail.com"
9
+ s.homepage = "http://github.com/railsjedi/rails_app_config"
10
+ s.description = "Provides an easy to use Application Configuration object"
11
+ s.authors = ["Jacques Crocker"]
12
+ s.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ # puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
17
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,168 @@
1
+ require 'ostruct'
2
+ require 'yaml'
3
+ require 'erb'
4
+
5
+ module ApplicationConfig
6
+ # == Summary
7
+ # This is API documentation, NOT documentation on how to use this plugin. For that, see the README.
8
+ class ConfigBuilder
9
+ @@load_paths = []
10
+ @@expand_keys = []
11
+ @@root_path = ""
12
+
13
+ # Create a config object (OpenStruct) from a yaml file. If a second yaml file is given, then the sections of that file will overwrite the sections
14
+ # if the first file if they exist in the first file.
15
+ def self.load_files(options = {})
16
+ config = OpenStruct.new
17
+
18
+ @@load_paths = [options[:paths]].flatten.compact.uniq
19
+ @@expand_keys = [options[:expand_keys]].flatten.compact.uniq
20
+ @@root_path = options[:root_path]
21
+
22
+ # add singleton method to our AppConfig that reloads its settings from the load_paths options
23
+ def config.reload!
24
+
25
+ conf = {}
26
+ ConfigBuilder.load_paths.to_a.each do |path|
27
+ file_conf = YAML.load(ERB.new(IO.read(path)).result) if path and File.exists?(path)
28
+ next unless file_conf
29
+
30
+ if conf.size > 0
31
+ DeepMerge.deep_merge!(file_conf, conf, :preserve_unmergeables => false)
32
+ else
33
+ conf = file_conf
34
+ end
35
+ end
36
+
37
+ # expand the javascripts config to handle *.* paths
38
+ ConfigBuilder.expand_keys.to_a.each do |expand_path|
39
+ expand_path = expand_path.to_s
40
+ if conf[expand_path]
41
+ conf[expand_path] = ApplicationConfig::ConfigBuilder.expand(conf[expand_path], "#{ConfigBuilder.root_path}/public/#{expand_path}")
42
+ end
43
+ end
44
+
45
+ # load all the new values into the openstruct
46
+ marshal_load(ApplicationConfig::ConfigBuilder.convert(conf).marshal_dump)
47
+
48
+ return self
49
+ end
50
+
51
+ config.reload!
52
+ return config
53
+ end
54
+
55
+ def self.load_paths
56
+ @@load_paths
57
+ end
58
+
59
+ def self.expand_keys
60
+ @@expand_keys
61
+ end
62
+
63
+ def self.root_path
64
+ @@root_path
65
+ end
66
+
67
+ # Recursively converts Hashes to OpenStructs (including Hashes inside Arrays)
68
+ def self.convert(h) #:nodoc:
69
+ s = OpenStruct.new
70
+ h.each do |k, v|
71
+ s.new_ostruct_member(k)
72
+ if v.is_a?(Hash)
73
+ s.send( (k+'=').to_sym, convert(v))
74
+ elsif v.is_a?(Array)
75
+ converted_array = v.collect { |e| e.instance_of?(Hash) ? convert(e) : e }
76
+ s.send("#{k}=".to_sym, converted_array)
77
+ else
78
+ s.send("#{k}=".to_sym, v)
79
+ end
80
+ end
81
+ s
82
+ end
83
+
84
+ # expand a config val
85
+ def self.expand(config, base_path)
86
+ case config.class.to_s
87
+ when "Hash"
88
+ return expand_hash(config, base_path)
89
+ when "Array"
90
+ return expand_array(config, base_path)
91
+ when "String"
92
+ return expand_string(config, base_path)
93
+ end
94
+ return config
95
+ end
96
+
97
+ # expand a string and returns a list
98
+ def self.expand_string(config, base_path)
99
+ # puts "Expanding String: #{config.inspect}"
100
+ if config.include?("*")
101
+ results = Dir["#{base_path}/#{config}"].map{|i| i.to_s.gsub("#{base_path}/", "") }
102
+
103
+ # puts "EXPANDED PATH: #{base_path}/#{config}"
104
+ # puts results.inspect
105
+ return results
106
+ else
107
+ return config
108
+ end
109
+ end
110
+
111
+ # expand a hash by cycling throw all the hash values
112
+ def self.expand_hash(config, base_path)
113
+ # puts "Expanding Hash: #{config.inspect}"
114
+ new_config = {}
115
+ config.each do |key, val|
116
+ new_config[key] = expand(val, base_path)
117
+ end
118
+ return new_config
119
+ end
120
+
121
+ # expand an array by cycling through all the values
122
+ def self.expand_array(config, base_path)
123
+ # puts "Expanding Array: #{config.inspect}"
124
+ new_config = []
125
+ config.each do |val|
126
+ new_val = expand(val, base_path)
127
+ if new_val.is_a?(Array)
128
+ new_val.each do |inner|
129
+ new_config << inner
130
+ end
131
+ else
132
+ new_config << new_val
133
+ end
134
+ end
135
+ return new_config.uniq
136
+ end
137
+
138
+ # Cycles through the array of single element hashes
139
+ # and deep merges any duplicates it finds
140
+ #
141
+ # This is needed so you can define stylesheet keys
142
+ # in multiple config files
143
+ def self.merge_assets(list)
144
+ assets = Array(list).map do |i|
145
+ if i.is_a?(OpenStruct)
146
+ i.marshal_dump
147
+ else
148
+ i
149
+ end
150
+ end
151
+
152
+ # filter out the duplicate single hash keys
153
+ hash_keys = assets.select{|i| i.is_a?(Hash) and i.keys.size == 1}.group_by{|i| i.keys[0]}
154
+ hash_keys.each do |key, value|
155
+ if Array(value).size > 1
156
+ merged = value.inject({}){|merged, v| DeepMerge.deep_merge!(v,merged)}
157
+ value[0].replace(merged)
158
+ value[1..-1].each do |v|
159
+ v.clear
160
+ end
161
+ end
162
+ end
163
+
164
+ assets.select{|i| !i.blank? }
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,181 @@
1
+ module DeepMerge
2
+
3
+ class InvalidParameter < StandardError; end
4
+
5
+ DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
6
+
7
+ # Deep Merge core documentation.
8
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
9
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
10
+ # of child elements. These child elements to not have to be of the same types.
11
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
12
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
13
+ # the destination element with the contents of the source element at that level.
14
+ # So if you have two hashes like this:
15
+ # source = {:x => [1,2,3], :y => 2}
16
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
17
+ # dest.deep_merge!(source)
18
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
19
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
20
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
21
+ #
22
+ # Options:
23
+ # Options are specified in the last parameter passed, which should be in hash format:
24
+ # hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
25
+ # :preserve_unmergeables DEFAULT: false
26
+ # Set to true to skip any unmergeable elements from source
27
+ # :knockout_prefix DEFAULT: nil
28
+ # Set to string value to signify prefix which deletes elements from existing element
29
+ # :sort_merged_arrays DEFAULT: false
30
+ # Set to true to sort all arrays that are merged together
31
+ # :unpack_arrays DEFAULT: nil
32
+ # Set to string value to run "Array::join" then "String::split" against all arrays
33
+ # :merge_debug DEFAULT: false
34
+ # Set to true to get console output of merge process for debugging
35
+ #
36
+ # Selected Options Details:
37
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
38
+ # from existing Hash by specifying them in a special way in incoming hash
39
+ # source = {:x => ['--1', '2']}
40
+ # dest = {:x => ['1', '3']}
41
+ # dest.ko_deep_merge!(source)
42
+ # Results: {:x => ['2','3']}
43
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
44
+ # the entire element to be removed:
45
+ # source = {:x => '--'}
46
+ # dest = {:x => [1,2,3]}
47
+ # dest.ko_deep_merge!(source)
48
+ # Results: {:x => ""}
49
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
50
+ # in as strings and to be converted into discrete array elements
51
+ # irsource = {:x => ['1,2,3', '4']}
52
+ # dest = {:x => ['5','6','7,8']}
53
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
54
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
55
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
56
+ # to pass multiple values from within a single HTML element
57
+ #
58
+ # There are many tests for this library - and you can learn more about the features
59
+ # and usages of deep_merge! by just browsing the test examples
60
+ def DeepMerge.deep_merge!(source, dest, options = {})
61
+ # turn on this line for stdout debugging text
62
+ merge_debug = options[:merge_debug] || false
63
+ overwrite_unmergeable = !options[:preserve_unmergeables]
64
+ knockout_prefix = options[:knockout_prefix] || nil
65
+ if knockout_prefix == ""; raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!"; end
66
+ if knockout_prefix && !overwrite_unmergeable; raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!"; end
67
+ # if present: we will split and join arrays on this char before merging
68
+ array_split_char = options[:unpack_arrays] || false
69
+ # request that we sort together any arrays when they are merged
70
+ sort_merged_arrays = options[:sort_merged_arrays] || false
71
+ di = options[:debug_indent] || ''
72
+ # do nothing if source is nil
73
+ if source.nil? || (!source.is_a?(FalseClass) && source.respond_to?(:blank?) && source.blank?); return dest; end
74
+ # if dest doesn't exist, then simply copy source to it
75
+ if dest.nil? && overwrite_unmergeable; dest = source; return dest; end
76
+
77
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
78
+ if source.kind_of?(Hash)
79
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
80
+ source.each do |src_key, src_value|
81
+ if dest.kind_of?(Hash)
82
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
83
+ if !dest[src_key].nil?
84
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
85
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
86
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
87
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
88
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
89
+ begin
90
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
91
+ rescue TypeError
92
+ src_dup = src_value
93
+ end
94
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
95
+ end
96
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
97
+ if overwrite_unmergeable
98
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
99
+ dest = overwrite_unmergeables(source, dest, options)
100
+ end
101
+ end
102
+ end
103
+ elsif source.kind_of?(Array)
104
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
105
+ # if we are instructed, join/split any source arrays before processing
106
+ if array_split_char
107
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
108
+ source = source.join(array_split_char).split(array_split_char)
109
+ if dest.kind_of?(Array); dest = dest.join(array_split_char).split(array_split_char); end
110
+ end
111
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
112
+ if source.index(knockout_prefix); dest = clear_or_nil(dest); source.delete(knockout_prefix); end
113
+ if dest.kind_of?(Array)
114
+ if knockout_prefix
115
+ print "#{di} knocking out: " if merge_debug
116
+ # remove knockout prefix items from both source and dest
117
+ source.delete_if do |ko_item|
118
+ retval = false
119
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
120
+ if item != ko_item
121
+ print "#{ko_item} - " if merge_debug
122
+ dest.delete(item)
123
+ dest.delete(ko_item)
124
+ retval = true
125
+ end
126
+ retval
127
+ end
128
+ puts if merge_debug
129
+ end
130
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
131
+ dest = dest | source
132
+ if sort_merged_arrays; dest.sort!; end
133
+ elsif overwrite_unmergeable
134
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
135
+ dest = overwrite_unmergeables(source, dest, options)
136
+ end
137
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
138
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
139
+ dest = overwrite_unmergeables(source, dest, options)
140
+ end
141
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
142
+ dest
143
+ end # deep_merge!
144
+
145
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
146
+ def DeepMerge::overwrite_unmergeables(source, dest, options)
147
+ merge_debug = options[:merge_debug] || false
148
+ overwrite_unmergeable = !options[:preserve_unmergeables]
149
+ knockout_prefix = options[:knockout_prefix] || false
150
+ di = options[:debug_indent] || ''
151
+ if knockout_prefix && overwrite_unmergeable
152
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
153
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
154
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
155
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
156
+ else
157
+ src_tmp = source
158
+ end
159
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
160
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
161
+ dest = src_tmp
162
+ else # if we do find a knockout_prefix, then we just delete dest
163
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
164
+ dest = ""
165
+ end
166
+ elsif overwrite_unmergeable
167
+ dest = source
168
+ end
169
+ dest
170
+ end
171
+
172
+ def DeepMerge::clear_or_nil(obj)
173
+ if obj.respond_to?(:clear)
174
+ obj.clear
175
+ else
176
+ obj = nil
177
+ end
178
+ obj
179
+ end
180
+
181
+ end # module DeepMerge
@@ -0,0 +1,74 @@
1
+ module ApplicationConfig
2
+ module ViewHelpers
3
+ def javascripts_from_config(options = {})
4
+ html = ""
5
+ only = [options.delete(:only)].flatten.compact.map{|i| i.to_s}
6
+ if defined?(AppConfig) and AppConfig.javascripts
7
+
8
+ ConfigBuilder.merge_assets(AppConfig.javascripts).each do |javascript|
9
+ if javascript.is_a? Hash
10
+ javascript.each do |key, val|
11
+ next unless only.empty? || only.include?(key.to_s)
12
+
13
+ args = [val].flatten
14
+ args = args.map{|s| s.gsub("javascripts/", AppConfig.javascript_path)} if AppConfig.javascript_path
15
+ if defined?(Merb)
16
+ args << options.merge(:bundle => key.to_sym)
17
+ html << js_include_tag(*args).to_s
18
+ elsif defined?(Rails)
19
+ args << options.merge(:cache => key.to_s)
20
+ html << javascript_include_tag(*args).to_s
21
+ end
22
+ html << "\n"
23
+ end
24
+ else
25
+ args = [javascript].flatten
26
+ args = args.map{|s| s.gsub("javascripts/", AppConfig.javascript_path)} if AppConfig.javascript_path
27
+ args << options
28
+ if defined?(Merb)
29
+ html << js_include_tag(*args).to_s
30
+ elsif defined?(Rails)
31
+ html << javascript_include_tag(*args).to_s
32
+ end
33
+ end
34
+ end
35
+ end
36
+ return html
37
+ end
38
+
39
+ def stylesheets_from_config(options = {})
40
+ html = ""
41
+ only = [options.delete(:only)].flatten.compact.map{|i| i.to_s}
42
+ if defined?(AppConfig) and AppConfig.stylesheets
43
+ ConfigBuilder.merge_assets(AppConfig.stylesheets).each do |stylesheet|
44
+ if stylesheet.is_a? Hash
45
+ stylesheet.each do |key, val|
46
+ next unless only.empty? || only.include?(key.to_s)
47
+
48
+ args = [val].flatten
49
+ args = args.map{|s| s.gsub("stylesheets/", AppConfig.stylesheet_path)} if AppConfig.stylesheet_path
50
+ if defined?(Merb)
51
+ args << options.merge(:bundle => key.to_sym)
52
+ html << css_include_tag(*args).to_s
53
+ elsif defined?(Rails)
54
+ args << options.merge(:cache => key.to_s)
55
+ html << stylesheet_link_tag(*args).to_s
56
+ end
57
+ end
58
+ else
59
+ args = [stylesheet].flatten
60
+ args = args.map{|s| s.gsub("stylesheets/", AppConfig.stylesheet_path)} if AppConfig.stylesheet_path
61
+ args << options
62
+ if defined?(Merb)
63
+ html << css_include_tag(*args).to_s
64
+ elsif defined?(Rails)
65
+ html << stylesheet_link_tag(*args).to_s
66
+ end
67
+ end
68
+ html << "\n"
69
+ end
70
+ end
71
+ return html
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ require 'application_config/deep_merge' unless defined?(DeepMerge)
2
+ require 'application_config/config_builder'
3
+ require 'application_config/view_helpers'
4
+
5
+ require 'rails_app_config/railtie'
@@ -0,0 +1,17 @@
1
+ if defined?(Rails::Railtie)
2
+ module RailsAppConfig
3
+ class Railtie < Rails::Railtie
4
+ initializer :setup_app_config do
5
+ ::AppConfig = ApplicationConfig::ConfigBuilder.load_files(
6
+ :paths => [
7
+ Rails.root.join("config", "app_config.yml").to_s,
8
+ Rails.root.join("config", "app_config", "settings.yml").to_s,
9
+ Rails.root.join("config", "app_config", "#{Rails.env}.yml").to_s,
10
+ Rails.root.join("config", "environments", "#{Rails.env}.yml").to_s
11
+ ],
12
+ :root_path => Rails.root
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ namespace :app_config do
2
+ desc "Create a blank config/app_config.yml file"
3
+ task :init do
4
+ puts "Setting up AppConfig files..."
5
+ `mkdir -p config/app_config`
6
+
7
+ ["config/app_config.yml",
8
+ "config/app_config/development.yml",
9
+ "config/app_config/production.yml"
10
+ ].each do |path|
11
+ `touch #{path}`
12
+ puts "Created: #{path}"
13
+ end
14
+ puts "Complete!"
15
+ puts "Add key/value pairs to your yaml file,\nthen access them in your Merb project via AppConfig.[key]"
16
+ end
17
+ end
@@ -0,0 +1,88 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'extlib'
4
+ require File.dirname(__FILE__)+'/../lib/application_config/config_builder'
5
+ require File.dirname(__FILE__)+'/../lib/application_config/deep_merge'
6
+
7
+ class ConfigBuilderTest < Test::Unit::TestCase
8
+ def setup
9
+ @settings_path = File.dirname(__FILE__)+"/test_configs"
10
+ end
11
+
12
+ def test_missing_files
13
+ files = ["#{@settings_path}/empty1.yml", "#{@settings_path}/empty2.yml"]
14
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => files)
15
+ assert_equal OpenStruct.new, config
16
+ end
17
+
18
+ def test_empty_files
19
+ files = ["#{@settings_path}/empty1.yml", "#{@settings_path}/empty2.yml"]
20
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => files)
21
+ assert_equal OpenStruct.new, config
22
+ end
23
+
24
+ def test_common
25
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => "#{@settings_path}/app_config.yml")
26
+ assert_equal 1, config.size
27
+ assert_equal 'google.com', config.server
28
+ end
29
+
30
+ def test_environment_override
31
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/app_config.yml", "#{@settings_path}/development.yml"])
32
+ assert_equal 2, config.size
33
+ assert_equal 'google.com', config.server
34
+ end
35
+
36
+ def test_nested
37
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/development.yml"])
38
+ assert_equal 3, config.section.size
39
+ end
40
+
41
+ def test_array
42
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => "#{@settings_path}/development.yml")
43
+ assert_equal 'yahoo.com', config.section.servers[0].name
44
+ assert_equal 'amazon.com', config.section.servers[1].name
45
+ end
46
+
47
+ def test_erb
48
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => "#{@settings_path}/development.yml")
49
+ assert_equal 6, config.computed
50
+ end
51
+
52
+ def test_merge_hashes_from_multiple_configs
53
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/deep_merge/config1.yml", "#{@settings_path}/deep_merge/config2.yml"])
54
+
55
+ assert_equal 3, config.inner.marshal_dump.keys.size
56
+ assert_equal 3, config.inner2.inner2_inner.marshal_dump.keys.size
57
+ end
58
+
59
+
60
+ def test_merge_arrays_from_multiple_configs
61
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/deep_merge/config1.yml", "#{@settings_path}/deep_merge/config2.yml"])
62
+ assert_equal 6, config.arraylist1.size
63
+ assert_equal 6, config.arraylist2.inner.size
64
+ end
65
+
66
+ def test_merge_assets
67
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/deep_merge/config1.yml", "#{@settings_path}/deep_merge/config2.yml"])
68
+ merged = ApplicationConfig::ConfigBuilder.merge_assets(config.hash_array)
69
+
70
+ assert_equal 3, merged.size
71
+ assert_equal 6, merged.select{|i| i.is_a?(Hash)}.first[:inner].size
72
+ end
73
+
74
+ def test_merge_assets2
75
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/deep_merge2/config1.yml", "#{@settings_path}/deep_merge2/config2.yml"])
76
+
77
+ assert_equal 500, config.tvrage.cache
78
+ assert_equal "http://url2", config.tvrage.service_url
79
+ end
80
+
81
+ def test_boolean_overrides
82
+ config = ApplicationConfig::ConfigBuilder.load_files(:paths => ["#{@settings_path}/bool_override/config1.yml", "#{@settings_path}/bool_override/config2.yml"])
83
+ assert_equal false, config.override_bool
84
+ assert_equal true, config.override_bool_opposite
85
+ end
86
+
87
+
88
+ end
@@ -0,0 +1,2 @@
1
+ size: 1
2
+ server: google.com
@@ -0,0 +1,2 @@
1
+ override_bool: true
2
+ override_bool_opposite: false
@@ -0,0 +1,2 @@
1
+ override_bool: false
2
+ override_bool_opposite: true
@@ -0,0 +1,28 @@
1
+ size: 1
2
+ server: google.com
3
+ inner:
4
+ something1: "blah1"
5
+ something2: "blah2"
6
+
7
+ inner2:
8
+ inner2_inner:
9
+ foo1: "blah1"
10
+
11
+
12
+ arraylist1:
13
+ - 1
14
+ - 2
15
+ - 3
16
+
17
+ arraylist2:
18
+ inner:
19
+ - 1
20
+ - 2
21
+ - 3
22
+
23
+ hash_array:
24
+ - 1
25
+ - inner:
26
+ - 1
27
+ - 2
28
+ - 3
@@ -0,0 +1,28 @@
1
+ server: google.com
2
+
3
+ inner:
4
+ something3: "blah3"
5
+
6
+ inner2:
7
+ inner2_inner:
8
+ foo2: "blah2"
9
+ foo3: "blah3"
10
+
11
+ arraylist1:
12
+ - 4
13
+ - 5
14
+ - 6
15
+
16
+
17
+ arraylist2:
18
+ inner:
19
+ - 4
20
+ - 5
21
+ - 6
22
+
23
+ hash_array:
24
+ - 2
25
+ - inner:
26
+ - 4
27
+ - 5
28
+ - 6
@@ -0,0 +1,3 @@
1
+ tvrage:
2
+ service_url: 'http://services.tvrage.com'
3
+ cache: 500
@@ -0,0 +1,2 @@
1
+ tvrage:
2
+ service_url: "http://url2"
@@ -0,0 +1,5 @@
1
+ size: 2
2
+ computed: <%= 1 + 2 + 3 %>
3
+ section:
4
+ size: 3
5
+ servers: [ {name: yahoo.com}, {name: amazon.com} ]
File without changes
File without changes
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_app_config
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Jacques Crocker
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-21 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Provides an easy to use Application Configuration object
22
+ email: railsjedi@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - LICENSE
29
+ - README
30
+ files:
31
+ - LICENSE
32
+ - README
33
+ - Rakefile
34
+ - VERSION
35
+ - lib/application_config/config_builder.rb
36
+ - lib/application_config/deep_merge.rb
37
+ - lib/application_config/view_helpers.rb
38
+ - lib/rails_app_config.rb
39
+ - lib/rails_app_config/railtie.rb
40
+ - lib/tasks/app_config.rake
41
+ - test/config_builder_test.rb
42
+ - test/test_configs/app_config.yml
43
+ - test/test_configs/bool_override/config1.yml
44
+ - test/test_configs/bool_override/config2.yml
45
+ - test/test_configs/deep_merge/config1.yml
46
+ - test/test_configs/deep_merge/config2.yml
47
+ - test/test_configs/deep_merge2/config1.yml
48
+ - test/test_configs/deep_merge2/config2.yml
49
+ - test/test_configs/development.yml
50
+ - test/test_configs/empty1.yml
51
+ - test/test_configs/empty2.yml
52
+ has_rdoc: true
53
+ homepage: http://github.com/railsjedi/rails_app_config
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.6
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: provides an AppConfig for rails3 that reads config/app_config.yml
82
+ test_files:
83
+ - test/config_builder_test.rb