enphase-arturo 1.3.2
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/HISTORY.md +16 -0
- data/README.md +295 -0
- data/app/controllers/arturo/features_controller.rb +105 -0
- data/app/helpers/arturo/features_helper.rb +37 -0
- data/app/models/arturo/feature.rb +75 -0
- data/app/views/arturo/features/_feature.html.erb +5 -0
- data/app/views/arturo/features/_form.html.erb +16 -0
- data/app/views/arturo/features/edit.html.erb +2 -0
- data/app/views/arturo/features/forbidden.html.erb +2 -0
- data/app/views/arturo/features/index.html.erb +29 -0
- data/app/views/arturo/features/new.html.erb +2 -0
- data/app/views/arturo/features/show.html.erb +2 -0
- data/config/locales/en.yml +40 -0
- data/config/routes.rb +14 -0
- data/lib/arturo.rb +37 -0
- data/lib/arturo/controller_filters.rb +33 -0
- data/lib/arturo/engine.rb +10 -0
- data/lib/arturo/feature_availability.rb +37 -0
- data/lib/arturo/feature_caching.rb +83 -0
- data/lib/arturo/feature_factories.rb +4 -0
- data/lib/arturo/feature_management.rb +23 -0
- data/lib/arturo/middleware.rb +60 -0
- data/lib/arturo/special_handling.rb +62 -0
- data/lib/arturo/test_support.rb +30 -0
- data/lib/generators/arturo/assets_generator.rb +18 -0
- data/lib/generators/arturo/initializer_generator.rb +13 -0
- data/lib/generators/arturo/migration_generator.rb +27 -0
- data/lib/generators/arturo/routes_generator.rb +15 -0
- data/lib/generators/arturo/templates/arturo.css +67 -0
- data/lib/generators/arturo/templates/arturo.js +23 -0
- data/lib/generators/arturo/templates/arturo_customizations.css +1 -0
- data/lib/generators/arturo/templates/initializer.rb +29 -0
- data/lib/generators/arturo/templates/migration.rb +17 -0
- data/lib/generators/arturo/templates/semicolon.png +0 -0
- metadata +156 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Arturo
|
|
2
|
+
# A Rack middleware that requires a feature to be present. By default,
|
|
3
|
+
# checks feature availability against an `arturo.recipient` object
|
|
4
|
+
# in the `env`. If that object is missing, this middleware always fails,
|
|
5
|
+
# even if the feature is available for everyone.
|
|
6
|
+
#
|
|
7
|
+
# ## Usage
|
|
8
|
+
#
|
|
9
|
+
# use Arturo::Middleware, :feature => :foo
|
|
10
|
+
#
|
|
11
|
+
# ## Options
|
|
12
|
+
#
|
|
13
|
+
# * feature -- the name of the feature to require, as a Symbol; required
|
|
14
|
+
#
|
|
15
|
+
# * recipient -- the key in the `env` hash under which the feature
|
|
16
|
+
# recipient can be found; defaults to "arturo.recipient".
|
|
17
|
+
# * on_unavailable -- a Rack-like object
|
|
18
|
+
# (has `#call(Hash) -> [status, headers, body]`) that
|
|
19
|
+
# is called when the feature is unavailable; defaults
|
|
20
|
+
# to returning `[ 404, {}, ['Not Found'] ]`.
|
|
21
|
+
class Middleware
|
|
22
|
+
|
|
23
|
+
MISSING_FEATURE_ERROR = "Cannot create an Arturo::Middleware without a :feature"
|
|
24
|
+
|
|
25
|
+
DEFAULT_RECIPIENT_KEY = 'arturo.recipient'
|
|
26
|
+
|
|
27
|
+
DEFAULT_ON_UNAVAILABLE = lambda { |env| [ 404, {}, ['Not Found'] ] }
|
|
28
|
+
|
|
29
|
+
def initialize(app, options = {})
|
|
30
|
+
@app = app
|
|
31
|
+
@feature = options[:feature]
|
|
32
|
+
raise ArgumentError.new(MISSING_FEATURE_ERROR) unless @feature
|
|
33
|
+
@recipient_key = options[:recipient] || DEFAULT_RECIPIENT_KEY
|
|
34
|
+
@on_unavailable = options[:on_unavailable] || DEFAULT_ON_UNAVAILABLE
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def call(env)
|
|
38
|
+
if enabled_for_recipient?(env)
|
|
39
|
+
@app.call(env)
|
|
40
|
+
else
|
|
41
|
+
fail(env)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def enabled_for_recipient?(env)
|
|
48
|
+
::Arturo.feature_enabled_for?(@feature, recipient(env))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def recipient(env)
|
|
52
|
+
env[@recipient_key]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def fail(env)
|
|
56
|
+
@on_unavailable.call(env)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Arturo
|
|
2
|
+
|
|
3
|
+
# Adds whitelist and blacklist support to individual features by name.
|
|
4
|
+
# Blacklists override whitelists. (In the world of Apache, Features
|
|
5
|
+
# are "(deny,allow)".)
|
|
6
|
+
# @example
|
|
7
|
+
# # allow admins:
|
|
8
|
+
# Arturo::Feature.whitelist(:some_feature) do |user|
|
|
9
|
+
# user.is_admin?
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# # disallow for small accounts:
|
|
13
|
+
# Arturo::Feature.blacklist(:another_feature) do |user|
|
|
14
|
+
# user.account.small?
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# Blacklists and whitelists can be defined before the feature exists
|
|
18
|
+
# and are not persisted, so they are best defined in initializers.
|
|
19
|
+
# This is particularly important if your application runs in several
|
|
20
|
+
# different processes or on several servers.
|
|
21
|
+
module SpecialHandling
|
|
22
|
+
|
|
23
|
+
def self.included(base)
|
|
24
|
+
base.extend Arturo::SpecialHandling::ClassMethods
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def whitelists
|
|
29
|
+
@whitelists ||= {}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def blacklists
|
|
33
|
+
@blacklists ||= {}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def whitelist(feature_symbol, &block)
|
|
37
|
+
whitelists[feature_symbol.to_sym] = block
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def blacklist(feature_symbol, &block)
|
|
41
|
+
blacklists[feature_symbol.to_sym] = block
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def whitelisted?(feature_recipient)
|
|
48
|
+
x_listed?(self.class.whitelists, feature_recipient)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def blacklisted?(feature_recipient)
|
|
52
|
+
x_listed?(self.class.blacklists, feature_recipient)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def x_listed?(list_map, feature_recipient)
|
|
56
|
+
list = list_map[self.symbol.to_sym]
|
|
57
|
+
list.present? && list.call(feature_recipient)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Arturo.instance_eval do
|
|
2
|
+
|
|
3
|
+
# Enable a feature; create it if necessary.
|
|
4
|
+
# For use in testing. Not auto-required on load. To load,
|
|
5
|
+
#
|
|
6
|
+
# require 'arturo/test_support'
|
|
7
|
+
#
|
|
8
|
+
# @param [Symbol, String] name the feature name
|
|
9
|
+
def enable_feature!(name)
|
|
10
|
+
feature = Arturo::Feature.to_feature(name)
|
|
11
|
+
if feature
|
|
12
|
+
feature.update_attributes(:deployment_percentage => 100)
|
|
13
|
+
else
|
|
14
|
+
Arturo::Feature.create!(:symbol => name, :deployment_percentage => 100)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Disable a feature if it exists.
|
|
19
|
+
# For use in testing. Not auto-required on load. To load,
|
|
20
|
+
#
|
|
21
|
+
# require 'arturo/test_support'
|
|
22
|
+
#
|
|
23
|
+
# @param [Symbol, String] name the feature name
|
|
24
|
+
def disable_feature!(name)
|
|
25
|
+
if (feature = Arturo::Feature.to_feature(name))
|
|
26
|
+
feature.update_attributes(:deployment_percentage => 0)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module Arturo
|
|
4
|
+
class AssetsGenerator < Rails::Generators::Base
|
|
5
|
+
def self.source_root
|
|
6
|
+
File.join(File.dirname(__FILE__), 'templates')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def copy_assets
|
|
10
|
+
copy_file 'arturo.css', 'public/stylesheets/arturo.css', :force => true
|
|
11
|
+
copy_file 'arturo_customizations.css', 'public/stylesheets/arturo_customizations.css', :skip => true
|
|
12
|
+
copy_file 'arturo.js', 'public/javascripts/arturo.js'
|
|
13
|
+
copy_file 'semicolon.png', 'public/images/semicolon.png'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module Arturo
|
|
4
|
+
class InitializerGenerator < Rails::Generators::Base
|
|
5
|
+
def self.source_root
|
|
6
|
+
File.join(File.dirname(__FILE__), 'templates')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def copy_initializer_file
|
|
10
|
+
copy_file "initializer.rb", "config/initializers/arturo_initializer.rb"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
require 'rails/generators/migration'
|
|
3
|
+
|
|
4
|
+
module Arturo
|
|
5
|
+
class MigrationGenerator < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
def self.source_root
|
|
9
|
+
File.join(File.dirname(__FILE__), 'templates')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Implement the required interface for Rails::Generators::Migration.
|
|
13
|
+
# taken from
|
|
14
|
+
# http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
|
15
|
+
def self.next_migration_number(dirname) #:nodoc:
|
|
16
|
+
if ActiveRecord::Base.timestamped_migrations
|
|
17
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
18
|
+
else
|
|
19
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create_migration_file
|
|
24
|
+
migration_template 'migration.rb', 'db/migrate/create_features.rb'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module Arturo
|
|
4
|
+
class RoutesGenerator < Rails::Generators::Base
|
|
5
|
+
|
|
6
|
+
def add_mount
|
|
7
|
+
if Arturo::Engine.respond_to?(:routes)
|
|
8
|
+
route "mount Arturo::Engine => ''"
|
|
9
|
+
else
|
|
10
|
+
puts "This version of Rails doesn't support Engine-specific routing. Nothing to do."
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
WARNING:
|
|
3
|
+
|
|
4
|
+
Do not edit this file. Any changes you make to this file will be overwritten
|
|
5
|
+
when you regenerate the arturo assets (which happens when you upgrade the gem).
|
|
6
|
+
Instead, make customizations to arturo_customizations.css.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
.features code.symbol:before { content: ":"; }
|
|
10
|
+
|
|
11
|
+
.features { border-collapse: collapse; }
|
|
12
|
+
|
|
13
|
+
.features thead tr:last-child th { border-bottom: 1px solid; }
|
|
14
|
+
.features tfoot tr:first-child th { border-top: 1px solid; }
|
|
15
|
+
|
|
16
|
+
.features th, .features td {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0.5em 1.5em;
|
|
19
|
+
text-align: left;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
input.deployment_percentage[type=range] { width: 200px; }
|
|
23
|
+
|
|
24
|
+
output.deployment_percentage.no_js { display: none; }
|
|
25
|
+
output.deployment_percentage { margin-left: 1em; }
|
|
26
|
+
output.deployment_percentage:after { content: "%"; }
|
|
27
|
+
|
|
28
|
+
.features a[rel=edit] { visibility: hidden; }
|
|
29
|
+
.features tr:hover a[rel=edit] { visibility: inherit; }
|
|
30
|
+
|
|
31
|
+
.features tfoot th {
|
|
32
|
+
text-align: right;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.features tfoot th * + * {
|
|
36
|
+
margin-left: 2em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.feature_new label, .feature_edit label { font-weight: bold; }
|
|
40
|
+
|
|
41
|
+
.feature_new label, .feature_new .errors,
|
|
42
|
+
.feature_edit label, .feature_edit .errors {
|
|
43
|
+
display: block;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.feature_new label + input, .feature_new label + textarea, .feature_new label + select,
|
|
47
|
+
.feature_edit label + input, .feature_edit label + textarea, .feature_edit label + select {
|
|
48
|
+
margin-top: 0.5em;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.feature_new input + label, .feature_new textarea + label, .feature_new select + label,
|
|
52
|
+
.feature_edit input + label, .feature_edit textarea + label, .feature_edit select + label {
|
|
53
|
+
margin-top: 1.5em;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.feature_new input[type=text], .feature_edit input[type=text] { padding: 0.5em; }
|
|
57
|
+
|
|
58
|
+
.feature_new input.symbol, .feature_edit input.symbol {
|
|
59
|
+
background: transparent url('/images/semicolon.png') no-repeat 3px 4px;
|
|
60
|
+
font-family: "DejaVu Sans Mono", "Droid Sans Mono", "Mondale", monospace;
|
|
61
|
+
padding-left: 9px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.feature_new .errors, .feature_edit .errors { color: red; }
|
|
65
|
+
.feature_new :invalid { border-color: red; }
|
|
66
|
+
|
|
67
|
+
.feature_new footer, .feature_edit footer { margin-top: 2em; }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
if (typeof(jQuery) === 'function') {
|
|
2
|
+
jQuery.arturo = {
|
|
3
|
+
agentSupportsHTML5Output: ('for' in jQuery('<output />')),
|
|
4
|
+
|
|
5
|
+
linkAndShowOutputs: function() {
|
|
6
|
+
if (jQuery.arturo.agentSupportsHTML5Output) {
|
|
7
|
+
jQuery('.features output,.feature_new output,.feature_edit output').each(function(i, output) {
|
|
8
|
+
var output = jQuery(output);
|
|
9
|
+
var input = jQuery('#' + output.attr('for'));
|
|
10
|
+
input.change(function() {
|
|
11
|
+
console.log('input value changed to ' + input.val());
|
|
12
|
+
output.val(input.val());
|
|
13
|
+
});
|
|
14
|
+
output.removeClass('no_js');
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
jQuery(function() {
|
|
21
|
+
jQuery.arturo.linkAndShowOutputs();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* Make any customizations to the Arturo styles here */
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'arturo'
|
|
2
|
+
|
|
3
|
+
# Configure who may manage features here.
|
|
4
|
+
# The following is the default implementation.
|
|
5
|
+
# Arturo::FeatureManagement.class_eval do
|
|
6
|
+
# def may_manage_features?
|
|
7
|
+
# current_user.present? && current_user.admin?
|
|
8
|
+
# end
|
|
9
|
+
# end
|
|
10
|
+
|
|
11
|
+
# Configure what receives features here.
|
|
12
|
+
# The following is the default implementation.
|
|
13
|
+
# Arturo::FeatureAvailability.class_eval do
|
|
14
|
+
# def feature_recipient
|
|
15
|
+
# current_user
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
|
|
19
|
+
# Whitelists and Blacklists:
|
|
20
|
+
#
|
|
21
|
+
# Enable feature one for all admins:
|
|
22
|
+
# Arturo::Feature.whitelist(:feature_one) do |user|
|
|
23
|
+
# user.admin?
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Disable feature two for all small accounts:
|
|
27
|
+
# Arturo::Feature.blacklist(:feature_two) do |user|
|
|
28
|
+
# user.account.small?
|
|
29
|
+
# end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'active_support/core_ext'
|
|
2
|
+
|
|
3
|
+
class CreateFeatures < ActiveRecord::Migration
|
|
4
|
+
def self.up
|
|
5
|
+
create_table :features do |t|
|
|
6
|
+
t.string :symbol, :null => false
|
|
7
|
+
t.integer :deployment_percentage, :null => false
|
|
8
|
+
#Any additional fields here
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.down
|
|
15
|
+
drop_table :features
|
|
16
|
+
end
|
|
17
|
+
end
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: enphase-arturo
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.3.2
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- James A. Rosen
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-01-26 00:00:00.000000000Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: rails
|
|
16
|
+
requirement: &2177639760 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ~>
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '3.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *2177639760
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: mocha
|
|
27
|
+
requirement: &2177639360 !ruby/object:Gem::Requirement
|
|
28
|
+
none: false
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: *2177639360
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: rake
|
|
38
|
+
requirement: &2177638900 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
type: :development
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *2177638900
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: redgreen
|
|
49
|
+
requirement: &2177638400 !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.2'
|
|
55
|
+
type: :development
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: *2177638400
|
|
58
|
+
- !ruby/object:Gem::Dependency
|
|
59
|
+
name: sqlite3-ruby
|
|
60
|
+
requirement: &2177637900 !ruby/object:Gem::Requirement
|
|
61
|
+
none: false
|
|
62
|
+
requirements:
|
|
63
|
+
- - ~>
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '1.3'
|
|
66
|
+
type: :development
|
|
67
|
+
prerelease: false
|
|
68
|
+
version_requirements: *2177637900
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: factory_girl
|
|
71
|
+
requirement: &2177637440 !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ~>
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '1.3'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: *2177637440
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: timecop
|
|
82
|
+
requirement: &2177636980 !ruby/object:Gem::Requirement
|
|
83
|
+
none: false
|
|
84
|
+
requirements:
|
|
85
|
+
- - ~>
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '0.3'
|
|
88
|
+
type: :development
|
|
89
|
+
prerelease: false
|
|
90
|
+
version_requirements: *2177636980
|
|
91
|
+
description: Enphase specific fork. Deploy features incrementally to your users
|
|
92
|
+
email: james.a.rosen@gmail.com
|
|
93
|
+
executables: []
|
|
94
|
+
extensions: []
|
|
95
|
+
extra_rdoc_files: []
|
|
96
|
+
files:
|
|
97
|
+
- lib/arturo/controller_filters.rb
|
|
98
|
+
- lib/arturo/engine.rb
|
|
99
|
+
- lib/arturo/feature_availability.rb
|
|
100
|
+
- lib/arturo/feature_caching.rb
|
|
101
|
+
- lib/arturo/feature_factories.rb
|
|
102
|
+
- lib/arturo/feature_management.rb
|
|
103
|
+
- lib/arturo/middleware.rb
|
|
104
|
+
- lib/arturo/special_handling.rb
|
|
105
|
+
- lib/arturo/test_support.rb
|
|
106
|
+
- lib/arturo.rb
|
|
107
|
+
- lib/generators/arturo/assets_generator.rb
|
|
108
|
+
- lib/generators/arturo/initializer_generator.rb
|
|
109
|
+
- lib/generators/arturo/migration_generator.rb
|
|
110
|
+
- lib/generators/arturo/routes_generator.rb
|
|
111
|
+
- lib/generators/arturo/templates/arturo.css
|
|
112
|
+
- lib/generators/arturo/templates/arturo.js
|
|
113
|
+
- lib/generators/arturo/templates/arturo_customizations.css
|
|
114
|
+
- lib/generators/arturo/templates/initializer.rb
|
|
115
|
+
- lib/generators/arturo/templates/migration.rb
|
|
116
|
+
- lib/generators/arturo/templates/semicolon.png
|
|
117
|
+
- app/controllers/arturo/features_controller.rb
|
|
118
|
+
- app/helpers/arturo/features_helper.rb
|
|
119
|
+
- app/models/arturo/feature.rb
|
|
120
|
+
- app/views/arturo/features/_feature.html.erb
|
|
121
|
+
- app/views/arturo/features/_form.html.erb
|
|
122
|
+
- app/views/arturo/features/edit.html.erb
|
|
123
|
+
- app/views/arturo/features/forbidden.html.erb
|
|
124
|
+
- app/views/arturo/features/index.html.erb
|
|
125
|
+
- app/views/arturo/features/new.html.erb
|
|
126
|
+
- app/views/arturo/features/show.html.erb
|
|
127
|
+
- config/locales/en.yml
|
|
128
|
+
- config/routes.rb
|
|
129
|
+
- README.md
|
|
130
|
+
- HISTORY.md
|
|
131
|
+
homepage: http://github.com/jamesarosen/arturo
|
|
132
|
+
licenses: []
|
|
133
|
+
post_install_message:
|
|
134
|
+
rdoc_options: []
|
|
135
|
+
require_paths:
|
|
136
|
+
- .
|
|
137
|
+
- lib
|
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
|
+
none: false
|
|
140
|
+
requirements:
|
|
141
|
+
- - ! '>='
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '0'
|
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
|
+
none: false
|
|
146
|
+
requirements:
|
|
147
|
+
- - ! '>='
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '0'
|
|
150
|
+
requirements: []
|
|
151
|
+
rubyforge_project:
|
|
152
|
+
rubygems_version: 1.8.11
|
|
153
|
+
signing_key:
|
|
154
|
+
specification_version: 2
|
|
155
|
+
summary: Enphase specific fork. Feature sliders, wrapped up in an engine
|
|
156
|
+
test_files: []
|