can-do 0.1.1 → 1.0.0

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
  SHA1:
3
- metadata.gz: 8eb5a19ab6f14a1d63e0d490b212ce57da941430
4
- data.tar.gz: 2a53db2847e808306c426853d767a8f2319a62de
3
+ metadata.gz: a0ea512e8449c21e74af8d3d8f0d025b549c43e5
4
+ data.tar.gz: ba1daeabb76c50d8337a36a1833b7bf3394f8ed3
5
5
  SHA512:
6
- metadata.gz: 335a1d55bbc0ada21058946bf487a46915ed944e93c8d3bc007f0600277f30b656a8b1a324d37bb482a5263c39deff677b9b02e410693baa5b4b8b671e7132f2
7
- data.tar.gz: 356dfff84096d84920547a38c5787d6d3a58027189cf0d8d3c1b7471a1e7d5b4b71a4ea47491fae93790563e3e68af5e187f8944f15c1dcbda0f49a468ff56cc
6
+ metadata.gz: 66bf959f3b5f28b13f11589c2b485066b28d3d493bd2d2ddf675de2290640bc6c49579083c3b5fdc738216fe71adb1bf2d6c5bc51874b2f26830f2dbbeb36631
7
+ data.tar.gz: d1a7991590354dd293c68608163437fdad126bc9ebd5138363279c26ddeeb9fdda6830244fb946ce170a310d9ef0642d332b9240ee455bc418b50a0e900d9df6
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
  /tmp/
10
10
 
11
11
  .ruby-version
12
+ .DS_Store
13
+ .rubocop-http*
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/blacklane/rubocop/master/rubocop.yml
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ before_script:
3
+ - bundle install
4
+ script:
5
+ - bundle exec rspec
6
+ - bundle exec rubocop
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/can-do.svg)](http://badge.fury.io/rb/can-do)
4
4
 
5
- Flips your features based on a `config/features.yml` file or environment variables. No data store required.
5
+ Flips your features based on a redis key, a `config/features.yml` file or environment variables.
6
6
 
7
7
  ## Usage
8
8
 
@@ -14,6 +14,36 @@ Add `can-do` to your Gemfile:
14
14
  gem "can-do", require: "can_do"
15
15
  ```
16
16
 
17
+ ## Redis values
18
+
19
+ To use redis as a storage set the environment variable `CANDO_REDIS_URL` with your redis instance.
20
+
21
+ The keys have to be prefixed with 'features:'.
22
+
23
+ So to set and use the feature `experiment-1` set the key like
24
+
25
+ ```sh
26
+ $ redis-cli SET features:experiment_1 true
27
+ ```
28
+
29
+ and use it like
30
+
31
+ ```ruby
32
+ require "can_do"
33
+
34
+ CanDo.feature?(:experiment_1)
35
+ ```
36
+
37
+ Any unset key will fall back to either the environment variable or the yaml variable and `false` if none is set.
38
+
39
+ ```ruby
40
+ require "can_do"
41
+
42
+ CanDo.feature?(:experiment_1)
43
+ ```
44
+
45
+ ## Yaml File
46
+
17
47
  Inside the `config` folder relative to your working directory create a file called `features.yml`. Within this file,
18
48
  place your *default feature flags* within the `defaults` key. All available features should be listed here, together with
19
49
  their default values. Add *environment-specific* feature flags under the environment name.
@@ -48,7 +78,7 @@ CanDo.feature?(:some_feature) do
48
78
  end
49
79
  ```
50
80
 
51
- If a feature is not found, `CanDo::NotAFeature` is raised.
81
+ If a feature is not found, `false` is returned.
52
82
 
53
83
  ## Environment variables
54
84
 
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "can_do"
5
+
6
+ require "pry"
7
+ Pry.start
data/can_do.gemspec CHANGED
@@ -3,12 +3,11 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "can-do"
6
- spec.version = "0.1.1"
7
- spec.authors = ["Florin Lipan", "Yuri Veremeyenko"]
8
- spec.email = ["florin.lipan@blacklane.com", "yuri.veremeyenko@blacklane.com"]
6
+ spec.version = "1.0.0"
7
+ spec.authors = ["Blacklane"]
9
8
 
10
9
  spec.summary = %q{Simple feature flags.}
11
- spec.description = %q{Simple feature flags based on a YAML config file and/or environment variables.}
10
+ spec.description = %q{Simple feature flags based on a redis instance, a YAML config file and/or environment variables.}
12
11
  spec.homepage = "https://github.com/blacklane/can-do"
13
12
  spec.license = "MIT"
14
13
 
@@ -17,5 +16,12 @@ Gem::Specification.new do |spec|
17
16
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
17
  spec.require_paths = ["lib"]
19
18
 
19
+ spec.add_dependency "redis"
20
+ spec.add_dependency "connection_pool"
21
+
20
22
  spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "pry"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rubocop"
26
+ spec.add_development_dependency "rspec-mocks"
21
27
  end
data/lib/can_do.rb CHANGED
@@ -1,8 +1,10 @@
1
+ require "connection_pool"
2
+ require "redis"
1
3
  require "singleton"
2
4
  require "yaml"
3
5
 
4
- # Flips your features based on a config/features.yml file or environment variables.
5
- # Environment variables always take precedence over the settings in your YAML file.
6
+ # Flips your features based on either a redis key, a config/features.yml file or environment variables.
7
+ # Redis keys always take precedence over Environment variables and the settings in your YAML file.
6
8
  #
7
9
  # @example config/features.yml
8
10
  # defaults:
@@ -26,8 +28,11 @@ require "yaml"
26
28
  #
27
29
  class CanDo
28
30
  include Singleton
29
-
30
- NotAFeature = Class.new(StandardError)
31
+ FEATURE_KEY_PREFIX = "features:"
32
+ CONNECTION_POOL_SIZE = ENV.fetch("CANDO_CONNECTION_POOL_SIZE", 5)
33
+ CONNECTION_POOL = ConnectionPool.new(size: CONNECTION_POOL_SIZE, timeout: 5) do
34
+ Redis.new(url: ENV["CANDO_REDIS_URL"])
35
+ end
31
36
 
32
37
  THE_TRUTH = /^(true|t|yes|y|1)$/i
33
38
  DEFAULT_NAMESPACE = "defaults".freeze
@@ -38,18 +43,29 @@ class CanDo
38
43
  instance.features
39
44
  end
40
45
 
41
- def self.feature?(name, &block)
46
+ def self.shared_features(name)
47
+ CONNECTION_POOL.with do |redis|
48
+ begin
49
+ redis.get(FEATURE_KEY_PREFIX + name.to_s)
50
+ rescue Redis::BaseError
51
+ nil
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.feature?(name)
42
57
  name = name.to_s
43
58
  env_name = name.upcase
44
-
45
- fail NotAFeature.new(name) unless features.key?(name)
59
+ shared_feature = shared_features(name)
46
60
 
47
61
  is_enabled =
48
- if ENV.key?(env_name)
62
+ if !shared_feature.nil?
63
+ !!(shared_feature =~ THE_TRUTH)
64
+ elsif ENV.key?(env_name)
49
65
  !!(ENV[env_name] =~ THE_TRUTH)
50
- else
51
- features[name] == true
52
- end
66
+ else
67
+ features[name] == true
68
+ end
53
69
 
54
70
  # If no block is passed, return true or false
55
71
  return is_enabled unless block_given?
@@ -61,10 +77,15 @@ class CanDo
61
77
  private
62
78
 
63
79
  def initialize
64
- yaml = File.read(File.expand_path("config/features.yml", Dir.pwd))
65
- data = YAML.load(yaml)
66
-
67
- @features = (data.fetch(DEFAULT_NAMESPACE, {})).merge(data.fetch(env, {}))
80
+ yaml_file = File.expand_path("config/features.yml", Dir.pwd)
81
+
82
+ @features =
83
+ if File.exist?(yaml_file)
84
+ data = YAML.safe_load(File.read(yaml_file))
85
+ data.fetch(DEFAULT_NAMESPACE, {}).merge(data.fetch(env, {}))
86
+ else
87
+ {}
88
+ end
68
89
  end
69
90
 
70
91
  def env
metadata CHANGED
@@ -1,16 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: can-do
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Florin Lipan
8
- - Yuri Veremeyenko
7
+ - Blacklane
9
8
  autorequire:
10
9
  bindir: exe
11
10
  cert_chain: []
12
- date: 2016-04-18 00:00:00.000000000 Z
11
+ date: 2017-11-06 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: connection_pool
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
14
41
  - !ruby/object:Gem::Dependency
15
42
  name: bundler
16
43
  requirement: !ruby/object:Gem::Requirement
@@ -25,18 +52,76 @@ dependencies:
25
52
  - - ">="
26
53
  - !ruby/object:Gem::Version
27
54
  version: '0'
28
- description: Simple feature flags based on a YAML config file and/or environment variables.
29
- email:
30
- - florin.lipan@blacklane.com
31
- - yuri.veremeyenko@blacklane.com
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-mocks
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Simple feature flags based on a redis instance, a YAML config file and/or
112
+ environment variables.
113
+ email:
32
114
  executables: []
33
115
  extensions: []
34
116
  extra_rdoc_files: []
35
117
  files:
36
118
  - ".gitignore"
119
+ - ".rubocop.yml"
120
+ - ".travis.yml"
37
121
  - Gemfile
38
122
  - LICENSE.txt
39
123
  - README.md
124
+ - bin/console
40
125
  - can_do.gemspec
41
126
  - lib/can_do.rb
42
127
  homepage: https://github.com/blacklane/can-do
@@ -59,8 +144,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
144
  version: '0'
60
145
  requirements: []
61
146
  rubyforge_project:
62
- rubygems_version: 2.4.6
147
+ rubygems_version: 2.5.1
63
148
  signing_key:
64
149
  specification_version: 4
65
150
  summary: Simple feature flags.
66
151
  test_files: []
152
+ has_rdoc: