abstract_feature_branch 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +138 -37
  3. data/VERSION +1 -1
  4. data/abstract_feature_branch.gemspec +26 -11
  5. data/config/features/admin.local.yml +2 -1
  6. data/config/features/admin.yml +2 -1
  7. data/config/features/internal/wiki.local.yml +2 -1
  8. data/config/features/internal/wiki.yml +2 -1
  9. data/config/features/public.local.yml +2 -1
  10. data/config/features/public.yml +2 -1
  11. data/lib/abstract_feature_branch.rb +14 -3
  12. data/lib/abstract_feature_branch/file_beautifier.rb +63 -0
  13. data/lib/generators/abstract_feature_branch/install_generator.rb +1 -0
  14. data/lib/generators/templates/config/features.local.yml +1 -0
  15. data/lib/generators/templates/config/initializers/abstract_feature_branch.rb +3 -0
  16. data/lib/generators/templates/lib/tasks/abstract_feature_branch.rake +9 -0
  17. data/spec/abstract_feature_branch/file_beautifier_spec.rb +384 -0
  18. data/spec/ext/feature_branch__feature_branch_spec.rb +145 -0
  19. data/spec/ext/feature_branch__feature_enabled_spec.rb +84 -0
  20. data/spec/{application_no_config → fixtures/application_no_config}/no_config +0 -0
  21. data/spec/{application_rails_config → fixtures/application_rails_config}/config/features.local.yml +1 -0
  22. data/spec/{application_rails_config → fixtures/application_rails_config}/config/features.yml +0 -0
  23. data/spec/fixtures/application_ugly_config_reference/config/another_application_configuration.yml +31 -0
  24. data/spec/fixtures/application_ugly_config_reference/config/database.yml +17 -0
  25. data/spec/fixtures/application_ugly_config_reference/config/features.local.yml +44 -0
  26. data/spec/fixtures/application_ugly_config_reference/config/features.yml +49 -0
  27. data/spec/fixtures/application_ugly_config_reference/config/features/admin.local.yml +44 -0
  28. data/spec/fixtures/application_ugly_config_reference/config/features/admin.yml +44 -0
  29. data/spec/fixtures/application_ugly_config_reference/config/features/empty.local.yml +0 -0
  30. data/spec/fixtures/application_ugly_config_reference/config/features/feature_empty_config.local.yml +13 -0
  31. data/spec/fixtures/application_ugly_config_reference/config/features/including_comments.local.yml +52 -0
  32. data/spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.local.yml +44 -0
  33. data/spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.yml +44 -0
  34. data/spec/fixtures/application_ugly_config_reference/config/features/public.local.yml +44 -0
  35. data/spec/fixtures/application_ugly_config_reference/config/features/public.yml +44 -0
  36. metadata +46 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39c4f8aecce089f175cc513abd3aafad9496eed3
4
- data.tar.gz: eee7c48b9f9a6e8f10e834f472cc46257399a155
3
+ metadata.gz: 695366cdc70dc9883e9bcfcc498c384d8b52620c
4
+ data.tar.gz: 9850c42b60dd40e604500acac757ea21598dd339
5
5
  SHA512:
6
- metadata.gz: 55903d3949b2f5c619d8d11ef45f829df1e1f9fdfcde2f714db9fe807eef138a9d9f758e345f9a8cd5941d2be6901a6cea57ed4b3aa1d712c14d61a7a2d7ea0d
7
- data.tar.gz: 5a85cb2406e37bb19f9adb933d6180123abfef0c48f2f0ca2ca7f2a9cbce36de2e0584d8123f883b841b44632111e3f3a1dbf35857704a2e1d6c5f95536df6bb
6
+ metadata.gz: 918fdebd4a2ea0b5f600141910d816573721434bb3931dd7d0e881815adfec0f5c0da2c084e1e5cd1a667c812a9ca95457929ef16b1afa477202c40c7db5861b
7
+ data.tar.gz: a1a7c5fceca419639dee473ee41d38ef9b0d9bb7f1aff55242d7fa4147e71ee950c860a8dac8172ce1c3a1e11b3c0c46f85894a4f36a9030410dae18368320af
data/README.md CHANGED
@@ -7,10 +7,10 @@ abstract_feature_branch is a Rails gem that enables developers to easily branch
7
7
  http://paulhammant.com/blog/branch_by_abstraction.html
8
8
 
9
9
  It is a productivity and fault tolerance enhancing team practice that has been utilized by professional software development
10
- teams at large corporations, such as Sears and Groupon.
10
+ teams at large corporations, such as [Sears](http://www.sears.com) and [Groupon](http://www.groupon.com).
11
11
 
12
- It gives ability to wrap blocks of code with an abstract feature branch name, and then
13
- specify which features to be switched on or off in a configuration file.
12
+ It provides the ability to wrap blocks of code with an abstract feature branch name, and then
13
+ specify in a configuration file which features to be switched on or off.
14
14
 
15
15
  The goal is to build out upcoming features in the same source code repository branch, regardless of whether all are
16
16
  completed by the next release date or not, thus increasing team productivity by preventing integration delays.
@@ -21,7 +21,7 @@ This gives developers the added benefit of being able to switch a feature off af
21
21
  for a high risk feature.
22
22
 
23
23
  abstract_feature_branch additionally supports [DDD](http://www.domaindrivendesign.org)'s pattern of
24
- [bounded contexts](http://dddcommunity.org/uncategorized/bounded-context/) by allowing developers to configure
24
+ [Bounded Contexts](http://dddcommunity.org/uncategorized/bounded-context/) by allowing developers to configure
25
25
  context-specific feature files if needed.
26
26
 
27
27
  Requirements
@@ -32,25 +32,26 @@ Requirements
32
32
  Setup
33
33
  -----
34
34
 
35
- ### Rails Application
35
+ ### Rails Application Use
36
36
 
37
37
  1. Configure Rubygem
38
- - Rails (~> 4.0.0 or ~> 3.0): Add the following to Gemfile <pre>gem 'abstract_feature_branch', '0.7.1'</pre>
39
- - Rails (~> 2.0): Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '0.7.1'</pre>
40
- 2. Generate <code>config/initializers/abstract_feature_branch.rb</code>, <code>config/features.yml</code> and <code>config/features.local.yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:install</pre>
41
- 3. (Optional) Generate <code>config/features/[context_path].yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:context context_path</pre> (more details under **instructions**)
38
+ - Rails (~> 4.0.0 or ~> 3.0): Add the following to Gemfile <pre>gem 'abstract_feature_branch', '0.8.0'</pre>
39
+ - Rails (~> 2.0): Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '0.8.0'</pre>
40
+ 2. Generate <code>config/initializers/abstract_feature_branch.rb</code>, <code>lib/tasks/abstract_feature_branch.rake</code>, <code>config/features.yml</code> and <code>config/features.local.yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:install</pre>
41
+ 3. (Optional) Generate <code>config/features/[context_path].yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:context context_path</pre> (more details under [**instructions**](#instructions))
42
42
  4. (Optional and rarely needed) Customize configuration in <code>config/initializers/abstract_feature_branch.rb</code> (can be useful for changing location of feature files in Rails application or troubleshooting a specific Rails environment feature configuration)
43
43
 
44
- ### Ruby Application (general use)
44
+ ### Ruby Application General Use
45
45
 
46
- 1. <pre>gem install abstract_feature_branch -v 0.7.1</pre>
46
+ 1. <pre>gem install abstract_feature_branch -v 0.8.0</pre>
47
47
  2. Add code <code>require 'abstract_feature_branch'</code>
48
- 3. Create <code>config/features.yml</code> under <code>AbstractFeatureBranch.application_root</code> and fill it with content similar to that of the sample <code>config/features.yml</code> mentioned under **instructions**.
49
- 4. (Optional) Create <code>config/features.local.yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under **instructions**)
50
- 5. (Optional) Create <code>config/features/[context_path].yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under **instructions**)
48
+ 3. Create <code>config/features.yml</code> under <code>AbstractFeatureBranch.application_root</code> and fill it with content similar to that of the sample <code>config/features.yml</code> mentioned under [**instructions**](#instructions).
49
+ 4. (Optional) Create <code>config/features.local.yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under [**instructions**](#instructions))
50
+ 5. (Optional) Create <code>config/features/[context_path].yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under [**instructions**](#instructions))
51
51
  6. (Optional) Add code <code>AbstractFeatureBranch.application_root = "[your_application_path]"</code> to configure the location of feature files (it defaults to <code>'.'</code>)
52
52
  7. (Optional) Add code <code>AbstractFeatureBranch.application_environment = "[your_application_environment]"</code> (it defaults to <code>'development'</code>). Alternatively, you can set <code>ENV['APP_ENV']</code> before the <code>require</code> statement or an an external environment variable.
53
- 8. (Optional) Add code <code>AbstractFeatureBranch.load_application_features</code> to pre-load application features for improved first-use performance
53
+ 8. (Optional) Add code <code>AbstractFeatureBranch.logger = "[your_application_logger]"</code> (it defaults to a new instance of Ruby <code>Logger</code>. Must use a logger with <code>info</code> and <code>warn</code> methods).
54
+ 9. (Optional) Add code <code>AbstractFeatureBranch.load_application_features</code> to pre-load application features for improved first-use performance
54
55
 
55
56
  Instructions
56
57
  ------------
@@ -128,20 +129,6 @@ Note that <code>feature_branch</code> executes the false branch if the feature i
128
129
 
129
130
  Note that <code>feature_enabled?</code> returns false if the feature is disabled and nil if the feature is non-existent (practically the same effect, but nil can sometimes be useful to detect if a feature is referenced).
130
131
 
131
- Initializer
132
- -----------
133
-
134
- Here is the content of the generated initializer (<code>config/initializers/abstract_feature_branch.rb</code>), which contains instructions on how to customize:
135
-
136
- > # Application root where config/features.yml or config/features/ is found
137
- > AbstractFeatureBranch.application_root = Rails.root
138
- >
139
- > # Application environment (e.g. "development", "staging" or "production")
140
- > AbstractFeatureBranch.application_environment = Rails.env.to_s
141
- >
142
- > # Pre-loads application features to improve performance of first web-page hit
143
- > AbstractFeatureBranch.load_application_features
144
-
145
132
  Recommendations
146
133
  ---------------
147
134
 
@@ -199,11 +186,11 @@ simply switching off the URL route to them. Example:
199
186
  > }
200
187
 
201
188
  - Once a feature has been released and switched on in production, and it has worked well for a while (e.g. for two consecutive releases),
202
- it is recommended that its feature branching code is plucked out of the codebase to simplify and improve
189
+ it is **strongly recommended** that its feature branching code is plucked out of the codebase to simplify and improve
203
190
  future maintainability given that it is no longer needed at that point.
204
191
 
205
- - Split <code>config/features.yml</code> into multiple context-specific feature files once it grows too big (e.g. 20+ features) by
206
- utilizing the context generator mentioned above: <pre>rails g abstract_feature_branch:context context_path</pre>
192
+ - Once <code>config/features.yml</code> grows too big (e.g. 20+ features), it is **strongly recommended* to split it into
193
+ multiple context-specific feature files by utilizing the context generator mentioned above: <pre>rails g abstract_feature_branch:context context_path</pre>
207
194
 
208
195
  - When working on a new feature locally that the developer does not want others on the team to see yet, the feature
209
196
  can be enabled in <code>config/features.local.yml</code> only as it is git ignored, and disabled in <code>config/features.yml</code>
@@ -262,11 +249,12 @@ Gotcha with abstract feature branching in CSS and JS files:
262
249
 
263
250
  If you've used abstract feature branching in CSS or JS files via ERB, setting environment variable overrides won't
264
251
  affect them as you need asset recompilation in addition to it, which can only be triggered by changing a CSS or JS
265
- file and redeploying on Heroku (hint: even if it's just a minor change to force it). In any case, environment variable
252
+ file and redeploying on Heroku (even if it's just a minor change to force it). In any case, environment variable
266
253
  overrides have been recommended above as an emergency or temporary measure. If there is a need to rely on environment
267
- variable overrides to alter the style or JavaScript behavior of a page back and forth without a redeploy, one solution
268
- is to do additional abstract feature branching in HTML templates (e.g. ERB or HAML templates) to link to different
269
- CSS classes or invoke different JavaScript methods per branch of HTML for example.
254
+ variable overrides to alter the style or JavaScript behavior of a page back and forth without a redeploy, **one solution**
255
+ is to do additional abstract feature branching in HTML templates (e.g. ERB or [HAML](http://haml.info) to
256
+ link to different stylesheets and JS files, use different CSS classes, or invoke different JavaScript methods per branch
257
+ of HTML for example.
270
258
 
271
259
  Feature Configuration Load Order
272
260
  --------------------------------
@@ -280,9 +268,119 @@ the former if overlap in features occurs:
280
268
  4. Main local feature file override: <code>config/features.local.yml</code>
281
269
  5. Environment variable overrides
282
270
 
271
+ Rails Initializer
272
+ -----------------
273
+
274
+ Here is the content of the generated initializer (<code>config/initializers/abstract_feature_branch.rb</code>), which contains instructions on how to customize via [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection):
275
+
276
+ > # Application root where config/features.yml or config/features/ is found
277
+ > AbstractFeatureBranch.application_root = Rails.root
278
+ >
279
+ > # Application environment (e.g. "development", "staging" or "production")
280
+ > AbstractFeatureBranch.application_environment = Rails.env.to_s
281
+ >
282
+ > # Abstract Feature Branch logger
283
+ > AbstractFeatureBranch.logger = Rails.logger
284
+ >
285
+ > # Pre-loads application features to improve performance of first web-page hit
286
+ > AbstractFeatureBranch.load_application_features
287
+
288
+ Rake Task
289
+ ---------
290
+
291
+ Abstract Feature Branch comes with a rake task to beautify feature files that have grown unorganized by sorting features
292
+ by name and getting rid of extra empty lines. It does so per section, without affecting the order of the sections
293
+ themselves.
294
+
295
+ For example, here is content before and after beautification.
296
+
297
+ Before:
298
+
299
+ > defaults: &defaults
300
+ >
301
+ >
302
+ > gallery: true
303
+ >
304
+ > carousel: true
305
+ >
306
+ > third_party_integration: false
307
+ > caching: true
308
+ >
309
+ > development:
310
+ > <<: *defaults
311
+ >
312
+ > test:
313
+ > <<: *defaults
314
+ >
315
+ > caching: false
316
+ >
317
+ > staging:
318
+ > <<: *defaults
319
+ > third_party_integration: true
320
+ > caching: true
321
+ >
322
+ > production:
323
+ > <<: *defaults
324
+ > third_party_integration: false
325
+ >
326
+ > caching: false
327
+
328
+ After:
329
+
330
+ > defaults: &defaults
331
+ > caching: true
332
+ > carousel: true
333
+ > gallery: true
334
+ > third_party_integration: false
335
+ >
336
+ > development:
337
+ > <<: *defaults
338
+ >
339
+ > test:
340
+ > <<: *defaults
341
+ > caching: false
342
+ >
343
+ > staging:
344
+ > <<: *defaults
345
+ > caching: true
346
+ > third_party_integration: true
347
+ >
348
+ > production:
349
+ > <<: *defaults
350
+ > caching: false
351
+ > third_party_integration: false
352
+
353
+ This is very useful in bigger applications that have scores of features since it allows a developer to quickly scan
354
+ for alphabetical sorted feature names. Although file find is an alternative solution, having tidy organized feature
355
+ names can help increase overall team productivity in the long term.
356
+
357
+ For Rails application use, the rake task is generated under <code>lib/tasks/abstract_feature_branch.rake</code>.
358
+
359
+ For Ruby application general use, here is the content of the rake task:
360
+
361
+ > namespace :abstract_feature_branch do
362
+ >
363
+ > desc "Beautify YAML of specified feature file via file_path argument or all feature files when no argument specified (config/features.yml, config/features.local.yml, and config/features/**/*.yml) by sorting features by name and eliminating extra empty lines"
364
+ > task :beautify_files, :file_path do |_, args|
365
+ > AbstractFeatureBranch::FileBeautifier.process(args[:file_path])
366
+ > end
367
+ >
368
+ > end
369
+
370
+ The rake task may be invoked in a number of ways:
371
+ - <code>rake abstract_feature_branch:beautify_files</code> beautifies all feature files under [application_root]/config
372
+ - <code>rake abstract_feature_branch:beautify_files[file_path]</code> beautifies a single feature file
373
+ - <code>rake abstract_feature_branch:beautify_files[directory_path]</code> beautifies all feature files under directory path recursively
374
+
375
+ Verify after the task has been invoked that your feature file contents are to your satisfaction before committing the
376
+ task changes.
377
+
283
378
  Release Notes
284
379
  -------------
285
380
 
381
+ Version 0.8.0:
382
+ - Added rake task for beautifying feature files, sorting feature names within environment sections and eliminating extra empty lines. Added support for externalized logger.
383
+
286
384
  Version 0.7.1:
287
385
  - Fixed undefined method issue with using <code>AbstractFeatureBranch.load_application_features</code> to improve first use performance
288
386
 
@@ -330,7 +428,6 @@ Version 0.2.0:
330
428
  Upcoming
331
429
  --------
332
430
 
333
- - Add rake task to reorder feature entries in feature.yml alphabetically
334
431
  - Support runtime read of features yml in development for easy testing purposes (trading off performance)
335
432
  - Support configuring per environment whether features yml is read at runtime or not (given performance trade-off)
336
433
 
@@ -353,6 +450,10 @@ Contributors
353
450
  ---------------------------------------
354
451
  [Christian Nennemann](https://github.com/XORwell)
355
452
 
453
+ Feedback and Idea Providers
454
+ ---------------------------------------
455
+ [Ben Downey](https://github.com/bnd5k)
456
+
356
457
  Copyright
357
458
  ---------------------------------------
358
459
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.1
1
+ 0.8.0
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "abstract_feature_branch"
8
- s.version = "0.7.1"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Annas \"Andy\" Maleh"]
12
12
  s.date = "2013-11-25"
13
- s.description = "It gives ability to wrap blocks of code with an abstract feature branch name, and then\nspecify which features to be switched on or off in a configuration file.\n\nThe goal is to build out future features with full integration into the codebase, thus\nensuring no delay in integration in the future, while releasing currently done features\nat the same time. Developers then disable future features until they are ready to be\nswitched on in production, but do enable them in staging and locally.\n\nThis gives developers the added benefit of being able to switch a feature off after\nrelease should big problems arise for a high risk feature.\n"
13
+ s.description = "abstract_feature_branch is a Rails gem that enables developers to easily branch by abstraction as per this pattern:\nhttp://paulhammant.com/blog/branch_by_abstraction.html\n\nIt is a productivity and fault tolerance enhancing team practice that has been utilized by professional software development\nteams at large corporations, such as Sears and Groupon.\n\nIt provides the ability to wrap blocks of code with an abstract feature branch name, and then\nspecify in a configuration file which features to be switched on or off.\n\nThe goal is to build out upcoming features in the same source code repository branch, regardless of whether all are\ncompleted by the next release date or not, thus increasing team productivity by preventing integration delays.\nDevelopers then disable in-progress features until they are ready to be switched on in production, yet enable them\nlocally and in staging environments for in-progress testing.\n\nThis gives developers the added benefit of being able to switch a feature off after release should big problems arise\nfor a high risk feature.\n\nabstract_feature_branch additionally supports DDD's pattern of\nBounded Contexts by allowing developers to configure\ncontext-specific feature files if needed.\n"
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE.txt",
16
16
  "README.md"
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  "config/features/public.local.yml",
29
29
  "config/features/public.yml",
30
30
  "lib/abstract_feature_branch.rb",
31
+ "lib/abstract_feature_branch/file_beautifier.rb",
31
32
  "lib/ext/feature_branch.rb",
32
33
  "lib/generators/abstract_feature_branch/context_generator.rb",
33
34
  "lib/generators/abstract_feature_branch/install_generator.rb",
@@ -35,9 +36,26 @@ Gem::Specification.new do |s|
35
36
  "lib/generators/templates/config/features.local.yml",
36
37
  "lib/generators/templates/config/features.yml",
37
38
  "lib/generators/templates/config/initializers/abstract_feature_branch.rb",
38
- "spec/application_no_config/no_config",
39
- "spec/application_rails_config/config/features.local.yml",
40
- "spec/application_rails_config/config/features.yml"
39
+ "lib/generators/templates/lib/tasks/abstract_feature_branch.rake",
40
+ "spec/abstract_feature_branch/file_beautifier_spec.rb",
41
+ "spec/ext/feature_branch__feature_branch_spec.rb",
42
+ "spec/ext/feature_branch__feature_enabled_spec.rb",
43
+ "spec/fixtures/application_no_config/no_config",
44
+ "spec/fixtures/application_rails_config/config/features.local.yml",
45
+ "spec/fixtures/application_rails_config/config/features.yml",
46
+ "spec/fixtures/application_ugly_config_reference/config/another_application_configuration.yml",
47
+ "spec/fixtures/application_ugly_config_reference/config/database.yml",
48
+ "spec/fixtures/application_ugly_config_reference/config/features.local.yml",
49
+ "spec/fixtures/application_ugly_config_reference/config/features.yml",
50
+ "spec/fixtures/application_ugly_config_reference/config/features/admin.local.yml",
51
+ "spec/fixtures/application_ugly_config_reference/config/features/admin.yml",
52
+ "spec/fixtures/application_ugly_config_reference/config/features/empty.local.yml",
53
+ "spec/fixtures/application_ugly_config_reference/config/features/feature_empty_config.local.yml",
54
+ "spec/fixtures/application_ugly_config_reference/config/features/including_comments.local.yml",
55
+ "spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.local.yml",
56
+ "spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.yml",
57
+ "spec/fixtures/application_ugly_config_reference/config/features/public.local.yml",
58
+ "spec/fixtures/application_ugly_config_reference/config/features/public.yml"
41
59
  ]
42
60
  s.homepage = "http://github.com/AndyObtiva/abstract_feature_branch"
43
61
  s.licenses = ["MIT"]
@@ -50,20 +68,17 @@ Gem::Specification.new do |s|
50
68
 
51
69
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
70
  s.add_runtime_dependency(%q<deep_merge>, ["= 1.0.0"])
53
- s.add_development_dependency(%q<rspec>, ["= 2.11.0"])
54
- s.add_development_dependency(%q<rdoc>, ["= 3.12.2"])
55
71
  s.add_development_dependency(%q<jeweler>, ["= 1.8.8"])
72
+ s.add_development_dependency(%q<rspec>, ["= 2.14.1"])
56
73
  else
57
74
  s.add_dependency(%q<deep_merge>, ["= 1.0.0"])
58
- s.add_dependency(%q<rspec>, ["= 2.11.0"])
59
- s.add_dependency(%q<rdoc>, ["= 3.12.2"])
60
75
  s.add_dependency(%q<jeweler>, ["= 1.8.8"])
76
+ s.add_dependency(%q<rspec>, ["= 2.14.1"])
61
77
  end
62
78
  else
63
79
  s.add_dependency(%q<deep_merge>, ["= 1.0.0"])
64
- s.add_dependency(%q<rspec>, ["= 2.11.0"])
65
- s.add_dependency(%q<rdoc>, ["= 3.12.2"])
66
80
  s.add_dependency(%q<jeweler>, ["= 1.8.8"])
81
+ s.add_dependency(%q<rspec>, ["= 2.14.1"])
67
82
  end
68
83
  end
69
84
 
@@ -11,4 +11,5 @@ staging:
11
11
  <<: *defaults
12
12
 
13
13
  production:
14
- <<: *defaults
14
+ <<: *defaults
15
+
@@ -13,4 +13,5 @@ staging:
13
13
  <<: *defaults
14
14
 
15
15
  production:
16
- <<: *defaults
16
+ <<: *defaults
17
+
@@ -11,4 +11,5 @@ staging:
11
11
  <<: *defaults
12
12
 
13
13
  production:
14
- <<: *defaults
14
+ <<: *defaults
15
+
@@ -13,4 +13,5 @@ staging:
13
13
  <<: *defaults
14
14
 
15
15
  production:
16
- <<: *defaults
16
+ <<: *defaults
17
+
@@ -11,4 +11,5 @@ staging:
11
11
  <<: *defaults
12
12
 
13
13
  production:
14
- <<: *defaults
14
+ <<: *defaults
15
+
@@ -13,4 +13,5 @@ staging:
13
13
  <<: *defaults
14
14
 
15
15
  production:
16
- <<: *defaults
16
+ <<: *defaults
17
+
@@ -9,6 +9,7 @@ rescue Bundler::BundlerError => e
9
9
  $stderr.puts "Run `bundle install` to install missing gems"
10
10
  exit e.status_code
11
11
  end
12
+ require 'logger' unless defined?(Rails) && Rails.logger
12
13
  require 'deep_merge' unless {}.respond_to?(:deep_merge!)
13
14
 
14
15
  module AbstractFeatureBranch
@@ -19,7 +20,7 @@ module AbstractFeatureBranch
19
20
  @application_root = path
20
21
  end
21
22
  def self.initialize_application_root
22
- self.application_root = Object.const_defined?(:Rails) ? Rails.root : '.'
23
+ self.application_root = defined?(Rails) ? Rails.root : '.'
23
24
  end
24
25
  def self.application_environment
25
26
  @application_environment ||= initialize_application_environment
@@ -28,7 +29,16 @@ module AbstractFeatureBranch
28
29
  @application_environment = environment
29
30
  end
30
31
  def self.initialize_application_environment
31
- self.application_environment = Object.const_defined?(:Rails) ? Rails.env.to_s : ENV['APP_ENV'] || 'development'
32
+ self.application_environment = defined?(Rails) ? Rails.env.to_s : ENV['APP_ENV'] || 'development'
33
+ end
34
+ def self.logger
35
+ @logger ||= initialize_logger
36
+ end
37
+ def self.logger=(logger)
38
+ @logger = logger
39
+ end
40
+ def self.initialize_logger
41
+ self.logger = defined?(Rails) && Rails.logger ? Rails.logger : Logger.new(STDOUT)
32
42
  end
33
43
  def self.environment_variable_overrides
34
44
  @environment_variable_overrides ||= load_environment_variable_overrides
@@ -102,8 +112,9 @@ module AbstractFeatureBranch
102
112
  end
103
113
 
104
114
  def self.downcase_feature_hash_keys(hash)
105
- Hash[hash.map {|k, v| [k, v && downcase_keys(v)]}]
115
+ Hash[(hash || {}).map {|k, v| [k, v && downcase_keys(v)]}]
106
116
  end
107
117
  end
108
118
 
109
119
  require File.join(File.dirname(__FILE__), 'ext', 'feature_branch')
120
+ require File.join(File.dirname(__FILE__), 'abstract_feature_branch', 'file_beautifier')
@@ -0,0 +1,63 @@
1
+ module AbstractFeatureBranch::FileBeautifier
2
+ def self.process(file_path=nil)
3
+ if file_path.nil?
4
+ feature_directory_path = File.join(AbstractFeatureBranch.application_root, 'config', 'features')
5
+ feature_file_path = File.join(AbstractFeatureBranch.application_root, 'config', 'features.yml')
6
+ local_feature_file_path = File.join(AbstractFeatureBranch.application_root, 'config', 'features.local.yml')
7
+ process_directory(feature_directory_path)
8
+ process_file(feature_file_path)
9
+ process_file(local_feature_file_path)
10
+ else
11
+ if File.directory?(file_path)
12
+ process_directory(file_path)
13
+ else
14
+ process_file(file_path)
15
+ end
16
+ end
17
+ AbstractFeatureBranch.logger.info "File beautification done."
18
+ end
19
+
20
+ def self.process_directory(directory_path)
21
+ Dir.glob(File.join(directory_path, '**', '*.yml')).each do |file_path|
22
+ process_file(file_path)
23
+ end
24
+ end
25
+
26
+ def self.process_file(file_path)
27
+ AbstractFeatureBranch.logger.info "Beautifying #{file_path}..."
28
+ file_content = nil
29
+ File.open(file_path, 'r') do |file|
30
+ file_content = file.readlines.join
31
+ end
32
+ beautified_file_content = beautify(file_content)
33
+ File.open(file_path, 'w+') do |file|
34
+ file << beautified_file_content
35
+ end
36
+ end
37
+
38
+ def self.beautify(content)
39
+ #Not relying on ordered hashes for backwards compatibility with Ruby 1.8.7
40
+ sections = []
41
+ section_features = []
42
+ content.split("\n").each do |line|
43
+ if line.strip.empty? || (line.strip.start_with?('#') && !section_features.flatten.empty?)
44
+ # ignore empty line
45
+ elsif line.start_with?(" ")
46
+ section_features.last << line
47
+ else
48
+ sections << line
49
+ section_features << []
50
+ end
51
+ end
52
+ beautified_file_content = ''
53
+ sections.each_with_index do |section, i|
54
+ if section.start_with?('#')
55
+ beautified_file_content << "#{section}\n"
56
+ else
57
+ beautified_file_content << "#{section}\n"
58
+ beautified_file_content << "#{section_features[i].sort.join("\n")}\n\n"
59
+ end
60
+ end
61
+ beautified_file_content
62
+ end
63
+ end