can-do 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/can_do.gemspec +1 -1
  4. data/lib/can_do.rb +56 -54
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0ea512e8449c21e74af8d3d8f0d025b549c43e5
4
- data.tar.gz: ba1daeabb76c50d8337a36a1833b7bf3394f8ed3
3
+ metadata.gz: bff3d57eaf45561bc031a0fc69b6204ee12fc95f
4
+ data.tar.gz: ae8b80fee8aff5b8faab98e34b7d91724fe1c3ce
5
5
  SHA512:
6
- metadata.gz: 66bf959f3b5f28b13f11589c2b485066b28d3d493bd2d2ddf675de2290640bc6c49579083c3b5fdc738216fe71adb1bf2d6c5bc51874b2f26830f2dbbeb36631
7
- data.tar.gz: d1a7991590354dd293c68608163437fdad126bc9ebd5138363279c26ddeeb9fdda6830244fb946ce170a310d9ef0642d332b9240ee455bc418b50a0e900d9df6
6
+ metadata.gz: 24b18790e7043f62fc2171b689f285e5a9953af0b2127c8d20618621e96c6a813650229b4a452715e975911983521abf914d8243b06710b312546036c6c78633
7
+ data.tar.gz: 9d05c3df6ba44e2e5c2b790bc071f3e443c7152f45b87a3d6c6e50b4d9f7ec4ad2ef414450103bf090a5f238fa9fc3f2632f8c9cd6d7d9647091086cd0035552
data/.travis.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  language: ruby
2
+ services:
3
+ - redis-server
2
4
  before_script:
3
5
  - bundle install
4
6
  script:
data/can_do.gemspec CHANGED
@@ -3,7 +3,7 @@ $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 = "1.0.0"
6
+ spec.version = "1.1.0"
7
7
  spec.authors = ["Blacklane"]
8
8
 
9
9
  spec.summary = %q{Simple feature flags.}
data/lib/can_do.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require "connection_pool"
2
2
  require "redis"
3
- require "singleton"
4
3
  require "yaml"
5
4
 
6
5
  # Flips your features based on either a redis key, a config/features.yml file or environment variables.
@@ -27,8 +26,6 @@ require "yaml"
27
26
  # end
28
27
  #
29
28
  class CanDo
30
- include Singleton
31
- FEATURE_KEY_PREFIX = "features:"
32
29
  CONNECTION_POOL_SIZE = ENV.fetch("CANDO_CONNECTION_POOL_SIZE", 5)
33
30
  CONNECTION_POOL = ConnectionPool.new(size: CONNECTION_POOL_SIZE, timeout: 5) do
34
31
  Redis.new(url: ENV["CANDO_REDIS_URL"])
@@ -37,66 +34,71 @@ class CanDo
37
34
  THE_TRUTH = /^(true|t|yes|y|1)$/i
38
35
  DEFAULT_NAMESPACE = "defaults".freeze
39
36
 
40
- attr_reader :features
37
+ class << self
38
+ def feature?(feature)
39
+ is_enabled = read(feature)
40
+ # If no block is passed, return true or false
41
+ return is_enabled unless block_given?
42
+ # If a block is passed, return block or nil
43
+ yield if is_enabled
44
+ end
41
45
 
42
- def self.features
43
- instance.features
44
- end
46
+ def read(feature)
47
+ name = feature.to_s
48
+ shared_feature = pool.with { |redis| redis.get(redis_key(name)) }
49
+
50
+ fallback_value = fallback.fetch(name, false)
45
51
 
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
52
+ return !!(shared_feature =~ THE_TRUTH) unless shared_feature.nil?
53
+ write(name, fallback_value)
54
+ fallback_value
55
+ rescue Redis::CannotConnectError
56
+ fallback_value
53
57
  end
54
- end
55
58
 
56
- def self.feature?(name)
57
- name = name.to_s
58
- env_name = name.upcase
59
- shared_feature = shared_features(name)
60
-
61
- is_enabled =
62
- if !shared_feature.nil?
63
- !!(shared_feature =~ THE_TRUTH)
64
- elsif ENV.key?(env_name)
65
- !!(ENV[env_name] =~ THE_TRUTH)
66
- else
67
- features[name] == true
68
- end
69
-
70
- # If no block is passed, return true or false
71
- return is_enabled unless block_given?
72
-
73
- # If a block is passed, return block or nil
74
- yield if is_enabled
75
- end
59
+ def write(name, val)
60
+ pool.with { |redis| redis.set(redis_key(name), val) } == "OK"
61
+ rescue Redis::CannotConnectError
62
+ false
63
+ end
76
64
 
77
- private
65
+ def features
66
+ keys = pool.with { |redis| redis.keys(redis_key("*")) }
67
+ keys.map { |key| key.sub(redis_key(nil), "") }
68
+ rescue Redis::CannotConnectError
69
+ []
70
+ end
78
71
 
79
- def initialize
80
- yaml_file = File.expand_path("config/features.yml", Dir.pwd)
72
+ private
81
73
 
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
89
- end
74
+ def redis_key(name)
75
+ "#{redis_namespace}:#{name}"
76
+ end
90
77
 
91
- def env
92
- rails_env || rack_env
93
- end
78
+ def pool
79
+ CONNECTION_POOL
80
+ end
94
81
 
95
- def rails_env
96
- defined?(Rails) ? Rails.env : ENV["RAILS_ENV"]
97
- end
82
+ def fallback
83
+ @fallback ||= load_yaml_features
84
+ end
85
+
86
+ def yaml_file_path
87
+ File.expand_path("config/features.yml", Dir.pwd)
88
+ end
98
89
 
99
- def rack_env
100
- ENV["RACK_ENV"]
90
+ def load_yaml_features
91
+ return {} unless File.exist?(yaml_file_path)
92
+ data = YAML.safe_load(File.read(yaml_file_path))
93
+ data.fetch(DEFAULT_NAMESPACE, {}).merge(data.fetch(env, {}))
94
+ end
95
+
96
+ def env
97
+ ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
98
+ end
99
+
100
+ def redis_namespace
101
+ "features"
102
+ end
101
103
  end
102
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: can-do
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blacklane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-06 00:00:00.000000000 Z
11
+ date: 2017-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis