Skip to content

Commit 60730db

Browse files
author
Sidelnikov Stanislav
committed
Loading settings from ENV. A task pushing settings to Heroku
1 parent e609360 commit 60730db

File tree

10 files changed

+155
-1
lines changed

10 files changed

+155
-1
lines changed

lib/rails_config.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ module RailsConfig
99
# ensures the setup only gets run once
1010
@@_ran_once = false
1111

12-
mattr_accessor :const_name
12+
mattr_accessor :const_name, :use_env
1313
@@const_name = "Settings"
14+
@@use_env = false
1415

1516
def self.setup
1617
yield self if @@_ran_once == false
@@ -28,6 +29,7 @@ def self.load_files(*files)
2829
end
2930

3031
config.load!
32+
config.load_env! if @@use_env
3133
config
3234
end
3335

lib/rails_config/integration/rails.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ module Integration
33
module Rails3
44
if defined?(Rails::Railtie)
55
class Railtie < Rails::Railtie
6+
rake_tasks do
7+
Dir[File.join(File.dirname(__FILE__),'../tasks/*.rake')].each { |f| load f }
8+
end
69

710
# manually load the custom initializer before everything else
811
initializer :load_custom_rails_config, :before => :load_environment_config, :group => :all do

lib/rails_config/options.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,24 @@ def add_source!(source)
1616
@config_sources << source
1717
end
1818

19+
def reload_env!
20+
conf = Hash.new
21+
ENV.each do |key, value|
22+
next unless key.to_s.index(RailsConfig.const_name) == 0
23+
hash = value
24+
key.to_s.split('.').reverse.each do |element|
25+
hash = {element => hash}
26+
end
27+
DeepMerge.deep_merge!(hash, conf, :preserve_unmergeables => false)
28+
end
29+
30+
merge!(conf[RailsConfig.const_name] || {})
31+
32+
return self
33+
end
34+
35+
alias :load_env! :reload_env!
36+
1937
# look through all our sources and rebuild the configuration
2038
def reload!
2139
conf = {}
@@ -32,6 +50,8 @@ def reload!
3250
# swap out the contents of the OStruct with a hash (need to recursively convert)
3351
marshal_load(__convert(conf).marshal_dump)
3452

53+
reload_env! if RailsConfig.use_env
54+
3555
return self
3656
end
3757

lib/rails_config/railtie.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require 'rails'
2+
module RailsConfig
3+
class Railtie < Rails::Railtie
4+
rake_tasks do
5+
Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
6+
end
7+
end
8+
end

lib/rails_config/tasks/heroku.rake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require 'rails_config'
2+
require 'tasks.rb'
3+
namespace 'rails_config' do
4+
task :heroku => :environment do |_, args|
5+
RailsConfig::Tasks::Heroku.new(args[:app]).invoke
6+
end
7+
end

lib/rails_config/tasks/task.rake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
task :test do
2+
puts 'A test task'
3+
end

lib/tasks.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require "bundler"
2+
3+
module RailsConfig
4+
module Tasks
5+
class Heroku < Struct.new(:app)
6+
def invoke
7+
puts 'Setting vars...'
8+
heroku_command = "config:set #{vars}"
9+
heroku(heroku_command)
10+
puts 'Vars set:'
11+
puts heroku_command
12+
end
13+
14+
def vars
15+
# Load only local options to Heroku
16+
RailsConfig.load_and_set_settings(
17+
Rails.root.join("config", "settings.local.yml").to_s,
18+
Rails.root.join("config", "settings", "#{environment}.local.yml").to_s,
19+
Rails.root.join("config", "environments", "#{environment}.local.yml").to_s
20+
)
21+
22+
out = ''
23+
dotted_hash = to_dotted_hash Kernel.const_get(RailsConfig.const_name).to_hash
24+
dotted_hash.each {|key, value| out += " #{key}=#{value} "}
25+
out
26+
end
27+
28+
def environment
29+
heroku("run 'echo $RAILS_ENV'").chomp[/(\w+)\z/]
30+
end
31+
32+
def heroku(command)
33+
with_app = app ? " --app #{app}" : ""
34+
`heroku #{command}#{with_app}`
35+
#puts "heroku #{command}#{with_app}"
36+
end
37+
38+
def `(command)
39+
Bundler.with_clean_env { super }
40+
end
41+
42+
def to_dotted_hash(source, target = {}, namespace = nil)
43+
prefix = "#{namespace}." if namespace
44+
case source
45+
when Hash
46+
source.each do |key, value|
47+
to_dotted_hash(value, target, "#{prefix}#{key}")
48+
end
49+
when Array
50+
source.each_with_index do |value, index|
51+
to_dotted_hash(value, target, "#{prefix}#{index}")
52+
end
53+
else
54+
target[namespace] = source
55+
end
56+
target
57+
end
58+
end
59+
end
60+
end

spec/fixtures/env/settings.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Settings.test_var: 123
2+
Settings.size: 3
3+
Settings.hash_test.one: 1-1
4+
Settings.hash_test.two: 1-2

spec/rails_config_spec.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,45 @@
6666
Settings.size.should eq 2
6767
end
6868

69+
context "ENV variables" do
70+
let(:config) do
71+
RailsConfig.load_files(setting_path("settings.yml"))
72+
end
73+
74+
before :all do
75+
load_env(setting_path('env/settings.yml'))
76+
RailsConfig.use_env = true
77+
end
78+
after :all do
79+
RailsConfig.use_env = false
80+
end
81+
82+
it "should load basic ENV variables" do
83+
config.load_env!
84+
config.test_var.should eq "123"
85+
end
86+
87+
it "should load nested sections" do
88+
config.load_env!
89+
config.hash_test.one.should eq "1-1"
90+
end
91+
92+
it "should override settings from files" do
93+
RailsConfig.load_and_set_settings [setting_path("settings.yml")]
94+
95+
Settings.server.should eq "google.com"
96+
Settings.size.should eq "3"
97+
end
98+
99+
it "should reload env" do
100+
RailsConfig.load_and_set_settings [setting_path("settings.yml")]
101+
RailsConfig.reload!
102+
103+
Settings.server.should eq "google.com"
104+
Settings.size.should eq "3"
105+
end
106+
end
107+
69108
context "Nested Settings" do
70109
let(:config) do
71110
RailsConfig.load_files(setting_path("development.yml"))

spec/spec_helper.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,13 @@ def setting_path(filename)
2121
@fixture_path.join(filename)
2222
end
2323

24+
# loads ENV vars from a file
25+
def load_env(filename)
26+
if filename and File.exists?(filename.to_s)
27+
result = YAML.load(ERB.new(IO.read(filename.to_s)).result)
28+
end
29+
result.each { |key, value| ENV[key.to_s] = value.to_s } unless result.nil?
30+
end
31+
2432
end
2533

0 commit comments

Comments
 (0)