rollout 2.4.1 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: be3151ff1e21e7693a5b5be187e4db45cf4eb5d3
4
- data.tar.gz: 4bf397113ea44c2a522b4929c2030ca1aa756fab
2
+ SHA256:
3
+ metadata.gz: acf240ab59dcfdebec335aee19df882f8936e7de5b7a0c347a3c28cfa8b3fc6d
4
+ data.tar.gz: 2ca7c2d7c761c6e539790421547b5e8eb82bbe8b56dca246975f6adc0773866d
5
5
  SHA512:
6
- metadata.gz: 579ebe41258df73bf78477cba47da1529302c560e246f03a1bf4c652e93518a1de7e7053ec9665f3eefc94f04e21015b48a568dbdd1951d44ce23775aa967673
7
- data.tar.gz: 34fee387845b0cd8df9f1f593d900b8bb22de23acc2aee4777e99672a5caac1c78122ca020f032453e786d607bb7d905e65dbf807cbb8b796beafabba98fa6c2
6
+ metadata.gz: dc61fd463b60a94e85b5b141ad5fb7431f37249d9b899739b52524bd0fc28106135e039cbfe0130a0c35d0934b50339e426e38255516381636ec1ff226068e49
7
+ data.tar.gz: 5babd80ccaab8b4f7b4efeac63e5941709913014e5d5d37f71c5f8b04ae62d09a38e50f7f6236df8d09ce359384cb0d877452209a1b63b69284fd649bb49033c
@@ -0,0 +1,80 @@
1
+ version: 2.1
2
+
3
+ workflows:
4
+ main:
5
+ jobs:
6
+ - ruby26
7
+ - ruby25
8
+ - ruby24
9
+ - ruby23
10
+
11
+ executors:
12
+ ruby26:
13
+ docker:
14
+ - image: circleci/ruby:2.6
15
+ ruby25:
16
+ docker:
17
+ - image: circleci/ruby:2.5
18
+ ruby24:
19
+ docker:
20
+ - image: circleci/ruby:2.4
21
+ ruby23:
22
+ docker:
23
+ - image: circleci/ruby:2.3
24
+
25
+ commands:
26
+ test:
27
+ steps:
28
+ - restore_cache:
29
+ keys:
30
+ - bundler-{{ checksum "Gemfile.lock" }}
31
+
32
+ - run:
33
+ name: Bundle Install
34
+ command: bundle check --path vendor/bundle || bundle install --deployment
35
+
36
+ - save_cache:
37
+ key: bundler-{{ checksum "Gemfile.lock" }}
38
+ paths:
39
+ - vendor/bundle
40
+
41
+ - run:
42
+ name: Run rspec
43
+ command: |
44
+ bundle exec rspec --format documentation --format RspecJunitFormatter --out test_results/rspec.xml
45
+
46
+ jobs:
47
+ ruby26:
48
+ executor: ruby26
49
+ steps:
50
+ - checkout
51
+ - test
52
+
53
+ - run:
54
+ name: Report Test Coverage
55
+ command: |
56
+ wget https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 -O cc-test-reporter
57
+ chmod +x cc-test-reporter
58
+ ./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.json coverage/.resultset.json
59
+ ./cc-test-reporter upload-coverage -i coverage/codeclimate.json
60
+
61
+ - store_test_results:
62
+ path: test_results
63
+
64
+ ruby25:
65
+ executor: ruby25
66
+ steps:
67
+ - checkout
68
+ - test
69
+
70
+ ruby24:
71
+ executor: ruby24
72
+ steps:
73
+ - checkout
74
+ - test
75
+
76
+ ruby23:
77
+ executor: ruby23
78
+ steps:
79
+ - checkout
80
+ - test
data/.gitignore CHANGED
@@ -19,5 +19,6 @@ rdoc
19
19
  pkg
20
20
  *.gem
21
21
  gemfiles/*.lock
22
+ .rspec_status
22
23
 
23
24
  ## PROJECT::SPECIFIC
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'spec/**/*'
4
+
5
+ Metrics/LineLength:
6
+ Max: 120
7
+ Metrics/MethodLength:
8
+ Max: 20
9
+
10
+ Style/TrailingCommaInArguments:
11
+ EnforcedStyleForMultiline: comma
data/.travis.yml CHANGED
@@ -4,13 +4,13 @@ sudo: false
4
4
  services:
5
5
  - redis-server
6
6
  rvm:
7
- - 2.4.1
8
- - 2.3.1
7
+ - 2.6
8
+ - 2.5
9
+ - 2.4
10
+ - 2.3
9
11
  - 2.2
10
12
  - 2.1
11
- - 2.0.0
12
- - 1.9.3
13
- - jruby-19mode
13
+ - 2.0
14
14
  env:
15
15
  - USE_REAL_REDIS=true
16
16
  gemfile:
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,56 +1,65 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rollout (2.4.0)
4
+ rollout (2.4.5)
5
+ redis (~> 4.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- appraisal (2.1.0)
10
- bundler
11
- rake
12
- thor (>= 0.14.0)
13
- codeclimate-test-reporter (1.0.5)
14
- simplecov
10
+ ast (2.4.0)
15
11
  diff-lcs (1.3)
16
- docile (1.1.5)
17
- fakeredis (0.6.0)
18
- redis (~> 3.2)
19
- json (2.0.3)
20
- rake (12.0.0)
21
- redis (3.3.3)
22
- rspec (3.5.0)
23
- rspec-core (~> 3.5.0)
24
- rspec-expectations (~> 3.5.0)
25
- rspec-mocks (~> 3.5.0)
26
- rspec-core (3.5.4)
27
- rspec-support (~> 3.5.0)
28
- rspec-expectations (3.5.0)
12
+ docile (1.3.2)
13
+ fakeredis (0.7.0)
14
+ redis (>= 3.2, < 5.0)
15
+ jaro_winkler (1.5.3)
16
+ json (2.2.0)
17
+ parallel (1.17.0)
18
+ parser (2.6.3.0)
19
+ ast (~> 2.4.0)
20
+ rainbow (3.0.0)
21
+ redis (4.1.2)
22
+ rspec (3.8.0)
23
+ rspec-core (~> 3.8.0)
24
+ rspec-expectations (~> 3.8.0)
25
+ rspec-mocks (~> 3.8.0)
26
+ rspec-core (3.8.2)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-expectations (3.8.4)
29
29
  diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.5.0)
31
- rspec-mocks (3.5.0)
30
+ rspec-support (~> 3.8.0)
31
+ rspec-mocks (3.8.1)
32
32
  diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.5.0)
34
- rspec-support (3.5.0)
35
- simplecov (0.13.0)
36
- docile (~> 1.1.0)
33
+ rspec-support (~> 3.8.0)
34
+ rspec-support (3.8.2)
35
+ rspec_junit_formatter (0.4.1)
36
+ rspec-core (>= 2, < 4, != 2.12.0)
37
+ rubocop (0.72.0)
38
+ jaro_winkler (~> 1.5.1)
39
+ parallel (~> 1.10)
40
+ parser (>= 2.6)
41
+ rainbow (>= 2.2.2, < 4.0)
42
+ ruby-progressbar (~> 1.7)
43
+ unicode-display_width (>= 1.4.0, < 1.7)
44
+ ruby-progressbar (1.10.1)
45
+ simplecov (0.16.1)
46
+ docile (~> 1.1)
37
47
  json (>= 1.8, < 3)
38
48
  simplecov-html (~> 0.10.0)
39
- simplecov-html (0.10.0)
40
- thor (0.19.4)
49
+ simplecov-html (0.10.2)
50
+ unicode-display_width (1.6.0)
41
51
 
42
52
  PLATFORMS
43
53
  ruby
44
54
 
45
55
  DEPENDENCIES
46
- appraisal
47
- bundler (>= 1.0.0)
48
- codeclimate-test-reporter
56
+ bundler (~> 1.17)
49
57
  fakeredis
50
- redis
51
58
  rollout!
52
- rspec
53
- simplecov
59
+ rspec (~> 3.0)
60
+ rspec_junit_formatter (~> 0.4)
61
+ rubocop (~> 0.71)
62
+ simplecov (~> 0.16)
54
63
 
55
64
  BUNDLED WITH
56
- 1.12.5
65
+ 1.17.2
data/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  Fast feature flags based on Redis.
4
4
 
5
- [![Build Status](https://travis-ci.org/fetlife/rollout.svg?branch=master)](https://travis-ci.org/fetlife/rollout)
6
- [![Code Climate](https://codeclimate.com/github/FetLife/rollout/badges/gpa.svg)](https://codeclimate.com/github/fetlife/rollout)
7
- [![Test Coverage](https://codeclimate.com/github/FetLife/rollout/badges/coverage.svg)](https://codeclimate.com/github/fetlife/rollout/coverage)
8
- [![Dependency Status](https://gemnasium.com/FetLife/rollout.svg)](https://gemnasium.com/fetlife/rollout)
5
+ [![Gem Version](https://badge.fury.io/rb/rollout.svg)](https://badge.fury.io/rb/rollout)
6
+ [![CircleCI](https://circleci.com/gh/fetlife/rollout.svg?style=svg)](https://circleci.com/gh/fetlife/rollout)
7
+ [![Code Climate](https://codeclimate.com/github/FetLife/rollout/badges/gpa.svg)](https://codeclimate.com/github/FetLife/rollout)
8
+ [![Test Coverage](https://codeclimate.com/github/FetLife/rollout/badges/coverage.svg)](https://codeclimate.com/github/FetLife/rollout/coverage)
9
9
 
10
10
  ## Install it
11
11
 
@@ -20,7 +20,7 @@ Initialize a rollout object. I assign it to a global var.
20
20
  ```ruby
21
21
  require 'redis'
22
22
 
23
- $redis = Redis.new
23
+ $redis = Redis.new
24
24
  $rollout = Rollout.new($redis)
25
25
  ```
26
26
 
@@ -71,6 +71,9 @@ Deactivate groups like this:
71
71
  $rollout.deactivate_group(:chat, :all)
72
72
  ```
73
73
 
74
+ Groups need to be defined every time your app starts. The logic is not persisted
75
+ anywhere.
76
+
74
77
  ## Specific Users
75
78
 
76
79
  You might want to let a specific user into a beta test or something. If that
@@ -98,7 +101,7 @@ $rollout.activate_percentage(:chat, 20)
98
101
  The algorithm for determining which users get let in is this:
99
102
 
100
103
  ```ruby
101
- CRC32(user.id) % 100_000 < percentage * 1_000
104
+ CRC32(user.id) < (2**32 - 1) / 100.0 * percentage
102
105
  ```
103
106
 
104
107
  So, for 20%, users 0, 1, 10, 11, 20, 21, etc would be allowed in. Those users
@@ -176,6 +179,7 @@ This example would use the "development:feature:chat:groups" key.
176
179
  * Python: https://github.com/asenchi/proclaim
177
180
  * PHP: https://github.com/opensoft/rollout
178
181
  * Clojure: https://github.com/yeller/shoutout
182
+ * Perl: https://metacpan.org/pod/Toggle
179
183
 
180
184
 
181
185
  ## Contributors
data/Rakefile CHANGED
@@ -1,9 +1,7 @@
1
- begin
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
3
2
 
4
- RSpec::Core::RakeTask.new(:spec)
3
+ require 'rspec/core/rake_task'
5
4
 
6
- task default: :spec
7
- rescue LoadError
8
- # no rspec available
9
- end
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Rollout
2
- VERSION = "2.4.1"
4
+ VERSION = '2.4.5'
3
5
  end
data/lib/rollout.rb CHANGED
@@ -1,9 +1,13 @@
1
- require "rollout/version"
2
- require "zlib"
3
- require "set"
4
- require "json"
1
+ # frozen_string_literal: true
2
+
3
+ require 'rollout/version'
4
+ require 'zlib'
5
+ require 'set'
6
+ require 'json'
5
7
 
6
8
  class Rollout
9
+ RAND_BASE = (2**32 - 1) / 100.0
10
+
7
11
  class Feature
8
12
  attr_accessor :groups, :users, :percentage, :data
9
13
  attr_reader :name, :options
@@ -13,7 +17,7 @@ class Rollout
13
17
  @name = name
14
18
 
15
19
  if string
16
- raw_percentage,raw_users,raw_groups,raw_data = string.split('|', 4)
20
+ raw_percentage, raw_users, raw_groups, raw_data = string.split('|', 4)
17
21
  @percentage = raw_percentage.to_f
18
22
  @users = users_from_string(raw_users)
19
23
  @groups = groups_from_string(raw_groups)
@@ -24,7 +28,7 @@ class Rollout
24
28
  end
25
29
 
26
30
  def serialize
27
- "#{@percentage}|#{@users.to_a.join(",")}|#{@groups.to_a.join(",")}|#{serialize_data}"
31
+ "#{@percentage}|#{@users.to_a.join(',')}|#{@groups.to_a.join(',')}|#{serialize_data}"
28
32
  end
29
33
 
30
34
  def add_user(user)
@@ -45,8 +49,8 @@ class Rollout
45
49
  end
46
50
 
47
51
  def clear
48
- @groups = groups_from_string("")
49
- @users = users_from_string("")
52
+ @groups = groups_from_string('')
53
+ @users = users_from_string('')
50
54
  @percentage = 0
51
55
  @data = {}
52
56
  end
@@ -56,7 +60,7 @@ class Rollout
56
60
  id = user_id(user)
57
61
  user_in_percentage?(id) ||
58
62
  user_in_active_users?(id) ||
59
- user_in_active_group?(user, rollout)
63
+ user_in_active_group?(user, rollout)
60
64
  else
61
65
  @percentage == 100
62
66
  end
@@ -75,65 +79,66 @@ class Rollout
75
79
  end
76
80
 
77
81
  private
78
- def user_id(user)
79
- if user.is_a?(Integer) || user.is_a?(String)
80
- user.to_s
81
- else
82
- user.send(id_user_by).to_s
83
- end
84
- end
85
82
 
86
- def id_user_by
87
- @options[:id_user_by] || :id
83
+ def user_id(user)
84
+ if user.is_a?(Integer) || user.is_a?(String)
85
+ user.to_s
86
+ else
87
+ user.send(id_user_by).to_s
88
88
  end
89
+ end
89
90
 
90
- def user_in_percentage?(user)
91
- Zlib.crc32(user_id_for_percentage(user)) % 100_000 < @percentage * 1_000
92
- end
91
+ def id_user_by
92
+ @options[:id_user_by] || :id
93
+ end
93
94
 
94
- def user_id_for_percentage(user)
95
- if @options[:randomize_percentage]
96
- user_id(user).to_s + @name.to_s
97
- else
98
- user_id(user)
99
- end
95
+ def user_in_percentage?(user)
96
+ Zlib.crc32(user_id_for_percentage(user)) < RAND_BASE * @percentage
97
+ end
98
+
99
+ def user_id_for_percentage(user)
100
+ if @options[:randomize_percentage]
101
+ user_id(user).to_s + @name.to_s
102
+ else
103
+ user_id(user)
100
104
  end
105
+ end
101
106
 
102
- def user_in_active_group?(user, rollout)
103
- @groups.any? do |g|
104
- rollout.active_in_group?(g, user)
105
- end
107
+ def user_in_active_group?(user, rollout)
108
+ @groups.any? do |g|
109
+ rollout.active_in_group?(g, user)
106
110
  end
111
+ end
107
112
 
108
- def serialize_data
109
- return "" unless @data.is_a? Hash
113
+ def serialize_data
114
+ return '' unless @data.is_a? Hash
110
115
 
111
- @data.to_json
112
- end
116
+ @data.to_json
117
+ end
113
118
 
114
- def users_from_string(raw_users)
115
- users = (raw_users || "").split(",").map(&:to_s)
116
- if @options[:use_sets]
117
- users.to_set
118
- else
119
- users
120
- end
119
+ def users_from_string(raw_users)
120
+ users = (raw_users || '').split(',').map(&:to_s)
121
+ if @options[:use_sets]
122
+ users.to_set
123
+ else
124
+ users
121
125
  end
126
+ end
122
127
 
123
- def groups_from_string(raw_groups)
124
- groups = (raw_groups || "").split(",").map(&:to_sym)
125
- if @options[:use_sets]
126
- groups.to_set
127
- else
128
- groups
129
- end
128
+ def groups_from_string(raw_groups)
129
+ groups = (raw_groups || '').split(',').map(&:to_sym)
130
+ if @options[:use_sets]
131
+ groups.to_set
132
+ else
133
+ groups
130
134
  end
135
+ end
131
136
  end
132
137
 
133
138
  def initialize(storage, opts = {})
134
139
  @storage = storage
135
140
  @options = opts
136
- @groups = { all: lambda { |user| true } }
141
+ @groups = { all: ->(_user) { true } }
137
142
  end
138
143
 
139
144
  def activate(feature)
@@ -143,15 +148,13 @@ class Rollout
143
148
  end
144
149
 
145
150
  def deactivate(feature)
146
- with_feature(feature) do |f|
147
- f.clear
148
- end
151
+ with_feature(feature, &:clear)
149
152
  end
150
153
 
151
154
  def delete(feature)
152
- features = (@storage.get(features_key) || "").split(",")
155
+ features = (@storage.get(features_key) || '').split(',')
153
156
  features.delete(feature.to_s)
154
- @storage.set(features_key, features.join(","))
157
+ @storage.set(features_key, features.join(','))
155
158
  @storage.del(key(feature))
156
159
  end
157
160
 
@@ -191,13 +194,20 @@ class Rollout
191
194
 
192
195
  def activate_users(feature, users)
193
196
  with_feature(feature) do |f|
194
- users.each{|user| f.add_user(user)}
197
+ users.each { |user| f.add_user(user) }
195
198
  end
196
199
  end
197
200
 
198
201
  def deactivate_users(feature, users)
199
202
  with_feature(feature) do |f|
200
- users.each{|user| f.remove_user(user)}
203
+ users.each { |user| f.remove_user(user) }
204
+ end
205
+ end
206
+
207
+ def set_users(feature, users)
208
+ with_feature(feature) do |f|
209
+ f.users = []
210
+ users.each { |user| f.add_user(user) }
201
211
  end
202
212
  end
203
213
 
@@ -233,7 +243,7 @@ class Rollout
233
243
 
234
244
  def active_in_group?(group, user)
235
245
  f = @groups[group.to_sym]
236
- f && f.call(user)
246
+ f&.call(user)
237
247
  end
238
248
 
239
249
  def get(feature)
@@ -254,35 +264,41 @@ class Rollout
254
264
  end
255
265
 
256
266
  def multi_get(*features)
257
- feature_keys = features.map{ |feature| key(feature) }
267
+ return [] if features.empty?
268
+
269
+ feature_keys = features.map { |feature| key(feature) }
258
270
  @storage.mget(*feature_keys).map.with_index { |string, index| Feature.new(features[index], string, @options) }
259
271
  end
260
272
 
261
273
  def features
262
- (@storage.get(features_key) || "").split(",").map(&:to_sym)
274
+ (@storage.get(features_key) || '').split(',').map(&:to_sym)
263
275
  end
264
276
 
265
277
  def feature_states(user = nil)
266
- features.each_with_object({}) do |f, hash|
267
- hash[f] = active?(f, user)
278
+ multi_get(*features).each_with_object({}) do |f, hash|
279
+ hash[f.name] = f.active?(self, user)
268
280
  end
269
281
  end
270
282
 
271
283
  def active_features(user = nil)
272
- features.select do |f|
273
- active?(f, user)
274
- end
284
+ multi_get(*features).select do |f|
285
+ f.active?(self, user)
286
+ end.map(&:name)
275
287
  end
276
288
 
277
289
  def clear!
278
290
  features.each do |feature|
279
- with_feature(feature) { |f| f.clear }
291
+ with_feature(feature, &:clear)
280
292
  @storage.del(key(feature))
281
293
  end
282
294
 
283
295
  @storage.del(features_key)
284
296
  end
285
297
 
298
+ def exists?(feature)
299
+ @storage.exists(key(feature))
300
+ end
301
+
286
302
  private
287
303
 
288
304
  def key(name)
@@ -290,7 +306,7 @@ class Rollout
290
306
  end
291
307
 
292
308
  def features_key
293
- "feature:__features__"
309
+ 'feature:__features__'
294
310
  end
295
311
 
296
312
  def with_feature(feature)
@@ -301,6 +317,6 @@ class Rollout
301
317
 
302
318
  def save(feature)
303
319
  @storage.set(key(feature.name), feature.serialize)
304
- @storage.set(features_key, (features | [feature.name.to_sym]).join(","))
320
+ @storage.set(features_key, (features | [feature.name.to_sym]).join(','))
305
321
  end
306
322
  end
data/rollout.gemspec CHANGED
@@ -1,27 +1,31 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "rollout/version"
1
+ # frozen_string_literal: true
4
2
 
5
- Gem::Specification.new do |s|
6
- s.name = "rollout"
7
- s.version = Rollout::VERSION
8
- s.authors = ["James Golick"]
9
- s.email = ["jamesgolick@gmail.com"]
10
- s.description = "Feature flippers with redis."
11
- s.summary = "Feature flippers with redis."
12
- s.homepage = "https://github.com/FetLife/rollout"
13
- s.license = "MIT"
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+ require 'rollout/version'
14
5
 
15
- s.files = `git ls-files`.split("\n")
16
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
- s.require_paths = ["lib"]
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rollout'
8
+ spec.version = Rollout::VERSION
9
+ spec.authors = ['James Golick']
10
+ spec.email = ['jamesgolick@gmail.com']
11
+ spec.description = 'Feature flippers with redis.'
12
+ spec.summary = 'Feature flippers with redis.'
13
+ spec.homepage = 'https://github.com/FetLife/rollout'
14
+ spec.license = 'MIT'
19
15
 
20
- s.add_development_dependency "rspec"
21
- s.add_development_dependency "appraisal"
22
- s.add_development_dependency "bundler", ">= 1.0.0"
23
- s.add_development_dependency "redis"
24
- s.add_development_dependency "fakeredis"
25
- s.add_development_dependency "simplecov"
26
- s.add_development_dependency "codeclimate-test-reporter"
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 2.3'
22
+
23
+ spec.add_dependency 'redis', '~> 4.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.17'
26
+ spec.add_development_dependency 'fakeredis'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4'
29
+ spec.add_development_dependency 'rubocop', '~> 0.71'
30
+ spec.add_development_dependency 'simplecov', '~> 0.16'
27
31
  end
data/spec/rollout_spec.rb CHANGED
@@ -226,6 +226,16 @@ RSpec.describe "Rollout" do
226
226
  end
227
227
  end
228
228
 
229
+
230
+ describe 'set a group of users' do
231
+ it 'should replace the users with the given array' do
232
+ users = %w(1 2 3 4)
233
+ @rollout.activate_users(:chat, %w(10 20 30))
234
+ @rollout.set_users(:chat, users)
235
+ expect(@rollout.get(:chat).users).to eq(users)
236
+ end
237
+ end
238
+
229
239
  describe "activating a feature globally" do
230
240
  before do
231
241
  @rollout.activate(:chat)
@@ -595,6 +605,12 @@ RSpec.describe "Rollout" do
595
605
  expect(features[2].percentage).to eq 100
596
606
  expect(features.size).to eq 3
597
607
  end
608
+
609
+ describe 'when given feature keys is empty' do
610
+ it 'returns empty array' do
611
+ expect(@rollout.multi_get(*[])).to match_array([])
612
+ end
613
+ end
598
614
  end
599
615
 
600
616
  describe "#set_feature_data" do
@@ -646,6 +662,17 @@ RSpec.describe "Rollout" do
646
662
  expect(@rollout.get(:chat).data).to eq({})
647
663
  end
648
664
  end
665
+
666
+ describe 'Check if feature exists' do
667
+ it 'it should return true if the feature is exist' do
668
+ @rollout.activate_percentage(:chat, 1)
669
+ expect(@rollout.exists?(:chat)).to be true
670
+ end
671
+
672
+ it 'it should return false if the feature is not exist' do
673
+ expect(@rollout.exists?(:chat)).to be false
674
+ end
675
+ end
649
676
  end
650
677
 
651
678
  describe "Rollout::Feature" do
data/spec/spec_helper.rb CHANGED
@@ -1,18 +1,21 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
1
+ # frozen_string_literal: true
3
2
 
4
- require "simplecov"
5
- require "rspec"
6
- require ENV["USE_REAL_REDIS"] == "true" ? "redis" : "fakeredis"
3
+ require 'simplecov'
7
4
 
8
- SimpleCov.start do
9
- formatter SimpleCov::Formatter::MultiFormatter.new([
10
- SimpleCov::Formatter::HTMLFormatter,
11
- ])
12
- end
5
+ SimpleCov.start
13
6
 
7
+ require 'bundler/setup'
8
+ require ENV["USE_REAL_REDIS"] == "true" ? "redis" : "fakeredis"
14
9
  require "rollout"
15
10
 
16
11
  RSpec.configure do |config|
12
+ config.example_status_persistence_file_path = '.rspec_status'
13
+
14
+ # config.disable_monkey_patching!
15
+
16
+ config.expect_with :rspec do |c|
17
+ c.syntax = :expect
18
+ end
19
+
17
20
  config.before { Redis.new.flushdb }
18
21
  end
metadata CHANGED
@@ -1,113 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollout
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Golick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-08 00:00:00.000000000 Z
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: redis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
19
+ version: '4.0'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '4.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: appraisal
28
+ name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.17'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.17'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: fakeredis
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.0
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: redis
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: fakeredis
70
+ name: rspec_junit_formatter
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.4'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '0.4'
83
83
  - !ruby/object:Gem::Dependency
84
- name: simplecov
84
+ name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '0.71'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '0.71'
97
97
  - !ruby/object:Gem::Dependency
98
- name: codeclimate-test-reporter
98
+ name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '0.16'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '0.16'
111
111
  description: Feature flippers with redis.
112
112
  email:
113
113
  - jamesgolick@gmail.com
@@ -115,18 +115,16 @@ executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
- - ".document"
118
+ - ".circleci/config.yml"
119
119
  - ".gitignore"
120
120
  - ".rspec"
121
+ - ".rubocop.yml"
121
122
  - ".travis.yml"
122
- - Appraisals
123
123
  - Gemfile
124
124
  - Gemfile.lock
125
125
  - LICENSE
126
126
  - README.md
127
127
  - Rakefile
128
- - gemfiles/redis_3.gemfile
129
- - gemfiles/redis_4.gemfile
130
128
  - lib/rollout.rb
131
129
  - lib/rollout/version.rb
132
130
  - rollout.gemspec
@@ -144,15 +142,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
142
  requirements:
145
143
  - - ">="
146
144
  - !ruby/object:Gem::Version
147
- version: '0'
145
+ version: '2.3'
148
146
  required_rubygems_version: !ruby/object:Gem::Requirement
149
147
  requirements:
150
148
  - - ">="
151
149
  - !ruby/object:Gem::Version
152
150
  version: '0'
153
151
  requirements: []
154
- rubyforge_project:
155
- rubygems_version: 2.6.10
152
+ rubygems_version: 3.0.3
156
153
  signing_key:
157
154
  specification_version: 4
158
155
  summary: Feature flippers with redis.
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/Appraisals DELETED
@@ -1,7 +0,0 @@
1
- appraise "redis-3" do
2
- gem "redis", "~> 3.3.2"
3
- end
4
-
5
- appraise "redis-4" do
6
- gem "redis", "4.0.0.rc1"
7
- end
@@ -1,13 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- if RUBY_VERSION >= '2.0'
6
- gem "json"
7
- else
8
- gem "json", "~> 1.8.3"
9
- end
10
-
11
- gem "redis", "~> 3.3.2"
12
-
13
- gemspec :path => "../"
@@ -1,13 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- if RUBY_VERSION >= '2.0'
6
- gem "json"
7
- else
8
- gem "json", "~> 1.8.3"
9
- end
10
-
11
- gem "redis", "4.0.0.rc1"
12
-
13
- gemspec :path => "../"