rails_config_i18n 0.3.1.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.
Files changed (44) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE +23 -0
  5. data/README.md +243 -0
  6. data/Rakefile +28 -0
  7. data/autotest/discover.rb +2 -0
  8. data/init.rb +1 -0
  9. data/lib/generators/rails_config/install_generator.rb +32 -0
  10. data/lib/generators/rails_config/templates/rails_config.rb +4 -0
  11. data/lib/generators/rails_config/templates/settings/development.yml +1 -0
  12. data/lib/generators/rails_config/templates/settings/production.yml +1 -0
  13. data/lib/generators/rails_config/templates/settings/test.yml +1 -0
  14. data/lib/generators/rails_config/templates/settings.local.yml +1 -0
  15. data/lib/generators/rails_config/templates/settings.yml +1 -0
  16. data/lib/rails_config/integration/rails.rb +38 -0
  17. data/lib/rails_config/integration/sinatra.rb +31 -0
  18. data/lib/rails_config/options.rb +100 -0
  19. data/lib/rails_config/rack/reloader.rb +15 -0
  20. data/lib/rails_config/rails_config.rb +55 -0
  21. data/lib/rails_config/sources/yaml_source.rb +24 -0
  22. data/lib/rails_config/vendor/deep_merge.rb +180 -0
  23. data/lib/rails_config/version.rb +3 -0
  24. data/lib/rails_config_i18n.rb +1 -0
  25. data/rails_config.gemspec +26 -0
  26. data/spec/fixtures/bool_override/config1.yml +2 -0
  27. data/spec/fixtures/bool_override/config2.yml +2 -0
  28. data/spec/fixtures/custom_types/hash.yml +7 -0
  29. data/spec/fixtures/deep_merge/config1.yml +28 -0
  30. data/spec/fixtures/deep_merge/config2.yml +28 -0
  31. data/spec/fixtures/deep_merge2/config1.yml +3 -0
  32. data/spec/fixtures/deep_merge2/config2.yml +2 -0
  33. data/spec/fixtures/development.yml +4 -0
  34. data/spec/fixtures/empty1.yml +0 -0
  35. data/spec/fixtures/empty2.yml +0 -0
  36. data/spec/fixtures/locales/settings.en.yml +3 -0
  37. data/spec/fixtures/locales/settings.zh-CN.yml +2 -0
  38. data/spec/fixtures/settings.yml +3 -0
  39. data/spec/fixtures/settings2.yml +1 -0
  40. data/spec/fixtures/with_erb.yml +4 -0
  41. data/spec/rails_config_spec.rb +235 -0
  42. data/spec/sources/yaml_source_spec.rb +69 -0
  43. data/spec/spec_helper.rb +25 -0
  44. metadata +191 -0
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ --- {}
2
+
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ pkg/*.gem
3
+ .rvmrc
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'i18n'
7
+ gem 'json', :platforms => :mri_18
8
+ gem "ruby-debug", :platforms => :mri_18
9
+ gem "ruby-debug19", :platforms => :mri_19
10
+ end
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.md ADDED
@@ -0,0 +1,243 @@
1
+ # RailsConfig
2
+
3
+ ## Summary
4
+
5
+ RailsConfig I18n helps you manage environment and locale specific Rails settings in an easy and usable manner
6
+
7
+ <del>RailsConfig helps you easily manage environment specific Rails settings in an easy and usable manner</del>
8
+
9
+ ## Features
10
+
11
+ * simple YAML config files
12
+ * Support locales with I18n
13
+ * config files support ERB
14
+ * config files support inheritance
15
+ * access config information via convenient object member notation
16
+
17
+ ## Compatibility
18
+
19
+ * Rails 3.x
20
+ * Padrino
21
+ * Sinatra
22
+
23
+ For older versions of Rails and other Ruby apps, use [AppConfig](http://github.com/fredwu/app_config).
24
+
25
+ ## Installing on Rails 3
26
+
27
+ Add this to your `Gemfile`:
28
+
29
+ ```ruby
30
+ gem "rails_config"
31
+ ```
32
+
33
+ ## Installing on Padrino
34
+
35
+ Add this to your `Gemfile`:
36
+
37
+ ```ruby
38
+ gem "rails_config"
39
+ ```
40
+
41
+ in your app.rb, you'll also need to register RailsConfig
42
+
43
+ ```ruby
44
+ register RailsConfig
45
+ ```
46
+
47
+ ## Installing on Sinatra
48
+
49
+ Add this to your `Gemfile`:
50
+
51
+ ```ruby
52
+ gem "rails_config"
53
+ ```
54
+
55
+ in your app, you'll need to register RailsConfig. You'll also need to give it a root so it can find the config files.
56
+
57
+ ```ruby
58
+ set :root, File.dirname(__FILE__)
59
+ register RailsConfig
60
+ ```
61
+
62
+ It's also possible to initialize it manually within your configure block if you want to just give it some yml paths to load from.
63
+
64
+ ```ruby
65
+ RailsConfig.load_and_set_settings("/path/to/yaml1", "/path/to/yaml2", ...)
66
+ ```
67
+
68
+ ## Customizing RailsConfig
69
+
70
+ You may customize the behavior of RailsConfig by generating an initializer file:
71
+
72
+ rails g rails_config:install
73
+
74
+ This will generate `config/initializers/rails_config.rb` with a set of default settings as well as to generate a set of default settings files:
75
+
76
+ config/settings.yml
77
+ config/settings/development.yml
78
+ config/settings/production.yml
79
+ config/settings/test.yml
80
+
81
+ ## Accessing the Settings object
82
+
83
+ After installing this plugin, the `Settings` object will be available globally. Entries are accessed via object member notation:
84
+
85
+ ```ruby
86
+ Settings.my_config_entry
87
+ ```
88
+
89
+ Nested entries are supported:
90
+
91
+ ```ruby
92
+ Settings.my_section.some_entry
93
+ ```
94
+
95
+ Alternatively, you can also use the `[]` operator if you don't know which exact setting you need to access ahead of time.
96
+
97
+ ```ruby
98
+ # All the following are equivalent to Settings.my_section.some_entry
99
+ Settings.my_section[:some_entry]
100
+ Settings.my_section['some_entry]
101
+ Settings[:my_section][:some_entry]
102
+ ```
103
+
104
+ If you have set a different constant name for the object in the initializer file, use that instead.
105
+
106
+ ## Common config file
107
+
108
+ Config entries are compiled from:
109
+
110
+ config/settings.yml
111
+ config/settings/#{environment}.yml
112
+ config/settings/#{locale}.yml
113
+ config/environments/#{environment}.yml
114
+
115
+ config/settings.local.yml
116
+ config/settings/#{environment}.local.yml
117
+ config/environments/#{environment}.local.yml
118
+
119
+ Settings defined in files that are lower in the list override settings higher.
120
+
121
+ ### Reloading settings
122
+
123
+ You can reload the Settings object at any time by running `Settings.reload!`.
124
+
125
+ ### Reloading settings and config files
126
+
127
+ You can also reload the `Settings` object from different config files at runtime.
128
+
129
+ For example, in your tests if you want to test the production settings, you can:
130
+
131
+ ```ruby
132
+ Rails.env = "production"
133
+ Settings.reload_from_files(
134
+ Rails.root.join("config", "settings.yml").to_s,
135
+ Rails.root.join("config", "settings", "#{Rails.env}.yml").to_s,
136
+ Rails.root.join("config", "environments", "#{Rails.env}.yml").to_s
137
+ )
138
+ ```
139
+
140
+ ### Environment specific config files
141
+
142
+ You can have environment specific config files. Environment specific config entries take precedence over common config entries.
143
+
144
+ Example development environment config file:
145
+
146
+ ```ruby
147
+ #{Rails.root}/config/environments/development.yml
148
+ ```
149
+
150
+ Example production environment config file:
151
+
152
+ ```ruby
153
+ #{Rails.root}/config/environments/production.yml
154
+ ```
155
+
156
+ ### Developer specific config files
157
+
158
+ If you want to have local settings, specific to your machine or development environment,
159
+ you can use the following files, which are automatically `.gitignored` :
160
+
161
+ Rails.root.join("config", "settings.local.yml").to_s,
162
+ Rails.root.join("config", "settings", "#{Rails.env}.local.yml").to_s,
163
+ Rails.root.join("config", "environments", "#{Rails.env}.local.yml").to_s
164
+
165
+
166
+ ### Adding sources at Runtime
167
+
168
+ You can add new YAML config files at runtime. Just use:
169
+
170
+ ```ruby
171
+ Settings.add_source!("/path/to/source.yml")
172
+ Settings.reload!
173
+ ```
174
+
175
+ This will use the given source.yml file and use its settings to overwrite any previous ones.
176
+
177
+ One thing I like to do for my Rails projects is provide a local.yml config file that is .gitignored (so its independent per developer). Then I create a new initializer in `config/initializers/add_local_config.rb` with the contents
178
+
179
+ ```ruby
180
+ Settings.add_source!("#{Rails.root}/config/settings/local.yml")
181
+ Settings.reload!
182
+ ```
183
+
184
+ > Note: this is an example usage, it is easier to just use the default local files `settings.local.yml, settings/#{Rails.env}.local.yml and environments/#{Rails.env}.local.yml`
185
+ > for your developer specific settings.
186
+
187
+ ## Embedded Ruby (ERB)
188
+
189
+ Embedded Ruby is allowed in the configuration files. See examples below.
190
+
191
+ ## Accessing Configuration Settings
192
+
193
+ Consider the two following config files.
194
+
195
+ #{Rails.root}/config/settings.yml:
196
+
197
+ ```yaml
198
+ size: 1
199
+ server: google.com
200
+ ```
201
+
202
+ #{Rails.root}/config/environments/development.yml:
203
+
204
+ ```yaml
205
+ size: 2
206
+ computed: <%= 1 + 2 + 3 %>
207
+ section:
208
+ size: 3
209
+ servers: [ {name: yahoo.com}, {name: amazon.com} ]
210
+ ```
211
+
212
+ Notice that the environment specific config entries overwrite the common entries.
213
+
214
+ ```ruby
215
+ Settings.size # => 2
216
+ Settings.server # => google.com
217
+ ```
218
+
219
+ Notice the embedded Ruby.
220
+
221
+ ```ruby
222
+ Settings.computed # => 6
223
+ ```
224
+
225
+ Notice that object member notation is maintained even in nested entries.
226
+
227
+ ```ruby
228
+ Settings.section.size # => 3
229
+ ```
230
+
231
+ Notice array notation and object member notation is maintained.
232
+
233
+ ```ruby
234
+ Settings.section.servers[0].name # => yahoo.com
235
+ Settings.section.servers[1].name # => amazon.com
236
+ ```
237
+
238
+ ## Authors
239
+
240
+ * [Jacques Crocker](http://github.com/railsjedi)
241
+ * [Fred Wu](http://github.com/fredwu)
242
+ * [Cedric Fung](https://bitbucket.org/ABitNo)
243
+ * Inherited from [AppConfig](http://github.com/cjbottaro/app_config) by [Christopher J. Bottaro](http://github.com/cjbottaro)
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ begin
2
+ require "bundler"
3
+ Bundler::GemHelper.install_tasks
4
+ rescue Exception => e
5
+ end
6
+
7
+ require "rake"
8
+ require "rspec"
9
+ require "rspec/core/rake_task"
10
+
11
+ RSpec::Core::RakeTask.new(:spec) do |spec|
12
+ spec.pattern = "spec/**/*_spec.rb"
13
+ end
14
+
15
+ RSpec::Core::RakeTask.new('spec:progress') do |spec|
16
+ spec.rspec_opts = %w(--format progress)
17
+ spec.pattern = "spec/**/*_spec.rb"
18
+ end
19
+
20
+ require "rdoc/task"
21
+ Rake::RDocTask.new do |rdoc|
22
+ rdoc.rdoc_dir = "rdoc"
23
+ rdoc.title = "Rails Config #{RailsConfig::VERSION}"
24
+ rdoc.rdoc_files.include("README*")
25
+ rdoc.rdoc_files.include("lib/**/*.rb")
26
+ end
27
+
28
+ task :default => :spec
@@ -0,0 +1,2 @@
1
+ Autotest.add_discovery { "rspec2" }
2
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/lib/rails_config_i18n'
@@ -0,0 +1,32 @@
1
+ module RailsConfig
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ desc "Generates a custom Rails Config initializer file."
5
+
6
+ def self.source_root
7
+ @_rails_config_source_root ||= File.expand_path("../templates", __FILE__)
8
+ end
9
+
10
+ def copy_initializer
11
+ template "rails_config.rb", "config/initializers/rails_config.rb"
12
+ end
13
+
14
+ def copy_settings
15
+ template "settings.yml", "config/settings.yml"
16
+ template "settings.local.yml", "config/settings.local.yml"
17
+ directory "settings", "config/settings"
18
+ end
19
+
20
+ def modify_gitignore
21
+ if File.exists?('.gitignore')
22
+ append_to_file '.gitignore' do
23
+ "\n" +
24
+ "config/settings.local.yml\n" +
25
+ "config/settings/*.local.yml\n" +
26
+ "config/environments/*.local.yml\n"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,4 @@
1
+ RailsConfig.setup do |config|
2
+ I18n.default_locale = :en
3
+ config.const_name = "Settings"
4
+ end
@@ -0,0 +1,38 @@
1
+ module RailsConfig
2
+ module Integration
3
+ module Rails3
4
+ if defined?(Rails::Railtie)
5
+ class Railtie < Rails::Railtie
6
+
7
+ # manually load the custom initializer before everything else
8
+ initializer :load_custom_rails_config, :before => :load_environment_config do
9
+ initializer = Rails.root.join("config", "initializers", "rails_config.rb")
10
+ require initializer if File.exist?(initializer)
11
+ end
12
+
13
+ # Parse the settings before any of the initializers
14
+ initializer :load_rails_config_settings, :after => :load_custom_rails_config, :before => :load_environment_config do
15
+ RailsConfig.load_and_set_settings(
16
+ Rails.root.join("config", "settings.yml").to_s,
17
+ *Dir[Rails.root.join("config", "settings", "**", "*.yml")],
18
+ Rails.root.join("config", "environments", "#{Rails.env}.yml").to_s,
19
+
20
+ Rails.root.join("config", "settings.local.yml").to_s,
21
+ Rails.root.join("config", "settings", "#{Rails.env}.local.yml").to_s,
22
+ Rails.root.join("config", "environments", "#{Rails.env}.local.yml").to_s
23
+ )
24
+ end
25
+
26
+ # Rails Dev environment should reload the Settings on every request
27
+ if Rails.env.development?
28
+ initializer :rails_config_reload_on_development do
29
+ ActionController::Base.class_eval do
30
+ prepend_before_filter { ::RailsConfig.reload! }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ require "rails_config/rack/reloader"
2
+
3
+ module RailsConfig
4
+ # provide helper to register within your Sinatra app
5
+ #
6
+ # set :root, File.dirname(__FILE__)
7
+ # register RailsConfig
8
+ #
9
+ def self.registered(app)
10
+ app.configure do |inner_app|
11
+
12
+ env = inner_app.environment || ENV["RACK_ENV"]
13
+ root = inner_app.root
14
+
15
+ # use Padrino settings if applicable
16
+ if defined?(Padrino)
17
+ env = Padrino.env
18
+ root = Padrino.root
19
+ end
20
+
21
+ RailsConfig.load_and_set_settings(
22
+ File.join(root.to_s, "config", "settings.yml").to_s,
23
+ File.join(root.to_s, "config", "settings", "#{env}.yml").to_s,
24
+ File.join(root.to_s, "config", "environments", "#{env}.yml").to_s
25
+ )
26
+
27
+ inner_app.use(::RailsConfig::Rack::Reloader) if inner_app.development?
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,100 @@
1
+ require 'ostruct'
2
+ module RailsConfig
3
+ class Options < OpenStruct
4
+
5
+ def empty?
6
+ marshal_dump.empty?
7
+ end
8
+
9
+ def add_source!(source)
10
+ # handle yaml file paths
11
+ source = (Sources::YAMLSource.new(source)) if source.is_a?(String)
12
+
13
+ @config_sources ||= []
14
+ @config_sources << source
15
+ end
16
+
17
+ # look through all our sources and rebuild the configuration
18
+ def reload!
19
+ conf = {}
20
+ @config_sources.each do |source|
21
+ source_conf = source.load
22
+
23
+ if conf.empty?
24
+ conf = source_conf
25
+ else
26
+ DeepMerge.deep_merge!(source_conf, conf, :preserve_unmergeables => false)
27
+ end
28
+ end
29
+
30
+ conf.each_pair { |locale, values|
31
+ unless locale == I18n.default_locale.to_s
32
+ conf[locale.to_s].merge!(conf[I18n.default_locale.to_s].merge(conf[locale.to_s])) if conf[I18n.default_locale.to_s].is_a?(Hash) && conf[locale.to_s].is_a?(Hash)
33
+ end
34
+ }
35
+
36
+ # swap out the contents of the OStruct with a hash (need to recursively convert)
37
+ marshal_load(__convert(conf).marshal_dump)
38
+
39
+ return self
40
+ end
41
+
42
+ alias :load! :reload!
43
+
44
+ def reload_from_files(*files)
45
+ RailsConfig.load_and_set_settings(files)
46
+ reload!
47
+ end
48
+
49
+ def to_hash
50
+ result = {}
51
+ marshal_dump.each do |k, v|
52
+ result[k] = v.instance_of?(RailsConfig::Options) ? v.to_hash : v
53
+ end
54
+ result
55
+ end
56
+
57
+ def to_json(*args)
58
+ require "json" unless defined?(JSON)
59
+ to_hash.to_json(*args)
60
+ end
61
+
62
+ def merge!(hash)
63
+ current = to_hash
64
+ DeepMerge.deep_merge!(hash.dup, current)
65
+ marshal_load(__convert(current).marshal_dump)
66
+ self
67
+ end
68
+
69
+ # An alternative mechanism for property access.
70
+ # This let's you do foo['bar'] along with foo.bar.
71
+ def [](param)
72
+ send("#{param}")
73
+ end
74
+
75
+ def []=(param, value)
76
+ send("#{param}=", value)
77
+ end
78
+
79
+ protected
80
+
81
+ # Recursively converts Hashes to Options (including Hashes inside Arrays)
82
+ def __convert(h) #:nodoc:
83
+ s = self.class.new
84
+
85
+ h.each do |k, v|
86
+ k = k.to_s if !k.respond_to?(:to_sym) && k.respond_to?(:to_s)
87
+ s.new_ostruct_member(k)
88
+
89
+ if v.is_a?(Hash)
90
+ v = v["type"] == "hash" ? v["contents"] : __convert(v)
91
+ elsif v.is_a?(Array)
92
+ v = v.collect { |e| e.instance_of?(Hash) ? __convert(e) : e }
93
+ end
94
+
95
+ s.send("#{k}=".to_sym, v)
96
+ end
97
+ s
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,15 @@
1
+ module RailsConfig
2
+ module Rack
3
+ # Rack middleware the reloads RailsConfig on every request (only use in dev mode)
4
+ class Reloader
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ RailsConfig.reload!
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'rails_config/options'
3
+
4
+ require "rails_config/sources/yaml_source"
5
+
6
+ require 'rails_config/vendor/deep_merge' unless defined?(DeepMerge)
7
+
8
+ module RailsConfig
9
+ # ensures the setup only gets run once
10
+ @@_ran_once = false
11
+
12
+ @@options = nil
13
+
14
+ mattr_accessor :const_name
15
+ @@const_name = "Settings"
16
+
17
+ def self.setup
18
+ yield self if @@_ran_once == false
19
+ @@_ran_once = true
20
+ end
21
+
22
+ # Create a populated Options instance from a yaml file. If a second yaml file is given, then the sections of that file will overwrite the sections
23
+ # if the first file if they exist in the first file.
24
+ def self.load_files(*files)
25
+ @@options = Options.new
26
+
27
+ # add yaml sources
28
+ [files].flatten.compact.uniq.each do |file|
29
+ @@options.add_source!(file.to_s)
30
+ end
31
+
32
+ @@options.load!
33
+ end
34
+
35
+ # Loads and sets the settings constant!
36
+ def self.load_and_set_settings(*files)
37
+ Kernel.send(:remove_const, @@const_name) if Kernel.const_defined?(@@const_name)
38
+ load_files(files)
39
+ Kernel.const_set(@@const_name, self)
40
+ end
41
+
42
+ def self.reload!
43
+ @@options.reload!
44
+ end
45
+
46
+ def self.method_missing(method, *args, &block)
47
+ (@@options[I18n.locale] || @@options[I18n.default_locale] || {}).send(method, *args)
48
+ end
49
+ end
50
+
51
+ # add rails integration
52
+ require('rails_config/integration/rails') if defined?(::Rails)
53
+
54
+ # add sinatra integration
55
+ require('rails_config/integration/sinatra') if defined?(::Sinatra)
@@ -0,0 +1,24 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+
4
+ module RailsConfig
5
+ module Sources
6
+ class YAMLSource
7
+
8
+ attr_accessor :path
9
+
10
+ def initialize(path)
11
+ @path = path
12
+ end
13
+
14
+ # returns a config hash from the YML file
15
+ def load
16
+ if @path and File.exists?(@path.to_s)
17
+ result = YAML.load(ERB.new(IO.read(@path.to_s)).result)
18
+ end
19
+ result || {}
20
+ end
21
+
22
+ end
23
+ end
24
+ end