mguymon-figaro 0.7.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/.gitignore +6 -0
- data/.travis.yml +19 -0
- data/Gemfile +13 -0
- data/LICENSE +22 -0
- data/README.md +139 -0
- data/Rakefile +6 -0
- data/figaro.gemspec +20 -0
- data/gemfiles/rails30.gemfile +11 -0
- data/gemfiles/rails31.gemfile +11 -0
- data/gemfiles/rails32.gemfile +11 -0
- data/gemfiles/rails40.gemfile +11 -0
- data/lib/figaro.rb +26 -0
- data/lib/figaro/application.rb +77 -0
- data/lib/figaro/env.rb +37 -0
- data/lib/figaro/error.rb +6 -0
- data/lib/figaro/rails.rb +9 -0
- data/lib/figaro/rails/application.rb +21 -0
- data/lib/figaro/rails/railtie.rb +13 -0
- data/lib/figaro/rails/tasks.rake +6 -0
- data/lib/figaro/tasks.rb +28 -0
- data/lib/generators/figaro/install/install_generator.rb +23 -0
- data/lib/generators/figaro/install/templates/application.yml +7 -0
- data/spec/figaro/application_spec.rb +244 -0
- data/spec/figaro/env_spec.rb +177 -0
- data/spec/figaro/rails/application_spec.rb +43 -0
- data/spec/figaro/tasks_spec.rb +71 -0
- data/spec/figaro_spec.rb +62 -0
- data/spec/rails_spec.rb +67 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/aruba.rb +10 -0
- data/spec/support/rake.rb +11 -0
- data/spec/support/reset.rb +6 -0
- metadata +127 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module Figaro
|
2
|
+
module Rails
|
3
|
+
class Application < Figaro::Application
|
4
|
+
private
|
5
|
+
|
6
|
+
def default_path
|
7
|
+
rails_not_initialized! unless ::Rails.root
|
8
|
+
|
9
|
+
::Rails.root.join("config", "application.yml")
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_environment
|
13
|
+
::Rails.env
|
14
|
+
end
|
15
|
+
|
16
|
+
def rails_not_initialized!
|
17
|
+
raise RailsNotInitialized
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/figaro/tasks.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
module Figaro
|
4
|
+
module Tasks
|
5
|
+
class Heroku < Struct.new(:app)
|
6
|
+
def invoke
|
7
|
+
heroku("config:set #{vars}")
|
8
|
+
end
|
9
|
+
|
10
|
+
def vars
|
11
|
+
Figaro.vars(environment)
|
12
|
+
end
|
13
|
+
|
14
|
+
def environment
|
15
|
+
heroku("run 'echo $RAILS_ENV'").chomp[/(\w+)\z/]
|
16
|
+
end
|
17
|
+
|
18
|
+
def heroku(command)
|
19
|
+
with_app = app ? " --app #{app}" : ""
|
20
|
+
`heroku #{command}#{with_app}`
|
21
|
+
end
|
22
|
+
|
23
|
+
def `(command)
|
24
|
+
Bundler.with_clean_env { super }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Figaro
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < ::Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
|
6
|
+
def create_configuration
|
7
|
+
copy_file("application.yml", "config/application.yml")
|
8
|
+
end
|
9
|
+
|
10
|
+
def ignore_configuration
|
11
|
+
if File.exists?(".gitignore")
|
12
|
+
append_to_file(".gitignore") do
|
13
|
+
<<-EOF.strip_heredoc
|
14
|
+
|
15
|
+
# Ignore application configuration
|
16
|
+
/config/application.yml
|
17
|
+
EOF
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Add application configuration variables here, as shown below.
|
2
|
+
#
|
3
|
+
# PUSHER_APP_ID: "2954"
|
4
|
+
# PUSHER_KEY: 7381a978f7dd7f9a1117
|
5
|
+
# PUSHER_SECRET: abdc3b896a0ffb85d373
|
6
|
+
# STRIPE_API_KEY: EdAvEPVEC3LuaTg5Q3z6WbDVqZlcBQ8Z
|
7
|
+
# STRIPE_PUBLIC_KEY: pk_BRgD57O8fHja9HxduJUszhef6jCyS
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "tempfile"
|
4
|
+
|
5
|
+
module Figaro
|
6
|
+
describe Application do
|
7
|
+
before do
|
8
|
+
Application.any_instance.stub(
|
9
|
+
default_path: "/path/to/app/config/application.yml",
|
10
|
+
default_environment: "development"
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#path" do
|
15
|
+
it "uses the default" do
|
16
|
+
application = Application.new
|
17
|
+
|
18
|
+
expect(application.path).to eq("/path/to/app/config/application.yml")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is configurable via initialization" do
|
22
|
+
application = Application.new(path: "/app/env.yml")
|
23
|
+
|
24
|
+
expect(application.path).to eq("/app/env.yml")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "is configurable via setter" do
|
28
|
+
application = Application.new
|
29
|
+
application.path = "/app/env.yml"
|
30
|
+
|
31
|
+
expect(application.path).to eq("/app/env.yml")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "casts to string" do
|
35
|
+
application = Application.new(path: Pathname.new("/app/env.yml"))
|
36
|
+
|
37
|
+
expect(application.path).to eq("/app/env.yml")
|
38
|
+
expect(application.environment).not_to be_a(Pathname)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "follows a changing default" do
|
42
|
+
application = Application.new
|
43
|
+
|
44
|
+
expect {
|
45
|
+
application.stub(default_path: "/app/env.yml")
|
46
|
+
}.to change {
|
47
|
+
application.path
|
48
|
+
}.from("/path/to/app/config/application.yml").to("/app/env.yml")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#environment" do
|
53
|
+
it "uses the default" do
|
54
|
+
application = Application.new
|
55
|
+
|
56
|
+
expect(application.environment).to eq("development")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is configurable via initialization" do
|
60
|
+
application = Application.new(environment: "test")
|
61
|
+
|
62
|
+
expect(application.environment).to eq("test")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "is configurable via setter" do
|
66
|
+
application = Application.new
|
67
|
+
application.environment = "test"
|
68
|
+
|
69
|
+
expect(application.environment).to eq("test")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "casts to string" do
|
73
|
+
application = Application.new(environment: ActiveSupport::StringInquirer.new("test"))
|
74
|
+
|
75
|
+
expect(application.environment).to eq("test")
|
76
|
+
expect(application.environment).not_to be_an(ActiveSupport::StringInquirer)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "follows a changing default" do
|
80
|
+
application = Application.new
|
81
|
+
|
82
|
+
expect {
|
83
|
+
application.stub(default_environment: "test")
|
84
|
+
}.to change {
|
85
|
+
application.environment
|
86
|
+
}.from("development").to("test")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#configuration" do
|
91
|
+
def yaml_to_path(yaml)
|
92
|
+
Tempfile.open("figaro") do |file|
|
93
|
+
file.write(yaml)
|
94
|
+
file.path
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "loads values from YAML" do
|
99
|
+
application = Application.new(path: yaml_to_path(<<-YAML))
|
100
|
+
foo: bar
|
101
|
+
YAML
|
102
|
+
|
103
|
+
expect(application.configuration).to eq("foo" => "bar")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "merges environment-specific values" do
|
107
|
+
application = Application.new(path: yaml_to_path(<<-YAML), environment: "test")
|
108
|
+
foo: bar
|
109
|
+
test:
|
110
|
+
foo: baz
|
111
|
+
YAML
|
112
|
+
|
113
|
+
expect(application.configuration).to eq("foo" => "baz")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "drops unused environment-specific values" do
|
117
|
+
application = Application.new(path: yaml_to_path(<<-YAML), environment: "test")
|
118
|
+
foo: bar
|
119
|
+
test:
|
120
|
+
foo: baz
|
121
|
+
production:
|
122
|
+
foo: bad
|
123
|
+
YAML
|
124
|
+
|
125
|
+
expect(application.configuration).to eq("foo" => "baz")
|
126
|
+
end
|
127
|
+
|
128
|
+
it "is empty when no YAML file is present" do
|
129
|
+
application = Application.new(path: "/path/to/nowhere")
|
130
|
+
|
131
|
+
expect(application.configuration).to eq({})
|
132
|
+
end
|
133
|
+
|
134
|
+
it "is empty when the YAML file is blank" do
|
135
|
+
application = Application.new(path: yaml_to_path(""))
|
136
|
+
|
137
|
+
expect(application.configuration).to eq({})
|
138
|
+
end
|
139
|
+
|
140
|
+
it "is empty when the YAML file contains only comments" do
|
141
|
+
application = Application.new(path: yaml_to_path(<<-YAML))
|
142
|
+
# Comment
|
143
|
+
YAML
|
144
|
+
|
145
|
+
expect(application.configuration).to eq({})
|
146
|
+
end
|
147
|
+
|
148
|
+
it "processes ERB" do
|
149
|
+
application = Application.new(path: yaml_to_path(<<-YAML))
|
150
|
+
foo: <%= "bar".upcase %>
|
151
|
+
YAML
|
152
|
+
|
153
|
+
expect(application.configuration).to eq("foo" => "BAR")
|
154
|
+
end
|
155
|
+
|
156
|
+
it "follows a changing default path" do
|
157
|
+
path_1 = yaml_to_path("foo: bar")
|
158
|
+
path_2 = yaml_to_path("foo: baz")
|
159
|
+
|
160
|
+
application = Application.new
|
161
|
+
application.stub(default_path: path_1)
|
162
|
+
|
163
|
+
expect {
|
164
|
+
application.stub(default_path: path_2)
|
165
|
+
}.to change {
|
166
|
+
application.configuration
|
167
|
+
}.from("foo" => "bar").to("foo" => "baz")
|
168
|
+
end
|
169
|
+
|
170
|
+
it "follows a changing default environment" do
|
171
|
+
application = Application.new(path: yaml_to_path(<<-YAML))
|
172
|
+
foo: bar
|
173
|
+
test:
|
174
|
+
foo: baz
|
175
|
+
YAML
|
176
|
+
application.stub(default_environment: "development")
|
177
|
+
|
178
|
+
expect {
|
179
|
+
application.stub(default_environment: "test")
|
180
|
+
}.to change {
|
181
|
+
application.configuration
|
182
|
+
}.from("foo" => "bar").to("foo" => "baz")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#load" do
|
187
|
+
let!(:application) { Application.new }
|
188
|
+
|
189
|
+
before do
|
190
|
+
::ENV.delete("foo")
|
191
|
+
::ENV.delete("FIGARO_foo")
|
192
|
+
|
193
|
+
application.stub(configuration: { "foo" => "bar" })
|
194
|
+
end
|
195
|
+
|
196
|
+
it "merges values into ENV" do
|
197
|
+
expect {
|
198
|
+
application.load
|
199
|
+
}.to change {
|
200
|
+
::ENV["foo"]
|
201
|
+
}.from(nil).to("bar")
|
202
|
+
end
|
203
|
+
|
204
|
+
it "skips keys that have already been set externally" do
|
205
|
+
::ENV["foo"] = "baz"
|
206
|
+
|
207
|
+
expect {
|
208
|
+
application.load
|
209
|
+
}.not_to change {
|
210
|
+
::ENV["foo"]
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
it "sets keys that have already been set internally" do
|
215
|
+
application.load
|
216
|
+
|
217
|
+
application2 = Application.new
|
218
|
+
application2.stub(configuration: { "foo" => "baz" })
|
219
|
+
|
220
|
+
expect {
|
221
|
+
application2.load
|
222
|
+
}.to change {
|
223
|
+
::ENV["foo"]
|
224
|
+
}.from("bar").to("baz")
|
225
|
+
end
|
226
|
+
|
227
|
+
it "warns when a key isn't a string" do
|
228
|
+
application.stub(configuration: { foo: "bar" })
|
229
|
+
|
230
|
+
expect(application).to receive(:warn).once
|
231
|
+
|
232
|
+
application.load
|
233
|
+
end
|
234
|
+
|
235
|
+
it "warns when a value isn't a string" do
|
236
|
+
application.stub(configuration: { "foo" => ["bar"] })
|
237
|
+
|
238
|
+
expect(application).to receive(:warn).once
|
239
|
+
|
240
|
+
application.load
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Figaro::ENV do
|
4
|
+
subject(:env) { Figaro::ENV }
|
5
|
+
|
6
|
+
before do
|
7
|
+
ENV["HELLO"] = "world"
|
8
|
+
ENV["foo"] = "bar"
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
ENV.delete("HELLO")
|
13
|
+
ENV.delete("foo")
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#method_missing" do
|
17
|
+
context "plain methods" do
|
18
|
+
it "makes ENV values accessible as lowercase methods" do
|
19
|
+
expect(env.hello).to eq("world")
|
20
|
+
expect(env.foo).to eq("bar")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "makes ENV values accessible as uppercase methods" do
|
24
|
+
expect(env.HELLO).to eq("world")
|
25
|
+
expect(env.FOO).to eq("bar")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "makes ENV values accessible as mixed-case methods" do
|
29
|
+
expect(env.Hello).to eq("world")
|
30
|
+
expect(env.fOO).to eq("bar")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns nil if no ENV key matches" do
|
34
|
+
expect(env.goodbye).to eq(nil)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "bang methods" do
|
39
|
+
it "makes ENV values accessible as lowercase methods" do
|
40
|
+
expect(env.hello!).to eq("world")
|
41
|
+
expect(env.foo!).to eq("bar")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "makes ENV values accessible as uppercase methods" do
|
45
|
+
expect(env.HELLO!).to eq("world")
|
46
|
+
expect(env.FOO!).to eq("bar")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "makes ENV values accessible as mixed-case methods" do
|
50
|
+
expect(env.Hello!).to eq("world")
|
51
|
+
expect(env.fOO!).to eq("bar")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises an error if no ENV key matches" do
|
55
|
+
expect { env.goodbye! }.to raise_error(Figaro::MissingKey)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "boolean methods" do
|
60
|
+
it "returns true for accessible, lowercase methods" do
|
61
|
+
expect(env.hello?).to eq(true)
|
62
|
+
expect(env.foo?).to eq(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns true for accessible, uppercase methods" do
|
66
|
+
expect(env.HELLO?).to eq(true)
|
67
|
+
expect(env.FOO?).to eq(true)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns true for accessible, mixed-case methods" do
|
71
|
+
expect(env.Hello?).to eq(true)
|
72
|
+
expect(env.fOO?).to eq(true)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns false if no ENV key matches" do
|
76
|
+
expect(env.goodbye?).to eq(false)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "setter methods" do
|
81
|
+
it "raises an error" do
|
82
|
+
expect { env.foo = "bar" }.to raise_error(NoMethodError)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#respond_to?" do
|
88
|
+
context "plain methods" do
|
89
|
+
context "when ENV has the key" do
|
90
|
+
it "is true for a lowercase method" do
|
91
|
+
expect(env.respond_to?(:hello)).to eq(true)
|
92
|
+
expect(env.respond_to?(:foo)).to eq(true)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "is true for a uppercase method" do
|
96
|
+
expect(env.respond_to?(:HELLO)).to eq(true)
|
97
|
+
expect(env.respond_to?(:FOO)).to eq(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "is true for a mixed-case key" do
|
101
|
+
expect(env.respond_to?(:Hello)).to eq(true)
|
102
|
+
expect(env.respond_to?(:fOO)).to eq(true)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when ENV doesn't have the key" do
|
107
|
+
it "is true" do
|
108
|
+
expect(env.respond_to?(:baz)).to eq(true)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "bang methods" do
|
114
|
+
context "when ENV has the key" do
|
115
|
+
it "is true for a lowercase method" do
|
116
|
+
expect(env.respond_to?(:hello!)).to eq(true)
|
117
|
+
expect(env.respond_to?(:foo!)).to eq(true)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "is true for a uppercase method" do
|
121
|
+
expect(env.respond_to?(:HELLO!)).to eq(true)
|
122
|
+
expect(env.respond_to?(:FOO!)).to eq(true)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "is true for a mixed-case key" do
|
126
|
+
expect(env.respond_to?(:Hello!)).to eq(true)
|
127
|
+
expect(env.respond_to?(:fOO!)).to eq(true)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when ENV doesn't have the key" do
|
132
|
+
it "is false" do
|
133
|
+
expect(env.respond_to?(:baz!)).to eq(false)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "boolean methods" do
|
139
|
+
context "when ENV has the key" do
|
140
|
+
it "is true for a lowercase method" do
|
141
|
+
expect(env.respond_to?(:hello?)).to eq(true)
|
142
|
+
expect(env.respond_to?(:foo?)).to eq(true)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "is true for a uppercase method" do
|
146
|
+
expect(env.respond_to?(:HELLO?)).to eq(true)
|
147
|
+
expect(env.respond_to?(:FOO?)).to eq(true)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "is true for a mixed-case key" do
|
151
|
+
expect(env.respond_to?(:Hello?)).to eq(true)
|
152
|
+
expect(env.respond_to?(:fOO?)).to eq(true)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when ENV doesn't have the key" do
|
157
|
+
it "is true" do
|
158
|
+
expect(env.respond_to?(:baz?)).to eq(true)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "setter methods" do
|
164
|
+
context "when ENV has the key" do
|
165
|
+
it "is false" do
|
166
|
+
expect(env.respond_to?(:foo=)).to eq(false)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "when ENV doesn't have the key" do
|
171
|
+
it "is false" do
|
172
|
+
expect(env.respond_to?(:baz=)).to eq(false)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|