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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47e99ade543da399fb1529db07bbecd871e23a1eb7cff9239a578067453dc312
4
- data.tar.gz: b54ab8066e04ee68d6d40940a84dd69f237354d40523e5003be4f34ef6d4e03b
3
+ metadata.gz: 5a8c7180bcc59c08383c35f7aaaa993c8d64684d8d5f52174f5cd27c6fbca1da
4
+ data.tar.gz: f22086f5d839b540864caa62ab5fc3f31baf8f99d194c5516135ec0ddc85f032
5
5
  SHA512:
6
- metadata.gz: a2d9b1f7a36c405bbb7406bd22b4ec29f0f9d4d55a1ecf7d83ee8adb6f77cba28159f20a32be8b1fa36f97422ccdf74a7f93c6c06d8cb617b0f5405d0d833052
7
- data.tar.gz: d851c77683233aa129261171769b8e693949bf178af7c958995daf8f237fed1d7364db8b805e635e5346acdb26c3944af24aab15aab8c5c1f686efa29aba5bcc
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2022 Andy Maleh
1
+ Copyright (c) 2012-2023 Andy Maleh
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,18 +1,17 @@
1
- # Abstract Feature Branch 1.3.2
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 Rails gem that enables developers to easily branch by abstraction as per this pattern:
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 [DDD](http://www.domaindrivendesign.org)'s pattern of
24
- [Bounded Contexts](http://dddcommunity.org/uncategorized/bounded-context/) by allowing developers to configure
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`) ([click for a list of tested Ruby versions](https://travis-ci.org/AndyObtiva/abstract_feature_branch))
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.2'</pre>
41
- - With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.2'</pre>
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`): Install view [Homebrew](https://brew.sh/) with `brew install redis`
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.2</pre>
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 conflict when you do attempt to integrate your feature into the larger app.
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-2022 Andy Maleh. See [LICENSE.txt](LICENSE.txt) for
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.2
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.2 ruby lib
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.2"
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 = ["Annas \"Andy\" Maleh".freeze]
14
- s.date = "2022-12-12"
15
- 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.\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".freeze
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 Rails gem that enables developers to easily branch by abstraction as per this pattern: http://paulhammant.com/blog/branch_by_abstraction.html".freeze
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
@@ -1,29 +1,55 @@
1
1
  class Object
2
- raise 'Abstract feature branch conflicts with another Ruby library' if respond_to?(:feature_branch)
3
- def self.feature_branch(feature_name, user_id = nil, &feature_work)
4
- if feature_enabled?(feature_name, user_id)
5
- feature_work.call
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
- end
8
-
9
- raise 'Abstract feature branch conflicts with another Ruby library' if respond_to?(:feature_enabled?)
10
- def self.feature_enabled?(feature_name, user_id = nil)
11
- normalized_feature_name = feature_name.to_s.downcase
12
-
13
- redis_override_value = (AbstractFeatureBranch.get_store_feature(normalized_feature_name) rescue nil) if AbstractFeatureBranch.configuration.feature_store_live_fetching?
14
- value = !redis_override_value.nil? ? redis_override_value : AbstractFeatureBranch.application_features[normalized_feature_name]
15
- if value == 'per_user'
16
- value = !user_id.nil? && AbstractFeatureBranch.user_features_storage.sismember("#{AbstractFeatureBranch::ENV_FEATURE_PREFIX}#{normalized_feature_name}", user_id)
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.2
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
- - Annas "Andy" Maleh
7
+ - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-12 00:00:00.000000000 Z
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 Rails gem that enables developers to easily branch by abstraction as per this pattern:
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 DDD's pattern of
115
- Bounded Contexts by allowing developers to configure
116
- context-specific feature files if needed.
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: 'abstract_feature_branch is a Rails gem that enables developers to easily
175
- branch by abstraction as per this pattern: http://paulhammant.com/blog/branch_by_abstraction.html'
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: []