arturo 1.4.0 → 1.5.0
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.
- data/README.md +1 -17
- data/app/controllers/arturo/features_controller.rb +18 -10
- data/app/helpers/arturo/features_helper.rb +16 -3
- data/app/models/arturo/feature.rb +9 -3
- data/app/views/arturo/features/_feature.html.erb +1 -1
- data/app/views/arturo/features/_form.html.erb +1 -1
- data/app/views/arturo/features/edit.html.erb +3 -0
- data/app/views/arturo/features/forbidden.html.erb +3 -0
- data/app/views/arturo/features/index.html.erb +5 -2
- data/app/views/arturo/features/new.html.erb +3 -0
- data/app/views/arturo/features/show.html.erb +3 -0
- data/config/locales/en.yml +4 -1
- data/config/routes.rb +12 -13
- data/lib/arturo.rb +1 -1
- data/lib/arturo/feature_caching.rb +14 -9
- data/lib/arturo/feature_factories.rb +7 -3
- data/lib/arturo/feature_params_support.rb +38 -0
- data/lib/arturo/no_such_feature.rb +29 -0
- metadata +137 -120
data/README.md
CHANGED
@@ -88,7 +88,7 @@ of Arturo.
|
|
88
88
|
|
89
89
|
$ rails g arturo:migration
|
90
90
|
$ rails g arturo:initializer
|
91
|
-
$ rails g arturo:
|
91
|
+
$ rails g arturo:routes
|
92
92
|
$ rails g arturo:assets
|
93
93
|
|
94
94
|
#### Run the migration:
|
@@ -277,19 +277,3 @@ percentage. See `Arturo::CacheSupport` for more information.
|
|
277
277
|
Arturo gets its name from
|
278
278
|
[Professor Maximillian Arturo](http://en.wikipedia.org/wiki/Maximillian_Arturo)
|
279
279
|
on [Sliders](http://en.wikipedia.org/wiki/Sliders).
|
280
|
-
|
281
|
-
## Contributing ##
|
282
|
-
|
283
|
-
For bug reports, open an [issue](https://github.com/jamesarosen/Timecop.js/issues)
|
284
|
-
on GitHub.
|
285
|
-
|
286
|
-
Timecop.js has a ‘commit-bit’ policy, much like the Rubinius project
|
287
|
-
and Gemcutter. Submit a patch that is accepted, and you can get full
|
288
|
-
commit access to the project. All you have to do is open an issue
|
289
|
-
asking for access and I'll add you as a collaborator.
|
290
|
-
Feel free to fork the project though and have fun in your own sandbox.
|
291
|
-
|
292
|
-
## Authors ##
|
293
|
-
|
294
|
-
* [https://github.com/jamesarosen](James A. Rosen)
|
295
|
-
* [https://github.com/plukevdh](Luke van der Hoeven)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'action_controller'
|
2
|
+
require 'arturo/feature_params_support'
|
2
3
|
|
3
4
|
# TODO: this doesn't do anything radically out of the ordinary.
|
4
5
|
# Are there Rails 3 patterns/mixins/methods I can use
|
@@ -10,12 +11,20 @@ module Arturo
|
|
10
11
|
# return true only for users who are permitted to manage features.
|
11
12
|
class FeaturesController < ApplicationController
|
12
13
|
include Arturo::FeatureManagement
|
14
|
+
include Arturo::FeatureParamsSupport
|
13
15
|
|
14
16
|
unloadable
|
15
17
|
respond_to :html, :json, :xml
|
16
18
|
before_filter :require_permission
|
17
19
|
before_filter :load_feature, :only => [ :show, :edit, :update, :destroy ]
|
18
20
|
|
21
|
+
if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0
|
22
|
+
def arturo_engine
|
23
|
+
self
|
24
|
+
end
|
25
|
+
helper_method :arturo_engine
|
26
|
+
end
|
27
|
+
|
19
28
|
def index
|
20
29
|
@features = Arturo::Feature.all
|
21
30
|
respond_with @features
|
@@ -24,7 +33,6 @@ module Arturo
|
|
24
33
|
def update_all
|
25
34
|
updated_count = 0
|
26
35
|
errors = []
|
27
|
-
features_params = params[:features] || {}
|
28
36
|
features_params.each do |id, attributes|
|
29
37
|
feature = Arturo::Feature.find_by_id(id)
|
30
38
|
if feature.blank?
|
@@ -32,7 +40,7 @@ module Arturo
|
|
32
40
|
elsif feature.update_attributes(attributes)
|
33
41
|
updated_count += 1
|
34
42
|
else
|
35
|
-
errors << t('arturo.features.flash.error_updating', :id => id)
|
43
|
+
errors << t('arturo.features.flash.error_updating', :id => id, :errors => feature.errors.full_messages.to_sentence)
|
36
44
|
end
|
37
45
|
end
|
38
46
|
if errors.any?
|
@@ -40,7 +48,7 @@ module Arturo
|
|
40
48
|
else
|
41
49
|
flash[:success] = t('arturo.features.flash.updated_many', :count => updated_count)
|
42
50
|
end
|
43
|
-
redirect_to features_path
|
51
|
+
redirect_to arturo_engine.features_path
|
44
52
|
end
|
45
53
|
|
46
54
|
def show
|
@@ -48,15 +56,15 @@ module Arturo
|
|
48
56
|
end
|
49
57
|
|
50
58
|
def new
|
51
|
-
@feature = Arturo::Feature.new(
|
59
|
+
@feature = Arturo::Feature.new(feature_params)
|
52
60
|
respond_with @feature
|
53
61
|
end
|
54
62
|
|
55
63
|
def create
|
56
|
-
@feature = Arturo::Feature.new(
|
64
|
+
@feature = Arturo::Feature.new(feature_params)
|
57
65
|
if @feature.save
|
58
66
|
flash[:notice] = t('arturo.features.flash.created', :name => @feature.to_s)
|
59
|
-
redirect_to features_path
|
67
|
+
redirect_to arturo_engine.features_path
|
60
68
|
else
|
61
69
|
flash[:alert] = t('arturo.features.flash.error_creating', :name => @feature.to_s)
|
62
70
|
render :action => 'new'
|
@@ -68,11 +76,11 @@ module Arturo
|
|
68
76
|
end
|
69
77
|
|
70
78
|
def update
|
71
|
-
if @feature.update_attributes(
|
79
|
+
if @feature.update_attributes(feature_params)
|
72
80
|
flash[:notice] = t('arturo.features.flash.updated', :name => @feature.to_s)
|
73
|
-
redirect_to feature_path(@feature)
|
81
|
+
redirect_to arturo_engine.feature_path(@feature)
|
74
82
|
else
|
75
|
-
|
83
|
+
flash[:alert] = t('arturo.features.flash.error_updating', :name => @feature.to_s)
|
76
84
|
render :action => 'edit'
|
77
85
|
end
|
78
86
|
end
|
@@ -83,7 +91,7 @@ module Arturo
|
|
83
91
|
else
|
84
92
|
flash[:alert] = t('arturo.features.flash.error_removing', :name => @feature.to_s)
|
85
93
|
end
|
86
|
-
redirect_to features_path
|
94
|
+
redirect_to arturo_engine.features_path
|
87
95
|
end
|
88
96
|
|
89
97
|
protected
|
@@ -1,10 +1,23 @@
|
|
1
|
-
require 'action_view/helpers/tag_helper'
|
2
|
-
require 'action_view/helpers/form_tag_helper'
|
3
|
-
|
4
1
|
module Arturo
|
5
2
|
module FeaturesHelper
|
6
3
|
include ActionView::Helpers::TagHelper
|
7
4
|
|
5
|
+
def arturo_flash_messages(flash = self.flash)
|
6
|
+
[ :success, :notice, :error ].inject(''.html_safe) do |output, status|
|
7
|
+
[* flash[status] ].each do |messages|
|
8
|
+
output += arturo_flash_message(status, messages)
|
9
|
+
end
|
10
|
+
output
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def arturo_flash_message(status, message)
|
15
|
+
content_tag(:div, :class => "alert alert-#{status} alert-arturo") do
|
16
|
+
close = content_tag(:a, '×'.html_safe, :href => '#', :class => 'close', 'data-dismiss' => 'alert')
|
17
|
+
content_tag(:span, message) + close
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
8
21
|
def deployment_percentage_range_and_output_tags(name, value, options = {})
|
9
22
|
id = sanitize_to_id(name)
|
10
23
|
options = {
|
@@ -10,6 +10,7 @@ module Arturo
|
|
10
10
|
Arturo::Feature::SYMBOL_REGEX = /^[a-zA-z][a-zA-Z0-9_]*$/
|
11
11
|
DEFAULT_ATTRIBUTES = { :deployment_percentage => 0 }.with_indifferent_access
|
12
12
|
|
13
|
+
attr_accessible :symbol, :deployment_percentage if Rails::VERSION::MAJOR < 4
|
13
14
|
attr_readonly :symbol
|
14
15
|
|
15
16
|
validates_presence_of :symbol, :deployment_percentage
|
@@ -29,8 +30,9 @@ module Arturo
|
|
29
30
|
end
|
30
31
|
|
31
32
|
# Create a new Feature
|
32
|
-
def initialize(
|
33
|
-
|
33
|
+
def initialize(*args, &block)
|
34
|
+
args[0] = DEFAULT_ATTRIBUTES.merge(args[0] || {})
|
35
|
+
super(*args, &block)
|
34
36
|
end
|
35
37
|
|
36
38
|
# @param [Object] feature_recipient a User, Account,
|
@@ -63,12 +65,16 @@ module Arturo
|
|
63
65
|
"<Arturo::Feature #{name}, deployed to #{deployment_percentage}%>"
|
64
66
|
end
|
65
67
|
|
68
|
+
def self.last_updated_at
|
69
|
+
maximum(:updated_at)
|
70
|
+
end
|
71
|
+
|
66
72
|
protected
|
67
73
|
|
68
74
|
def passes_threshold?(feature_recipient)
|
69
75
|
threshold = self.deployment_percentage || 0
|
70
|
-
return false if threshold == 0
|
71
76
|
return true if threshold == 100
|
77
|
+
return false if threshold == 0 || !feature_recipient.id
|
72
78
|
(((feature_recipient.id + (self.id || 1) + 17) * 13) % 100) < threshold
|
73
79
|
end
|
74
80
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<tr class='feature' id="feature_<%= feature.id %>">
|
2
2
|
<td><code class='ruby symbol'><%= feature.symbol %></code></td>
|
3
3
|
<td><%= deployment_percentage_range_and_output_tags("features[#{feature.id}][deployment_percentage]", feature.deployment_percentage) %></td>
|
4
|
-
<td><%= link_to t('.edit'), edit_feature_path(feature), :rel => 'edit', :class => 'edit' %></td>
|
4
|
+
<td><%= link_to t('.edit'), arturo_engine.edit_feature_path(feature), :rel => 'edit', :class => 'edit' %></td>
|
5
5
|
</tr>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= form_for(feature, :as => 'feature', :url => (feature.new_record? ? features_path : feature_path(feature))) do |form| %>
|
1
|
+
<%= form_for(feature, :as => 'feature', :url => (feature.new_record? ? arturo_engine.features_path : arturo_engine.feature_path(feature))) do |form| %>
|
2
2
|
<fieldset>
|
3
3
|
<legend><%= legend %></legend>
|
4
4
|
|
@@ -1,5 +1,8 @@
|
|
1
1
|
<h2><%= t('.title') %></h2>
|
2
|
-
|
2
|
+
|
3
|
+
<%= arturo_flash_messages %>
|
4
|
+
|
5
|
+
<%= form_tag(arturo_engine.features_path, :method => 'put', 'data-update-path' => arturo_engine.feature_path(:id => ':id'), :remote => true) do %>
|
3
6
|
<fieldset>
|
4
7
|
<legend><%= t('.title') %></legend>
|
5
8
|
<table class='features'>
|
@@ -14,7 +17,7 @@
|
|
14
17
|
</tr>
|
15
18
|
</thead>
|
16
19
|
<tfoot>
|
17
|
-
<tr><th colspan='4'><%= link_to t('.new'), new_feature_path %> <%= submit_tag %></th></tr>
|
20
|
+
<tr><th colspan='4'><%= link_to t('.new'), arturo_engine.new_feature_path %> <%= submit_tag %></th></tr>
|
18
21
|
</tfoot>
|
19
22
|
<tbody>
|
20
23
|
<% @features.each do |f| %>
|
data/config/locales/en.yml
CHANGED
@@ -35,6 +35,9 @@ en:
|
|
35
35
|
created: "Created %{name}"
|
36
36
|
error_creating: "Sorry, there was an error creating the feature."
|
37
37
|
updated: "Updated %{name}"
|
38
|
-
error_updating: "
|
38
|
+
error_updating: "Could not update feature #%{id}: %{errors}."
|
39
39
|
removed: "Removed %{name}"
|
40
40
|
error_removing: "Sorry, there was an error removing %{name}"
|
41
|
+
no_such_feature:
|
42
|
+
name: "NoSuchFeature: %{symbol}"
|
43
|
+
symbol_required: "NoSuchFeature marker objects must have a symbol."
|
data/config/routes.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0
|
2
|
+
Rails.application.routes.draw do
|
3
|
+
scope "/arturo" do
|
4
|
+
resources :features, :controller => "arturo/features"
|
5
|
+
put 'features', :to => 'arturo/features#update_all', :as => 'features'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
else
|
9
|
+
Arturo::Engine.routes.draw do
|
10
|
+
resources :features, :controller => 'arturo/features'
|
11
|
+
put 'features', :to => 'arturo/features#update_all', :as => 'features'
|
12
|
+
end
|
9
13
|
end
|
10
|
-
|
11
|
-
# Arturo::Engine.routes.draw do
|
12
|
-
# resources :features, :controller => 'arturo/features'
|
13
|
-
# put 'features', :to => 'arturo/features#update_all', :as => 'features'
|
14
|
-
# end
|
data/lib/arturo.rb
CHANGED
@@ -6,7 +6,7 @@ module Arturo
|
|
6
6
|
require 'arturo/feature_caching'
|
7
7
|
require 'arturo/controller_filters'
|
8
8
|
require 'arturo/middleware'
|
9
|
-
require 'arturo/engine' if defined?(Rails) && Rails::VERSION::MAJOR
|
9
|
+
require 'arturo/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
10
10
|
|
11
11
|
class <<self
|
12
12
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'arturo/no_such_feature'
|
2
|
+
|
1
3
|
module Arturo
|
2
4
|
|
3
5
|
# To be extended by Arturo::Feature if you want to enable
|
@@ -31,16 +33,18 @@ module Arturo
|
|
31
33
|
|
32
34
|
# Wraps Arturo::Feature.to_feature with in-memory caching.
|
33
35
|
def to_feature_with_caching(feature_or_symbol)
|
34
|
-
if !
|
35
|
-
|
36
|
+
if !caches_features?
|
37
|
+
to_feature_without_caching(feature_or_symbol)
|
36
38
|
elsif (feature_or_symbol.kind_of?(Arturo::Feature))
|
37
|
-
feature_cache.write(feature_or_symbol.symbol, feature_or_symbol, :expires_in => cache_ttl)
|
39
|
+
feature_cache.write(feature_or_symbol.symbol.to_sym, feature_or_symbol, :expires_in => cache_ttl)
|
38
40
|
feature_or_symbol
|
39
41
|
elsif (cached_feature = feature_cache.read(feature_or_symbol.to_sym))
|
40
42
|
cached_feature
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
else
|
44
|
+
symbol = feature_or_symbol.to_sym
|
45
|
+
feature = to_feature_without_caching(symbol) || Arturo::NoSuchFeature.new(symbol)
|
46
|
+
feature_cache.write(symbol, feature, :expires_in => cache_ttl)
|
47
|
+
feature
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -51,8 +55,8 @@ module Arturo
|
|
51
55
|
def initialize
|
52
56
|
@data = {} # of the form {key => [value, expires_at or nil]}
|
53
57
|
end
|
58
|
+
|
54
59
|
def read(name, options = nil)
|
55
|
-
name = name.to_s
|
56
60
|
value, expires_at = *@data[name]
|
57
61
|
if value && (expires_at.blank? || expires_at > Time.now)
|
58
62
|
value
|
@@ -60,8 +64,8 @@ module Arturo
|
|
60
64
|
nil
|
61
65
|
end
|
62
66
|
end
|
67
|
+
|
63
68
|
def write(name, value, options = nil)
|
64
|
-
name = name.to_s
|
65
69
|
expires_at = if options && options.respond_to?(:[]) && options[:expires_in]
|
66
70
|
Time.now + options.delete(:expires_in)
|
67
71
|
else
|
@@ -71,6 +75,7 @@ module Arturo
|
|
71
75
|
@data[name] = [value, expires_at]
|
72
76
|
end
|
73
77
|
end
|
78
|
+
|
74
79
|
def clear
|
75
80
|
@data.clear
|
76
81
|
end
|
@@ -78,4 +83,4 @@ module Arturo
|
|
78
83
|
|
79
84
|
end
|
80
85
|
|
81
|
-
end
|
86
|
+
end
|
@@ -1,4 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
FactoryGirl.define do
|
2
|
+
sequence(:feature_symbol) { |n| "feature_#{n}".to_sym }
|
3
|
+
|
4
|
+
factory :feature, :class => Arturo::Feature do
|
5
|
+
symbol { generate(:feature_symbol) }
|
6
|
+
deployment_percentage { rand(101) }
|
7
|
+
end
|
4
8
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Arturo
|
2
|
+
|
3
|
+
# Mix in to FeaturesController. Provides the logic for getting parameters
|
4
|
+
# for creating/updated features out of the request.
|
5
|
+
module FeatureParamsSupport
|
6
|
+
|
7
|
+
module WithoutStrongParams
|
8
|
+
def feature_params
|
9
|
+
params[:feature] || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def features_params
|
13
|
+
params[:features] || {}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module WithStrongParams
|
18
|
+
PERMITTED_ATTRIBUTES = [ :symbol, :deployment_percentage ]
|
19
|
+
|
20
|
+
def feature_params
|
21
|
+
params.permit(:feature => PERMITTED_ATTRIBUTES)[:feature]
|
22
|
+
end
|
23
|
+
|
24
|
+
def features_params
|
25
|
+
permitted = PERMITTED_ATTRIBUTES
|
26
|
+
features = params[:features]
|
27
|
+
features.each do |id, attributes|
|
28
|
+
features[id] = ActionController::Parameters.new(attributes).permit(*permitted)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
include defined?(ActionController::Parameters) ? WithStrongParams : WithoutStrongParams
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Arturo
|
2
|
+
|
3
|
+
# A Null-Object stand-in for a Feature.
|
4
|
+
class NoSuchFeature
|
5
|
+
|
6
|
+
attr_reader :symbol
|
7
|
+
|
8
|
+
def initialize(symbol)
|
9
|
+
raise ArgumentError.new(I18n.t('arturo.no_such_feature.symbol_required')) if symbol.nil?
|
10
|
+
@symbol = symbol
|
11
|
+
end
|
12
|
+
|
13
|
+
def enabled_for?(feature_recipient)
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
I18n.t('arturo.no_such_feature.name', :symbol => symbol)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :to_s, :name
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"<Arturo::NoSuchFeature #{symbol}>"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
CHANGED
@@ -1,140 +1,165 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: arturo
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.5.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 4
|
9
|
-
- 0
|
10
|
-
version: 1.4.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- James A. Rosen
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-04-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: rails
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
version: "3.0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>'
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
- - <
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '5.0'
|
33
25
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: mocha
|
37
26
|
prerelease: false
|
38
|
-
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
version:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>'
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
- - <
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '5.0'
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: mocha
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
47
44
|
type: :development
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: rake
|
51
45
|
prerelease: false
|
52
|
-
|
53
|
-
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rake
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
61
60
|
type: :development
|
62
|
-
version_requirements: *id003
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: redgreen
|
65
61
|
prerelease: false
|
66
|
-
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
63
|
none: false
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: minitest-rg
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
|
-
version_requirements: *id004
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: sqlite3
|
80
77
|
prerelease: false
|
81
|
-
|
82
|
-
none: false
|
83
|
-
requirements:
|
84
|
-
- -
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: sqlite3
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
90
92
|
type: :development
|
91
|
-
version_requirements: *id005
|
92
|
-
- !ruby/object:Gem::Dependency
|
93
|
-
name: factory_girl
|
94
93
|
prerelease: false
|
95
|
-
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: factory_girl
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
96
103
|
none: false
|
97
|
-
requirements:
|
104
|
+
requirements:
|
98
105
|
- - ~>
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
|
101
|
-
segments:
|
102
|
-
- 1
|
103
|
-
- 3
|
104
|
-
version: "1.3"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '4.2'
|
105
108
|
type: :development
|
106
|
-
|
107
|
-
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ~>
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '4.2'
|
116
|
+
- !ruby/object:Gem::Dependency
|
108
117
|
name: timecop
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0.3'
|
124
|
+
type: :development
|
109
125
|
prerelease: false
|
110
|
-
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.3'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: appraisal
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
111
135
|
none: false
|
112
|
-
requirements:
|
136
|
+
requirements:
|
113
137
|
- - ~>
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
|
116
|
-
segments:
|
117
|
-
- 0
|
118
|
-
- 3
|
119
|
-
version: "0.3"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.5'
|
120
140
|
type: :development
|
121
|
-
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ~>
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0.5'
|
122
148
|
description: Deploy features incrementally to your users
|
123
149
|
email: james.a.rosen@gmail.com
|
124
150
|
executables: []
|
125
|
-
|
126
151
|
extensions: []
|
127
|
-
|
128
152
|
extra_rdoc_files: []
|
129
|
-
|
130
|
-
files:
|
153
|
+
files:
|
131
154
|
- lib/arturo/controller_filters.rb
|
132
155
|
- lib/arturo/engine.rb
|
133
156
|
- lib/arturo/feature_availability.rb
|
134
157
|
- lib/arturo/feature_caching.rb
|
135
158
|
- lib/arturo/feature_factories.rb
|
136
159
|
- lib/arturo/feature_management.rb
|
160
|
+
- lib/arturo/feature_params_support.rb
|
137
161
|
- lib/arturo/middleware.rb
|
162
|
+
- lib/arturo/no_such_feature.rb
|
138
163
|
- lib/arturo/special_handling.rb
|
139
164
|
- lib/arturo/test_support.rb
|
140
165
|
- lib/arturo.rb
|
@@ -163,38 +188,30 @@ files:
|
|
163
188
|
- README.md
|
164
189
|
- HISTORY.md
|
165
190
|
homepage: http://github.com/jamesarosen/arturo
|
166
|
-
licenses:
|
167
|
-
|
191
|
+
licenses:
|
192
|
+
- APLv2
|
168
193
|
post_install_message:
|
169
194
|
rdoc_options: []
|
170
|
-
|
171
|
-
require_paths:
|
195
|
+
require_paths:
|
172
196
|
- .
|
173
197
|
- lib
|
174
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
198
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
175
199
|
none: false
|
176
|
-
requirements:
|
177
|
-
- -
|
178
|
-
- !ruby/object:Gem::Version
|
179
|
-
|
180
|
-
|
181
|
-
- 0
|
182
|
-
version: "0"
|
183
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ! '>='
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
205
|
none: false
|
185
|
-
requirements:
|
186
|
-
- -
|
187
|
-
- !ruby/object:Gem::Version
|
188
|
-
|
189
|
-
segments:
|
190
|
-
- 0
|
191
|
-
version: "0"
|
206
|
+
requirements:
|
207
|
+
- - ! '>='
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0'
|
192
210
|
requirements: []
|
193
|
-
|
194
211
|
rubyforge_project:
|
195
|
-
rubygems_version: 1.8.
|
212
|
+
rubygems_version: 1.8.25
|
196
213
|
signing_key:
|
197
214
|
specification_version: 2
|
198
215
|
summary: Feature sliders, wrapped up in an engine
|
199
216
|
test_files: []
|
200
|
-
|
217
|
+
has_rdoc: 'false'
|