rails_config_i18n 0.3.1.1

Sign up to get free protection for your applications and to get access to all the features.
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