featurer 0.0.1
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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +155 -0
- data/Rakefile +9 -0
- data/featurer.gemspec +31 -0
- data/lib/featurer/adapter.rb +29 -0
- data/lib/featurer/adapter_manager.rb +29 -0
- data/lib/featurer/adapter_proxy.rb +24 -0
- data/lib/featurer/adapters/redis.rb +45 -0
- data/lib/featurer/facade.rb +30 -0
- data/lib/featurer/version.rb +3 -0
- data/lib/featurer.rb +10 -0
- data/spec/lib/featurer/adapter_manager_spec.rb +21 -0
- data/spec/lib/featurer/adapter_proxy_spec.rb +19 -0
- data/spec/lib/featurer/adapters/redis_spec.rb +14 -0
- data/spec/lib/featurer/facade_spec.rb +52 -0
- data/spec/lib/featurer_spec.rb +65 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/fast_feedback_formatter.rb +13 -0
- metadata +200 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 121d24ce4e29bdf411ac7321930f1c5d3b09e499
|
4
|
+
data.tar.gz: 9bcd0d95f2e0fc4f5546873fb9ec9199d6177721
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3796c1cdccc1c4c8de217f66730d3e322f567687a1a299b6f1dd77d555c178b4fd10bc90682286fbd8afc044e4e81c1db1b7121fb5e258eab4e172577bb20490
|
7
|
+
data.tar.gz: 5e24d8700f2d416164835e721b6ab227be0068d123867adcb5c639065405cc4e1a7044bb7716a9df814c1fa2cdccb67a9e90102bb23f7f901c721cbd299471e2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.1
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alejandro El Informático
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# Featurer
|
2
|
+
Easy _feature flag_ for your project.
|
3
|
+
|
4
|
+
By default `featurer` saves all the data in Redis, although you can create your own adapter.
|
5
|
+
|
6
|
+
## Features
|
7
|
+
|
8
|
+
* Shipped with Redis support by default
|
9
|
+
* Fast
|
10
|
+
* Doesn't overload your main database
|
11
|
+
* Doesn't save data in your application's memory(don't lose it when restarting)
|
12
|
+
* Redis goodies :D
|
13
|
+
* Non-framework dependent
|
14
|
+
* Plug it wherever you want, Sinatra, Padrino, Rails, your own scripts...
|
15
|
+
* Create your own adapter
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'featurer'
|
23
|
+
```
|
24
|
+
|
25
|
+
And then execute:
|
26
|
+
|
27
|
+
$ bundle
|
28
|
+
|
29
|
+
Or install it yourself as:
|
30
|
+
|
31
|
+
$ gem install featurer
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Configure your connection:
|
36
|
+
```ruby
|
37
|
+
Featurer.configure(host: host, port: port)
|
38
|
+
```
|
39
|
+
|
40
|
+
or use the default _localhost_ connection:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
Featurer.init
|
44
|
+
```
|
45
|
+
|
46
|
+
### Start using it:
|
47
|
+
|
48
|
+
#### Per user feature
|
49
|
+
|
50
|
+
For different users:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Featurer.register(:feature, [first_user_id, sercond_users_id, third_user_id])
|
54
|
+
```
|
55
|
+
|
56
|
+
or single:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
Featurer.register(:feature, user_id)
|
60
|
+
```
|
61
|
+
|
62
|
+
Then request the enabled feature:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
Featurer.on?(:feature, user_id)
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Global feature
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
Featurer.register(:feature, true)
|
72
|
+
```
|
73
|
+
|
74
|
+
Then request the enabled feature:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
Featurer.on? :feature
|
78
|
+
```
|
79
|
+
|
80
|
+
#### Deleting features
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
Featurer.delete(:feature)
|
84
|
+
```
|
85
|
+
|
86
|
+
#### Create your own adapter
|
87
|
+
|
88
|
+
Just extend `Featurer::Adapter`, add the basic methods and your are done! e.g
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class TestAdapter < Featurer::Adapter
|
92
|
+
def prepare
|
93
|
+
# if defined this is called automatically
|
94
|
+
# in order to initialize your adapter
|
95
|
+
# e.g: @redis = Redis.new
|
96
|
+
end
|
97
|
+
|
98
|
+
def register(name, value = true)
|
99
|
+
# your logic
|
100
|
+
end
|
101
|
+
|
102
|
+
def on?(name, value = true)
|
103
|
+
# your logic
|
104
|
+
end
|
105
|
+
|
106
|
+
def delete(name)
|
107
|
+
# your logic
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
**This will automatically register your adapter in the adapters list**.
|
112
|
+
Also it will give it an _id_, in this case `test`, is the lowercase _class name_ without
|
113
|
+
the adapter keyword.
|
114
|
+
|
115
|
+
Then initialize your `featurer`:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
Featurer.configure(adapter: :test, custom: :option)
|
119
|
+
```
|
120
|
+
|
121
|
+
Your are ready to go! No need to call `.init`
|
122
|
+
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
1. Fork it ( https://github.com/ainformatico/featurer/fork )
|
127
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
128
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
129
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
130
|
+
5. Create a [new Pull Request](https://github.com/ainformatico/featurer/compare)
|
131
|
+
|
132
|
+
## License
|
133
|
+
|
134
|
+
Copyright (c) 2014 Alejandro El Informático
|
135
|
+
|
136
|
+
MIT License
|
137
|
+
|
138
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
139
|
+
a copy of this software and associated documentation files (the
|
140
|
+
"Software"), to deal in the Software without restriction, including
|
141
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
142
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
143
|
+
permit persons to whom the Software is furnished to do so, subject to
|
144
|
+
the following conditions:
|
145
|
+
|
146
|
+
The above copyright notice and this permission notice shall be
|
147
|
+
included in all copies or substantial portions of the Software.
|
148
|
+
|
149
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
150
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
151
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
152
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
153
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
154
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
155
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/featurer.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'featurer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'featurer'
|
8
|
+
spec.version = Featurer::VERSION
|
9
|
+
spec.authors = ['Alejandro El Informatico']
|
10
|
+
spec.email = ['aeinformatico@gmail.com']
|
11
|
+
spec.summary = %q{Easy feature flag for your project}
|
12
|
+
spec.description = %q{Easy feature flag for your project shipped with Redis support}
|
13
|
+
spec.homepage = 'https://github.com/ainformatico/featurer'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'redis', '~> 3.1'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
26
|
+
spec.add_development_dependency 'rubocop', '~> 0.26'
|
27
|
+
spec.add_development_dependency 'guard', '~> 2.6'
|
28
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.3'
|
29
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
30
|
+
spec.add_development_dependency 'pry-debugger', '~> 0.2'
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Featurer
|
2
|
+
class Adapter
|
3
|
+
attr_reader :config
|
4
|
+
|
5
|
+
def self.inherited(klass)
|
6
|
+
AdapterManager.add_adapter klass
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(config = {})
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def delete(feature)
|
14
|
+
fail 'implement a delete method'
|
15
|
+
end
|
16
|
+
|
17
|
+
def key(name)
|
18
|
+
fail 'implement a key method'
|
19
|
+
end
|
20
|
+
|
21
|
+
def on?(feature, user_id = nil)
|
22
|
+
fail 'implement a on? method'
|
23
|
+
end
|
24
|
+
|
25
|
+
def register(name, value = true)
|
26
|
+
fail 'implement a register? method'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Featurer
|
2
|
+
class AdapterManager
|
3
|
+
class << self
|
4
|
+
def add_adapter(klass)
|
5
|
+
name = extract_name(klass)
|
6
|
+
adapters[name] = klass
|
7
|
+
end
|
8
|
+
|
9
|
+
def adapters
|
10
|
+
@adapters ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(name, config)
|
14
|
+
adapters
|
15
|
+
.fetch(name)
|
16
|
+
.new(config)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def extract_name(klass)
|
22
|
+
klass.name
|
23
|
+
.downcase[/(?:\w+$)/] # get only class name
|
24
|
+
.sub('adapter', '') # remove adapter prefix
|
25
|
+
.to_sym
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Featurer
|
2
|
+
class AdapterProxy
|
3
|
+
attr_reader :adapter
|
4
|
+
|
5
|
+
def initialize(config = {})
|
6
|
+
initialize_adapter(default_options.merge(config))
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_options
|
12
|
+
# redis adapter is shipped within this gem
|
13
|
+
{
|
14
|
+
adapter: :redis,
|
15
|
+
prefix: :featurer
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize_adapter(config)
|
20
|
+
@adapter = AdapterManager.run(config[:adapter], config)
|
21
|
+
@adapter.prepare if @adapter.respond_to? :prepare
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Featurer
|
4
|
+
class RedisAdapter < Adapter
|
5
|
+
def prepare
|
6
|
+
@redis = ::Redis.new({
|
7
|
+
host: @config[:host],
|
8
|
+
port: @config[:port],
|
9
|
+
db: @config[:db]
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
def delete(feature)
|
14
|
+
delete_key(feature)
|
15
|
+
end
|
16
|
+
|
17
|
+
def on?(feature, value = true)
|
18
|
+
fetch_from_set(feature, value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def register(name, value = true)
|
22
|
+
# ensure old data is wiped
|
23
|
+
delete(name)
|
24
|
+
save_set(name, value)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def key(name)
|
30
|
+
"#{@config[:prefix]}:feature:#{name}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete_key(name)
|
34
|
+
@redis.del key(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def save_set(name, value)
|
38
|
+
@redis.sadd key(name), value
|
39
|
+
end
|
40
|
+
|
41
|
+
def fetch_from_set(name, id)
|
42
|
+
@redis.sismember(key(name), id)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Featurer
|
2
|
+
module Facade
|
3
|
+
attr_accessor :adapter
|
4
|
+
|
5
|
+
def configure(config)
|
6
|
+
@adapter = AdapterProxy.new(config).adapter
|
7
|
+
end
|
8
|
+
|
9
|
+
def reset
|
10
|
+
@adapter = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def init!
|
14
|
+
reset
|
15
|
+
init
|
16
|
+
end
|
17
|
+
|
18
|
+
def init
|
19
|
+
@adapter ||= AdapterProxy.new.adapter
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(method, *args)
|
23
|
+
if @adapter.respond_to? method
|
24
|
+
@adapter.send(method, *args)
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/featurer.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Featurer::AdapterManager do
|
4
|
+
|
5
|
+
describe 'registered adapters' do
|
6
|
+
it 'checks the default adapter' do
|
7
|
+
expect(Featurer::AdapterManager.adapters).to include(redis: Featurer::RedisAdapter)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'create new adapters' do
|
12
|
+
it 'registers a new adapter' do
|
13
|
+
expect(Featurer::AdapterManager).to receive(:add_adapter).and_call_original
|
14
|
+
|
15
|
+
class TestAdapter < Featurer::Adapter
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(Featurer::AdapterManager.adapters).to include(test: TestAdapter)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Featurer::AdapterProxy do
|
4
|
+
|
5
|
+
describe 'default adapter' do
|
6
|
+
it 'creates the default adapter' do
|
7
|
+
proxy = Featurer::AdapterProxy.new
|
8
|
+
expect(proxy.adapter).to be_an(Featurer::RedisAdapter)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'creates a new adapter' do
|
12
|
+
class TestAdapter < Featurer::Adapter
|
13
|
+
end
|
14
|
+
|
15
|
+
proxy = Featurer::AdapterProxy.new(adapter: :test)
|
16
|
+
expect(proxy.adapter).to be_an(TestAdapter)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Featurer::RedisAdapter do
|
4
|
+
it 'should create the connection' do
|
5
|
+
expect_any_instance_of(Featurer::RedisAdapter).to receive(:prepare)
|
6
|
+
.and_call_original
|
7
|
+
|
8
|
+
Featurer.init
|
9
|
+
redis_handler = Featurer.adapter.instance_variable_get(:@redis)
|
10
|
+
|
11
|
+
expect(redis_handler).to be_an(Redis)
|
12
|
+
expect(redis_handler.ping).to eq('PONG')
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Featurer::Facade do
|
4
|
+
describe 'configuration' do
|
5
|
+
it 'should use default options' do
|
6
|
+
Featurer.init!
|
7
|
+
expect(Featurer.adapter.config).to include(adapter: :redis)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should configure the adapter' do
|
11
|
+
options = {
|
12
|
+
adapter: :redis,
|
13
|
+
prefix: :custom,
|
14
|
+
host: '192.168.1.1'
|
15
|
+
}
|
16
|
+
Featurer.configure(options)
|
17
|
+
expect(Featurer.adapter.config).to include(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'reset configuration' do
|
22
|
+
before do
|
23
|
+
class NilAdapter < Featurer::Adapter
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#init' do
|
28
|
+
it 'should reset the adapter' do
|
29
|
+
Featurer.configure(adapter: :nil)
|
30
|
+
Featurer.init!
|
31
|
+
|
32
|
+
expect(Featurer.config).to include(adapter: :redis)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not reset the adapter' do
|
36
|
+
Featurer.configure(adapter: :nil, prefix: :custom)
|
37
|
+
Featurer.init
|
38
|
+
|
39
|
+
expect(Featurer.config).to eq(adapter: :nil, prefix: :custom)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#reset' do
|
44
|
+
it 'should reset the adapter' do
|
45
|
+
Featurer.configure(adapter: :nil)
|
46
|
+
Featurer.reset
|
47
|
+
|
48
|
+
expect(Featurer.adapter).to_not be
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Featurer do
|
4
|
+
describe 'feature flag is defined' do
|
5
|
+
after(:each) { Featurer.delete(:feature) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Featurer.init!
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:user_id) { 1 }
|
12
|
+
|
13
|
+
describe 'per user' do
|
14
|
+
it 'returns true because user is in the list' do
|
15
|
+
Featurer.register :feature, [user_id]
|
16
|
+
expect(Featurer.on?(:feature, user_id)).to be
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'defines the user twice and returns true' do
|
20
|
+
Featurer.register :feature, [user_id]
|
21
|
+
Featurer.register :feature, [user_id]
|
22
|
+
expect(Featurer.on?(:feature, user_id)).to be
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns false because user is not in the list' do
|
26
|
+
Featurer.register :feature, [user_id + 1]
|
27
|
+
expect(Featurer.on?(:feature, user_id)).to_not be
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'converts a per user feature into a global one' do
|
31
|
+
Featurer.register :feature, [user_id]
|
32
|
+
Featurer.register :feature, true
|
33
|
+
|
34
|
+
expect(Featurer.on?(:feature)).to be
|
35
|
+
expect(Featurer.on?(:feature, user_id)).to_not be
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'global' do
|
40
|
+
it 'returns true because the feature is enabled(default)' do
|
41
|
+
Featurer.register :feature
|
42
|
+
expect(Featurer.on?(:feature)).to be
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns true because the feature is enabled(manually)' do
|
46
|
+
Featurer.register :feature, true
|
47
|
+
expect(Featurer.on?(:feature)).to be
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns false because the feature is disabled' do
|
51
|
+
Featurer.register :feature, false
|
52
|
+
expect(Featurer.on?(:feature)).to_not be
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'converts a global feature into a per user one' do
|
56
|
+
Featurer.register :feature, true
|
57
|
+
Featurer.register :feature, [user_id]
|
58
|
+
|
59
|
+
expect(Featurer.on?(:feature, user_id)).to be
|
60
|
+
expect(Featurer.on?(:feature)).to_not be
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "rspec/core/formatters/progress_formatter"
|
2
|
+
|
3
|
+
class FastFeedbackFormatter < RSpec::Core::Formatters::ProgressFormatter
|
4
|
+
def example_failed(example)
|
5
|
+
super(example)
|
6
|
+
|
7
|
+
example_group = example.metadata[:example_group]
|
8
|
+
|
9
|
+
output.puts ""
|
10
|
+
output.puts red("#{example_group[:file_path]}:#{example_group[:line_number]}")
|
11
|
+
output.puts red(example.execution_result[:exception].to_s.strip)
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: featurer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alejandro El Informatico
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-29 00:00:00.000000000 Z
|
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: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.26'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.26'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard-rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '4.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.10'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.10'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-debugger
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.2'
|
139
|
+
description: Easy feature flag for your project shipped with Redis support
|
140
|
+
email:
|
141
|
+
- aeinformatico@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".gitignore"
|
147
|
+
- ".rspec"
|
148
|
+
- ".ruby-version"
|
149
|
+
- Gemfile
|
150
|
+
- Guardfile
|
151
|
+
- LICENSE.txt
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- featurer.gemspec
|
155
|
+
- lib/featurer.rb
|
156
|
+
- lib/featurer/adapter.rb
|
157
|
+
- lib/featurer/adapter_manager.rb
|
158
|
+
- lib/featurer/adapter_proxy.rb
|
159
|
+
- lib/featurer/adapters/redis.rb
|
160
|
+
- lib/featurer/facade.rb
|
161
|
+
- lib/featurer/version.rb
|
162
|
+
- spec/lib/featurer/adapter_manager_spec.rb
|
163
|
+
- spec/lib/featurer/adapter_proxy_spec.rb
|
164
|
+
- spec/lib/featurer/adapters/redis_spec.rb
|
165
|
+
- spec/lib/featurer/facade_spec.rb
|
166
|
+
- spec/lib/featurer_spec.rb
|
167
|
+
- spec/spec_helper.rb
|
168
|
+
- spec/support/fast_feedback_formatter.rb
|
169
|
+
homepage: https://github.com/ainformatico/featurer
|
170
|
+
licenses:
|
171
|
+
- MIT
|
172
|
+
metadata: {}
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
require_paths:
|
176
|
+
- lib
|
177
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
requirements: []
|
188
|
+
rubyforge_project:
|
189
|
+
rubygems_version: 2.2.2
|
190
|
+
signing_key:
|
191
|
+
specification_version: 4
|
192
|
+
summary: Easy feature flag for your project
|
193
|
+
test_files:
|
194
|
+
- spec/lib/featurer/adapter_manager_spec.rb
|
195
|
+
- spec/lib/featurer/adapter_proxy_spec.rb
|
196
|
+
- spec/lib/featurer/adapters/redis_spec.rb
|
197
|
+
- spec/lib/featurer/facade_spec.rb
|
198
|
+
- spec/lib/featurer_spec.rb
|
199
|
+
- spec/spec_helper.rb
|
200
|
+
- spec/support/fast_feedback_formatter.rb
|