abstract_feature_branch 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/LICENSE.txt +1 -1
- data/README.md +28 -20
- data/VERSION +1 -1
- data/abstract_feature_branch.gemspec +6 -6
- data/lib/abstract_feature_branch.rb +4 -1
- data/lib/ext/feature_branch.rb +44 -18
- metadata +13 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a8c7180bcc59c08383c35f7aaaa993c8d64684d8d5f52174f5cd27c6fbca1da
|
4
|
+
data.tar.gz: f22086f5d839b540864caa62ab5fc3f31baf8f99d194c5516135ec0ddc85f032
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44908f37b872e59a8160d87b7a598949635489553b82a8cb56fcaa28ca5eac43679f9334ef273908aacaa90d6e2b7fe255913d1805eaff05cca2a9792c3d5f6e
|
7
|
+
data.tar.gz: 8723b3f9ed9ce9131cbdc4c259e3700ad708925f50226c736115ee2f65da5a897f0f08537e1bac7b24d39741a0ef710ae732f8196e6ee7388b22058075318479
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.3.3
|
4
|
+
|
5
|
+
- Redis network failure error handling for per-user feature enablement to default to `nil` value instead of crashing
|
6
|
+
- Error logging upon encountering Redis network failure errors in loading Redis Overrides live or not and in per-user feature enablement
|
7
|
+
|
3
8
|
## 1.3.2
|
4
9
|
|
5
10
|
- Ensure better performance, fetch Redis Overrides at app/server startup time only by default while providing option to fetch live by setting `AbstractFeatureBranch.feature_store_live_fetching` to `true`
|
@@ -17,5 +22,5 @@
|
|
17
22
|
- Remove `redis` gem from required dependencies to allow using `abstract_feature_branch` without Redis
|
18
23
|
- Make configuration of Redis optional in generated Rails initializer
|
19
24
|
- Provide alias of `AbstractFeatureBranch::Configuration#feature_store` to `AbstractFeatureBranch::Configuration#user_features_storage` (plus corresponding aliases `feature_store=` and `initialize_feature_store`)
|
20
|
-
- Document support for Rails 7 and Redis Server 7
|
25
|
+
- Document support for Ruby 3.1, Rails 7 and Redis Server 7
|
21
26
|
- Add gem post install instructions, including how to run the Rails generators and install/use Redis
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
# Abstract Feature Branch 1.3.
|
1
|
+
# Abstract Feature Branch 1.3.3
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/abstract_feature_branch.png)](http://badge.fury.io/rb/abstract_feature_branch)
|
3
3
|
[![Build Status](https://api.travis-ci.org/AndyObtiva/abstract_feature_branch.png?branch=master)](https://travis-ci.org/AndyObtiva/abstract_feature_branch)
|
4
4
|
[![Coverage Status](https://coveralls.io/repos/AndyObtiva/abstract_feature_branch/badge.png?branch=master)](https://coveralls.io/r/AndyObtiva/abstract_feature_branch?branch=master)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/AndyObtiva/abstract_feature_branch.png)](https://codeclimate.com/github/AndyObtiva/abstract_feature_branch)
|
6
6
|
|
7
|
-
abstract_feature_branch is a
|
8
|
-
http://paulhammant.com/blog/branch_by_abstraction.html
|
7
|
+
[`abstract_feature_branch`](https://rubygems.org/gems/abstract_feature_branch) is a Ruby gem that provides a variation on the [Branch by Abstraction Pattern](http://paulhammant.com/blog/branch_by_abstraction.html) by [Paul Hammant](https://paulhammant.com/) and the [Feature Toggles Pattern](https://martinfowler.com/bliki/FeatureToggle.html) by [Martin Fowler](https://martinfowler.com/).
|
9
8
|
|
10
9
|
It is a productivity and fault tolerance enhancing team practice.
|
11
10
|
|
12
11
|
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.
|
12
|
+
[specify in a configuration file](#instructions) which features to be switched on or off.
|
14
13
|
|
15
|
-
The goal is to build out upcoming features in the same source code repository branch, regardless of whether all are
|
14
|
+
The goal is to build out upcoming features in the same source code repository branch (i.e. continuous integration), regardless of whether all are
|
16
15
|
completed by the next release date or not, thus increasing team productivity by preventing integration delays.
|
17
16
|
Developers then disable in-progress features until they are ready to be switched on in production, yet enable them
|
18
17
|
locally and in staging environments for in-progress testing.
|
@@ -20,13 +19,17 @@ locally and in staging environments for in-progress testing.
|
|
20
19
|
This gives developers the added benefit of being able to switch a feature off after release should big problems arise
|
21
20
|
for a high risk feature.
|
22
21
|
|
23
|
-
abstract_feature_branch additionally supports [
|
24
|
-
[Bounded Contexts](
|
22
|
+
[`abstract_feature_branch`](https://rubygems.org/gems/abstract_feature_branch) additionally supports [Domain Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design)'s pattern of
|
23
|
+
[Bounded Contexts](https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf) by allowing developers to configure
|
25
24
|
context-specific feature files if needed.
|
26
25
|
|
26
|
+
[`abstract_feature_branch`](https://rubygems.org/gems/abstract_feature_branch) is one of the simplest and most minimalistic "Feature Flags" Ruby gems out there as it enables you to get started very quickly by simply leveraging YAML files without having to set up a data store if you do not need it (albeit, you also have the option to use Redis as a very fast in-memory data store).
|
27
|
+
|
28
|
+
|
29
|
+
|
27
30
|
Requirements
|
28
31
|
------------
|
29
|
-
- Ruby (between `~> 3.1.0` and `~> 1.8.7`)
|
32
|
+
- Ruby (between `~> 3.1.0` and `~> 1.8.7`)
|
30
33
|
- [Optional] Rails (between `~> 7.0` and `~> 2.0`)
|
31
34
|
- [Optional] Redis Server (between `~> 7.0` and `~> 2.0`)
|
32
35
|
- [Optional] Redis client gem (between `~> 5.0` and `~> 3.0`)
|
@@ -37,17 +40,17 @@ Setup
|
|
37
40
|
### Rails Application Use
|
38
41
|
|
39
42
|
1. Configure Rubygem
|
40
|
-
- With `rails` between `~> 7.0` and `~> 2.0`: Add the following to Gemfile <pre>gem 'abstract_feature_branch', '~> 1.3.
|
41
|
-
- With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.
|
43
|
+
- With `rails` between `~> 7.0` and `~> 2.0`: Add the following to Gemfile <pre>gem 'abstract_feature_branch', '~> 1.3.3'</pre>
|
44
|
+
- With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.3'</pre>
|
42
45
|
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>
|
43
46
|
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))
|
44
|
-
4. [Optional] Customize configuration in <code>config/initializers/abstract_feature_branch.rb</code> (can be useful for changing location of feature files in Rails application, configuring Redis with a Redis or ConnectionPool instance to use for overrides, and per-user feature enablement, or troubleshooting a specific Rails environment feature configuration)
|
45
|
-
5. [Optional] Redis Server (between `~> 7.0` and `~> 3.0`):
|
46
|
-
6. [Optional] `redis` client gem (between `~> 5.0` and `~> 3.0`): Add the following to Gemfile above `abstract_feature_branch` <pre>gem 'redis', '~> 5.0.5'</pre>
|
47
|
+
4. [Optional] Customize configuration in <code>config/initializers/abstract_feature_branch.rb</code> (can be useful for changing location of feature files in Rails application, configuring Redis with a Redis or ConnectionPool instance to use for overrides, and [per-user feature enablement](#per-user-feature-enablement), or troubleshooting a specific Rails environment feature configuration)
|
48
|
+
5. [Optional] Redis Server (between `~> 7.0` and `~> 3.0`): On the Mac, you can install simply via [Homebrew](https://brew.sh/) with `brew install redis`
|
49
|
+
6. [Optional] `redis` client gem (between `~> 5.0` and `~> 3.0`): Add the following to Gemfile above [`abstract_feature_branch`](https://rubygems.org/gems/abstract_feature_branch) <pre>gem 'redis', '~> 5.0.5'</pre>
|
47
50
|
|
48
51
|
### Ruby Application General Use
|
49
52
|
|
50
|
-
1. <pre>gem install abstract_feature_branch -v 1.3.
|
53
|
+
1. <pre>gem install abstract_feature_branch -v 1.3.3</pre>
|
51
54
|
2. Add code <code>require 'abstract_feature_branch'</code>
|
52
55
|
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).
|
53
56
|
4. [Optional] Create <code>config/features.local.yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under [**instructions**](#instructions))
|
@@ -57,7 +60,7 @@ Setup
|
|
57
60
|
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).
|
58
61
|
9. [Optional] Add code <code>AbstractFeatureBranch.cacheable = {[environment] => [true/false]}</code> to indicate cacheability of loaded feature files for enhanced performance (it defaults to true for every environment other than development).
|
59
62
|
10. [Optional] Add code <code>AbstractFeatureBranch.load_application_features</code> to pre-load application features for improved first-use performance
|
60
|
-
11. [Optional] Add code <code>AbstractFeatureBranch.feature_store = Redis.new(options)</code> to configure Redis for overrides and/or per-user feature enablement
|
63
|
+
11. [Optional] Add code <code>AbstractFeatureBranch.feature_store = Redis.new(options)</code> to configure Redis for overrides and/or [per-user feature enablement](#per-user-feature-enablement)
|
61
64
|
12. [Optional] Set <code>AbstractFeatureBranch.feature_store_live_fetching = true</code> to enable live fetching of features from store (e.g. Redis) to avoid need for app/server restart upon feature changes, with the trade-off of slightly more latency due to making calls to feature store over the network
|
62
65
|
|
63
66
|
Instructions
|
@@ -125,9 +128,14 @@ Note that <code>feature_branch</code> returns nil and does not execute the block
|
|
125
128
|
|
126
129
|
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).
|
127
130
|
|
131
|
+
- List all configured features for a particular environment:
|
132
|
+
|
133
|
+
> AbstractFeatureBranch.environment_features('development')
|
134
|
+
> # => {"feature1"=>true, "feature2"=>false, "feature3"=>false, "feature4"=>true}
|
135
|
+
|
128
136
|
### Per-User Feature Enablement
|
129
137
|
|
130
|
-
It is possible to restrict enablement of features per specific users by setting a feature value to <code>per_user</code
|
138
|
+
It is possible to restrict enablement of features per specific users (or per entities of any kind) by setting a feature value to <code>per_user</code>, and then toggling features for specific users (or other entities).
|
131
139
|
|
132
140
|
1. Use <code>toggle_features_for_user</code> in Ruby code to enable features per user ID (e.g. email address or database ID). This loads Redis client gem into memory and stores per-user feature configuration in Redis.
|
133
141
|
In the example below, current_user is a method that provides the current signed in user (e.g. using Rails [Devise] (https://github.com/plataformatec/devise) library).
|
@@ -273,13 +281,13 @@ Keep in mind that by default, Redis Overrides are fetched on app/server start to
|
|
273
281
|
|
274
282
|
To enable live fetching of Redis Overrides, set `AbstractFeatureBranch#feature_store_live_fetching` to `true` (e.g. in `config/initializers/abstract_feature_branch.rb`), but keep in mind the trade-off with more latency due to making calls to Redis Server over the network.
|
275
283
|
|
276
|
-
You can override feature configuration with Redis hash values by calling `AbstractFeatureBranch#set_store_feature` in `rails console` (or `irb` after requiring `redis` and `abstract_feature_branch`):
|
284
|
+
You can override feature configuration with Redis hash values by calling `AbstractFeatureBranch#set_store_feature` in `rails console` (or `irb` after requiring `redis` and [`abstract_feature_branch`](https://rubygems.org/gems/abstract_feature_branch)):
|
277
285
|
|
278
286
|
```ruby
|
279
287
|
AbstractFeatureBranch.set_store_feature('feature1', true)
|
280
288
|
```
|
281
289
|
|
282
|
-
Behind the scenes, that is the equivalent of the following Redis client invocation, which stores a hash value in a `abstract_feature_branch` key:
|
290
|
+
Behind the scenes, that is the equivalent of the following Redis client invocation, which stores a hash value in a `'abstract_feature_branch'` key:
|
283
291
|
|
284
292
|
```ruby
|
285
293
|
AbstractFeatureBranch.configuration.feature_store.hset('abstract_feature_branch', 'feature1', 'true')
|
@@ -487,7 +495,7 @@ Although feature branches and branching by abstraction are similar, there are di
|
|
487
495
|
|
488
496
|
Feature branching leverages your version control software (VCS) to create a branch that is independent of your main branch. Once you write your feature, you integrate it with the rest of your code base. Feature branching is ideal for developing features that can be completed within the one or two iterations. But it can become cumbersome with larger features due to the fact your code is isolated and quickly falls out of sync with your main branch. You will have to regularly rebase with your main branch or devote substantial time to resolving merge conflicts.
|
489
497
|
|
490
|
-
Branching by abstraction, on the other hand, is ideal for substantial features, i.e. ones which take many iterations to complete. This approach to branching takes place outside of your VCS. Instead, you build your feature, but wrap the code inside configurable flags. These configuration flags will allow for different behavior, depending on the runtime environment. For example, a feature would be set to "on" when your app runs in development mode, but "off" when running in "production" mode. This approach avoids the pain of constantly rebasing or resolving a myriad of merge
|
498
|
+
Branching by abstraction, on the other hand, is ideal for substantial features, i.e. ones which take many iterations to complete. This approach to branching takes place outside of your VCS. Instead, you build your feature, but wrap the code inside configurable flags. These configuration flags will allow for different behavior, depending on the runtime environment. For example, a feature would be set to "on" when your app runs in development mode, but "off" when running in "production" mode. This approach avoids the pain of constantly rebasing or resolving a myriad of merge conflicts when you do attempt to integrate your feature into the larger app.
|
491
499
|
|
492
500
|
Contributing to abstract_feature_branch
|
493
501
|
---------------------------------------
|
@@ -511,5 +519,5 @@ Contributors
|
|
511
519
|
Copyright
|
512
520
|
---------------------------------------
|
513
521
|
|
514
|
-
Copyright (c) 2012-
|
522
|
+
Copyright (c) 2012-2023 Andy Maleh. See [LICENSE.txt](LICENSE.txt) for
|
515
523
|
further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.3.
|
1
|
+
1.3.3
|
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: abstract_feature_branch 1.3.
|
5
|
+
# stub: abstract_feature_branch 1.3.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "abstract_feature_branch".freeze
|
9
|
-
s.version = "1.3.
|
9
|
+
s.version = "1.3.3"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
|
-
s.authors = ["
|
14
|
-
s.date = "
|
15
|
-
s.description = "abstract_feature_branch is a
|
13
|
+
s.authors = ["Andy Maleh".freeze]
|
14
|
+
s.date = "2023-01-15"
|
15
|
+
s.description = "abstract_feature_branch is a Ruby gem that provides a variation on the Branch by Abstraction Pattern by Paul Hammant and the Feature Toggles Pattern by Martin Fowler.\n\nIt is a productivity and fault tolerance enhancing team practice.\n\nIt provides the ability to wrap blocks of code with an abstract feature branch name, and then specify 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 (i.e. continuous integration), regardless of whether all are completed by the next release date or not, thus increasing team productivity by preventing integration delays. Developers then disable in-progress features until they are ready to be switched on in production, yet enable them locally 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 for a high risk feature.\n\nabstract_feature_branch additionally supports Domain Driven Design's pattern of Bounded Contexts by allowing developers to configure context-specific feature files if needed.\n\nabstract_feature_branch is one of the simplest and most minimalistic \"Feature Flags\" Ruby gems out there as it enables you to get started very quickly by simply leveraging YAML files without having to set up a data store if you do not need it (albeit, you also have the option to use Redis as a very fast in-memory data store).\n".freeze
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"CHANGELOG.md",
|
18
18
|
"LICENSE.txt",
|
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.licenses = ["MIT".freeze]
|
42
42
|
s.post_install_message = "\nRails-only post-install instructions:\n\n1) Run the following command to generate the Rails initializer and basic feature files:\n\nrails g abstract_feature_branch:install\n\n2) Optionally, you may run this command to generate feature files per context:\n\nrails g abstract_feature_branch:context context_path\n \n3) Optionally, install Redis server with [Homebrew](https://brew.sh/) by running:\n\nbrew install redis\n\n4) Optionally, install redis client gem (required with Redis server) by adding the following line to Gemfile above abstract_feature_branch:\n\ngem 'redis', '~> 5.0.5'\n\nAfterwards, run:\n\nbundle\n\n5) Optionally, customize configuration in config/initializers/abstract_feature_branch.rb\n\n(can be useful for changing location of feature files in Rails application,\nconfiguring Redis with a Redis or ConnectionPool instance to use for overrides and per-user feature enablement,\nand/or troubleshooting specific Rails environment feature configurations)\n\n".freeze
|
43
43
|
s.rubygems_version = "3.1.4".freeze
|
44
|
-
s.summary = "abstract_feature_branch is a
|
44
|
+
s.summary = "abstract_feature_branch is a Ruby gem that provides a variation on the Branch by Abstraction Pattern by Paul Hammant and the Feature Toggles Pattern by Martin Fowler (aka Feature Flags).".freeze
|
45
45
|
|
46
46
|
if s.respond_to? :specification_version then
|
47
47
|
s.specification_version = 4
|
@@ -35,13 +35,16 @@ module AbstractFeatureBranch
|
|
35
35
|
@redis_overrides ||= load_redis_overrides
|
36
36
|
end
|
37
37
|
def load_redis_overrides
|
38
|
-
return {} if feature_store.nil?
|
38
|
+
return (@redis_overrides = {}) if feature_store.nil?
|
39
39
|
|
40
40
|
redis_feature_hash = get_store_features.inject({}) do |output, feature|
|
41
41
|
output.merge(feature => get_store_feature(feature))
|
42
42
|
end
|
43
43
|
|
44
44
|
@redis_overrides = downcase_keys(redis_feature_hash)
|
45
|
+
rescue Exception => error
|
46
|
+
AbstractFeatureBranch.logger.error "AbstractFeatureBranch encounter an error in loading Redis Overrides!\n\nError:#{error.full_message}\n\n"
|
47
|
+
@redis_overrides = {}
|
45
48
|
end
|
46
49
|
|
47
50
|
def environment_variable_overrides
|
data/lib/ext/feature_branch.rb
CHANGED
@@ -1,29 +1,55 @@
|
|
1
1
|
class Object
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
class << self
|
3
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object::feature_branch' if respond_to?(:feature_branch)
|
4
|
+
def feature_branch(feature_name, user_id = nil, &feature_work)
|
5
|
+
if feature_enabled?(feature_name, user_id)
|
6
|
+
feature_work.call
|
7
|
+
end
|
6
8
|
end
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
|
10
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object::feature_enabled?' if respond_to?(:feature_enabled?)
|
11
|
+
def feature_enabled?(feature_name, user_id = nil)
|
12
|
+
normalized_feature_name = feature_name.to_s.downcase
|
13
|
+
|
14
|
+
redis_override_value = feature_enabled_reddis_override_value(normalized_feature_name)
|
15
|
+
value = !redis_override_value.nil? ? redis_override_value : AbstractFeatureBranch.application_features[normalized_feature_name]
|
16
|
+
if value == 'per_user'
|
17
|
+
value = !user_id.nil? && feature_enabled_per_user_value(feature_name, user_id)
|
18
|
+
end
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object::feature_enabled_reddis_override_value' if Object.new.respond_to?(:feature_enabled_reddis_override_value, true)
|
25
|
+
def feature_enabled_reddis_override_value(normalized_feature_name)
|
26
|
+
if AbstractFeatureBranch.configuration.feature_store_live_fetching?
|
27
|
+
begin
|
28
|
+
AbstractFeatureBranch.get_store_feature(normalized_feature_name)
|
29
|
+
rescue Exception => error
|
30
|
+
AbstractFeatureBranch.logger.error "AbstractFeatureBranch encountered an error in retrieving Redis Override value for feature \"#{normalized_feature_name}\"! Defaulting to YAML configuration value...\n\nError: #{error.full_message}\n\n"
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object::feature_enabled_per_user_value' if Object.new.respond_to?(:feature_enabled_per_user_value, true)
|
37
|
+
def feature_enabled_per_user_value(normalized_feature_name, user_id)
|
38
|
+
begin
|
39
|
+
AbstractFeatureBranch.user_features_storage.sismember("#{AbstractFeatureBranch::ENV_FEATURE_PREFIX}#{normalized_feature_name}", user_id)
|
40
|
+
rescue Exception => error
|
41
|
+
AbstractFeatureBranch.logger.error "AbstractFeatureBranch encountered an error in retrieving Per-User value for feature \"#{normalized_feature_name}\" and user_id #{user_id}! Defaulting to nil value...\n\nError: #{error.full_message}\n\n"
|
42
|
+
nil
|
43
|
+
end
|
17
44
|
end
|
18
|
-
value
|
19
45
|
end
|
20
|
-
|
21
|
-
raise 'Abstract feature branch conflicts with another Ruby library' if Object.new.respond_to?(:feature_branch)
|
46
|
+
|
47
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object#feature_branch' if Object.new.respond_to?(:feature_branch)
|
22
48
|
def feature_branch(feature_name, user_id = nil, &feature_work)
|
23
49
|
Object.feature_branch(feature_name.to_s, user_id, &feature_work)
|
24
50
|
end
|
25
51
|
|
26
|
-
raise 'Abstract feature branch conflicts with another Ruby library' if Object.new.respond_to?(:feature_enabled?)
|
52
|
+
raise 'Abstract feature branch conflicts with another Ruby library having Object#feature_enabled?' if Object.new.respond_to?(:feature_enabled?)
|
27
53
|
def feature_enabled?(feature_name, user_id = nil)
|
28
54
|
Object.feature_enabled?(feature_name.to_s, user_id)
|
29
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abstract_feature_branch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deep_merge
|
@@ -95,25 +95,19 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 3.3.4
|
97
97
|
description: |
|
98
|
-
abstract_feature_branch is a
|
99
|
-
http://paulhammant.com/blog/branch_by_abstraction.html
|
98
|
+
abstract_feature_branch is a Ruby gem that provides a variation on the Branch by Abstraction Pattern by Paul Hammant and the Feature Toggles Pattern by Martin Fowler.
|
100
99
|
|
101
100
|
It is a productivity and fault tolerance enhancing team practice.
|
102
101
|
|
103
|
-
It provides the ability to wrap blocks of code with an abstract feature branch name, and then
|
104
|
-
specify in a configuration file which features to be switched on or off.
|
102
|
+
It provides the ability to wrap blocks of code with an abstract feature branch name, and then specify in a configuration file which features to be switched on or off.
|
105
103
|
|
106
|
-
The goal is to build out upcoming features in the same source code repository branch, regardless of whether all are
|
107
|
-
completed by the next release date or not, thus increasing team productivity by preventing integration delays.
|
108
|
-
Developers then disable in-progress features until they are ready to be switched on in production, yet enable them
|
109
|
-
locally and in staging environments for in-progress testing.
|
104
|
+
The goal is to build out upcoming features in the same source code repository branch (i.e. continuous integration), regardless of whether all are completed by the next release date or not, thus increasing team productivity by preventing integration delays. Developers then disable in-progress features until they are ready to be switched on in production, yet enable them locally and in staging environments for in-progress testing.
|
110
105
|
|
111
|
-
This gives developers the added benefit of being able to switch a feature off after release should big problems arise
|
112
|
-
for a high risk feature.
|
106
|
+
This gives developers the added benefit of being able to switch a feature off after release should big problems arise for a high risk feature.
|
113
107
|
|
114
|
-
abstract_feature_branch additionally supports
|
115
|
-
|
116
|
-
|
108
|
+
abstract_feature_branch additionally supports Domain Driven Design's pattern of Bounded Contexts by allowing developers to configure context-specific feature files if needed.
|
109
|
+
|
110
|
+
abstract_feature_branch is one of the simplest and most minimalistic "Feature Flags" Ruby gems out there as it enables you to get started very quickly by simply leveraging YAML files without having to set up a data store if you do not need it (albeit, you also have the option to use Redis as a very fast in-memory data store).
|
117
111
|
email:
|
118
112
|
executables: []
|
119
113
|
extensions: []
|
@@ -171,6 +165,7 @@ requirements: []
|
|
171
165
|
rubygems_version: 3.1.4
|
172
166
|
signing_key:
|
173
167
|
specification_version: 4
|
174
|
-
summary:
|
175
|
-
|
168
|
+
summary: abstract_feature_branch is a Ruby gem that provides a variation on the Branch
|
169
|
+
by Abstraction Pattern by Paul Hammant and the Feature Toggles Pattern by Martin
|
170
|
+
Fowler (aka Feature Flags).
|
176
171
|
test_files: []
|