config_manager 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.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/config_manager/application.js +15 -0
  6. data/app/assets/stylesheets/config_manager/_reset.css.scss +74 -0
  7. data/app/assets/stylesheets/config_manager/application.css +5 -0
  8. data/app/assets/stylesheets/config_manager/generic.css.scss +19 -0
  9. data/app/controllers/config_manager/admins_controller.rb +59 -0
  10. data/app/controllers/config_manager/application_controller.rb +12 -0
  11. data/app/controllers/config_manager/sessions_controller.rb +5 -0
  12. data/app/controllers/config_manager/toggles_controller.rb +57 -0
  13. data/app/helpers/config_manager/application_helper.rb +11 -0
  14. data/app/helpers/config_manager/toggles_helper.rb +7 -0
  15. data/app/models/config_manager/admin.rb +18 -0
  16. data/app/views/config_manager/admins/_errors.html.slim +7 -0
  17. data/app/views/config_manager/admins/_form.html.slim +10 -0
  18. data/app/views/config_manager/admins/edit.html.slim +13 -0
  19. data/app/views/config_manager/admins/index.html.slim +28 -0
  20. data/app/views/config_manager/admins/new.html.slim +10 -0
  21. data/app/views/config_manager/sessions/new.html.slim +23 -0
  22. data/app/views/config_manager/toggles/_form.html.slim +12 -0
  23. data/app/views/config_manager/toggles/index.html.slim +45 -0
  24. data/app/views/layouts/config_manager/application.html.slim +54 -0
  25. data/config/initializers/devise.rb +258 -0
  26. data/config/locales/devise.en.yml +59 -0
  27. data/config/routes.rb +17 -0
  28. data/db/migrate/20140725161636_create_config_manager_admins.rb +41 -0
  29. data/lib/config_manager.rb +6 -0
  30. data/lib/config_manager/engine.rb +20 -0
  31. data/lib/config_manager/toggle.rb +66 -0
  32. data/lib/config_manager/toggles/boolean.rb +21 -0
  33. data/lib/config_manager/toggles/definition.rb +103 -0
  34. data/lib/config_manager/toggles/null.rb +18 -0
  35. data/lib/config_manager/toggles/set.rb +21 -0
  36. data/lib/config_manager/version.rb +3 -0
  37. data/lib/tasks/config_manager_tasks.rake +4 -0
  38. data/spec/dummy/README.rdoc +28 -0
  39. data/spec/dummy/Rakefile +6 -0
  40. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  41. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  42. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  43. data/spec/dummy/app/controllers/dummy_controller.rb +4 -0
  44. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  45. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/spec/dummy/bin/bundle +3 -0
  47. data/spec/dummy/bin/rails +4 -0
  48. data/spec/dummy/bin/rake +4 -0
  49. data/spec/dummy/config.ru +4 -0
  50. data/spec/dummy/config/application.rb +28 -0
  51. data/spec/dummy/config/bad_toggles.yml +8 -0
  52. data/spec/dummy/config/boot.rb +5 -0
  53. data/spec/dummy/config/config_manager_toggles.yml +7 -0
  54. data/spec/dummy/config/database.yml +21 -0
  55. data/spec/dummy/config/environment.rb +5 -0
  56. data/spec/dummy/config/environments/development.rb +37 -0
  57. data/spec/dummy/config/environments/production.rb +82 -0
  58. data/spec/dummy/config/environments/test.rb +39 -0
  59. data/spec/dummy/config/initializers/assets.rb +8 -0
  60. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  61. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  62. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  63. data/spec/dummy/config/initializers/inflections.rb +16 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  65. data/spec/dummy/config/initializers/redis.rb +12 -0
  66. data/spec/dummy/config/initializers/session_store.rb +3 -0
  67. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/spec/dummy/config/locales/en.yml +23 -0
  69. data/spec/dummy/config/redis.yml +8 -0
  70. data/spec/dummy/config/routes.rb +5 -0
  71. data/spec/dummy/config/secrets.yml +22 -0
  72. data/spec/dummy/config/toggles.yml +8 -0
  73. data/spec/dummy/db/development.sqlite3 +0 -0
  74. data/spec/dummy/db/schema.rb +31 -0
  75. data/spec/dummy/db/test.sqlite3 +0 -0
  76. data/spec/dummy/log/development.log +9283 -0
  77. data/spec/dummy/log/test.log +557 -0
  78. data/spec/dummy/public/404.html +67 -0
  79. data/spec/dummy/public/422.html +67 -0
  80. data/spec/dummy/public/500.html +66 -0
  81. data/spec/dummy/public/favicon.ico +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sass/786e38d79a0d3df53e8917152c8f9ebd061f1eac/_reset.css.scssc +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sass/786e38d79a0d3df53e8917152c8f9ebd061f1eac/generic.css.scssc +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/1d468d61d8002d0709400b7ab8112441 +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/259bf4d13dff689b9dbca70a598c3755 +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/4c700e6b525103954790256e74000237 +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/53db5a69412d8243c467b6af17d2f483 +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/550cbb5bc745772776097bec6b7ee6db +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/6159fbf8e1fca57907de03eef7ed9cdb +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/69d29900d66ffd35bf01cae75f4e0fe6 +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/6d3f4fe92dd890a8bbdaf3f21eae0615 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/b248de24a4d5454a0dcf2490dc088b8e +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/bfdd9543b7b28b65c9d760f854cc387c +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/c5471c9026b426e70abbb969df7ba671 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/c69bf92b5432ae5a1c2044ebc2923c71 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/dbbeb33ef5af4bd661989cf666fde840 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/e808c4872b8e90c978084811080405ee +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/ecd5a5f69d121045c4fc39b914215798 +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/f0bf3eb5da8250b91d2179600efef783 +0 -0
  105. data/spec/dummy/tmp/cache/assets/development/sprockets/f318cd7091c78a646f7e5bed19e774bf +0 -0
  106. data/spec/dummy/tmp/cache/assets/development/sprockets/f33a897212fccae3670eab346f4e193e +0 -0
  107. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  108. data/spec/dummy/tmp/pids/server.pid +1 -0
  109. data/spec/dummy/tmp/test.yml +7 -0
  110. data/spec/integration/navigation_test.rb +10 -0
  111. data/spec/lib/config_manager/toggle_spec.rb +110 -0
  112. data/spec/lib/config_manager/toggles/boolean_spec.rb +34 -0
  113. data/spec/lib/config_manager/toggles/definition_spec.rb +130 -0
  114. data/spec/lib/config_manager/toggles/set_spec.rb +34 -0
  115. data/spec/rails_helper.rb +48 -0
  116. data/spec/spec_helper.rb +78 -0
  117. data/spec/support/rspec_redis_helper.rb +28 -0
  118. data/spec/test_helper.rb +15 -0
  119. metadata +486 -0
data/config/routes.rb ADDED
@@ -0,0 +1,17 @@
1
+ ConfigManager::Engine.routes.draw do
2
+ devise_for :admins,
3
+ :only => [:sessions],
4
+ :class_name => "ConfigManager::Admin"
5
+
6
+ resources :admins, :except => [:show]
7
+ resources :toggles, :only => [:index, :create, :destroy] do
8
+ collection do
9
+ post :load_default
10
+ post :dump
11
+ end
12
+ end
13
+ resources :settings, :only => [:index, :create, :destroy]
14
+
15
+ # change root later
16
+ root :to => "admins#index"
17
+ end
@@ -0,0 +1,41 @@
1
+ class CreateConfigManagerAdmins < ActiveRecord::Migration
2
+ def change
3
+ create_table :config_manager_admins do |t|
4
+ t.string :email, :limit => 255, :null => false, :unique => true
5
+ t.string :encrypted_password, :null => false
6
+
7
+ ## Recoverable
8
+ # t.string :reset_password_token
9
+ # t.datetime :reset_password_sent_at
10
+
11
+ ## Rememberable
12
+ t.datetime :remember_created_at
13
+
14
+ ## Trackable - If we want much more session history than this we should break it out into another table
15
+ t.integer :sign_in_count, :default => 0, :null => false
16
+ t.datetime :last_sign_in_at
17
+ t.string :last_sign_in_ip
18
+ t.datetime :current_sign_in_at
19
+ t.string :current_sign_in_ip
20
+
21
+ ## Confirmable
22
+ # t.string :confirmation_token
23
+ # t.datetime :confirmed_at
24
+ # t.datetime :confirmation_sent_at
25
+ # t.string :unconfirmed_email # Only if using reconfirmable
26
+
27
+ ## Lockable
28
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
29
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
30
+ # t.datetime :locked_at
31
+
32
+ ## Audit
33
+ t.timestamps
34
+ end
35
+
36
+ add_index :config_manager_admins, :email, :unique => true, :name => "ux_config_manager_admins__email"
37
+ # add_index :config_manager_users, :reset_password_token, unique: true
38
+ # add_index :config_manager_users, :confirmation_token, unique: true
39
+ # add_index :config_manager_users, :unlock_token, unique: true
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ require 'devise'
2
+ require "config_manager/engine"
3
+ require "config_manager/toggle"
4
+
5
+ module ConfigManager
6
+ end
@@ -0,0 +1,20 @@
1
+ module ConfigManager
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ConfigManager
4
+
5
+ initializer :append_migrations do |app|
6
+ unless app.root.to_s.match(root.to_s) && false
7
+ config.paths["db/migrate"].expanded.each do |expanded_path|
8
+ app.config.paths["db/migrate"] << expanded_path
9
+ end
10
+ end
11
+ end
12
+
13
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
14
+
15
+ config.generators do |g|
16
+ g.test_framework :rspec
17
+ g.fixture_replacement :factory_girl, :dir => 'spec/factories'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,66 @@
1
+ module ConfigManager
2
+ module Toggle
3
+ def self.active?(test, challenge=nil)
4
+ toggle_def = Toggles::Definition.new(test)
5
+ return false unless toggle_def.type
6
+
7
+ type_klass = toggle_def.type_class
8
+ if challenge
9
+ type_klass.active? toggle_def, challenge
10
+ else
11
+ type_klass.active? toggle_def
12
+ end
13
+ end
14
+
15
+ def self.toggles
16
+ toggle_defs = []
17
+ $redis.keys("#{Toggles::Definition.prefix}*").each do |key|
18
+ toggle_defs << Toggles::Definition.new(key.gsub(Toggles::Definition.prefix, ''))
19
+ end
20
+ toggle_defs
21
+ end
22
+
23
+ def self.create(*args)
24
+ toggle_hash = args.first
25
+
26
+ toggle_def = Toggles::Definition.new(toggle_hash[:name])
27
+ toggle_def.type = toggle_hash[:type]
28
+ values = (toggle_hash[:type] == 'boolean') ?
29
+ toggle_hash[:formatted_acceptable_values] :
30
+ toggle_hash[:formatted_acceptable_values].gsub(/\s*,\s*/,',').split(',')
31
+ toggle_def.acceptable_values = values
32
+
33
+ toggle_def
34
+ end
35
+
36
+ def self.delete(name)
37
+ toggle = Toggles::Definition.new(name)
38
+ toggle.delete
39
+ end
40
+
41
+ def self.from_yaml(path)
42
+ toggles = YAML::load(File.open(path))
43
+ counts = [0, 0]
44
+ toggles.each do |name, values|
45
+ begin
46
+ create({:name => name,
47
+ :type => values['type'],
48
+ :formatted_acceptable_values => values['acceptable_values']})
49
+ counts[0] += 1
50
+ rescue RuntimeError
51
+ Rails.logger.error " Bad toggle definition. #{$!}"
52
+ counts[1] += 1
53
+ end
54
+ end
55
+
56
+ counts
57
+ end
58
+
59
+ def self.to_yaml(path)
60
+ File.open(path, 'w') do |file|
61
+ toggles_hash = Hash[toggles.map(&:to_hash).map{|t| [t.keys.first, t.values.first]}]
62
+ YAML.dump(toggles_hash, file)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,21 @@
1
+ module ConfigManager
2
+ module Toggles
3
+ class Boolean
4
+ def self.active?(toggle_def)
5
+ toggle_def.acceptable_values
6
+ end
7
+
8
+ def self.to_json(value)
9
+ if value.is_a?(String)
10
+ !!(value =~ /^(true|t|yes|y|1)$/i)
11
+ else
12
+ value
13
+ end
14
+ end
15
+
16
+ def self.from_json(value)
17
+ to_json(value)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,103 @@
1
+ module ConfigManager
2
+ module Toggles
3
+ class Definition
4
+
5
+ def initialize(test)
6
+ @key = key(test)
7
+ end
8
+
9
+ def name
10
+ @key.gsub(Definition.prefix, '')
11
+ end
12
+
13
+ def type
14
+ @type ||= $redis.hget(@key, 'type')
15
+ end
16
+
17
+ def type=(type)
18
+ return unless name.present?
19
+
20
+ unless Definition.types.include?(type)
21
+ raise("#{type} is an unsupported Toggle type. Acceptable values are #{Definition.types}")
22
+ end
23
+ $redis.hset(@key, 'type', type)
24
+ @type = $redis.hget(@key, 'type')
25
+ end
26
+
27
+ def type_class
28
+ return Null unless valid?
29
+ eval("ConfigManager::Toggles::#{type.camelize}")
30
+ end
31
+
32
+ def acceptable_values
33
+ @values ||= $redis.hget(@key, 'acceptable_values')
34
+ #self.send("to_#{type}", @values)
35
+ type_class.from_json(@values)
36
+ end
37
+
38
+ def acceptable_values=(values)
39
+ return unless valid?
40
+
41
+ $redis.hset(@key, 'acceptable_values', type_class.to_json(values))
42
+ #$redis.hset(@key, 'acceptable_values', self.send("to_#{type}", values))
43
+ @values = $redis.hget(@key, 'acceptable_values')
44
+ end
45
+
46
+ def delete
47
+ $redis.del(@key)
48
+ end
49
+
50
+ def self.types
51
+ %w(boolean set)
52
+ end
53
+
54
+ def self.prefix
55
+ "#{Rails.application.class.parent_name.underscore}_toggles-"
56
+ end
57
+
58
+ def valid?
59
+ !!(name.present? && type)
60
+ end
61
+
62
+ def message
63
+ return "missing name" unless name.present?
64
+ return "missing type" unless type.present?
65
+ nil
66
+ end
67
+
68
+ alias_method :formatted_acceptable_values=, :acceptable_values=
69
+ def formatted_acceptable_values
70
+ values = acceptable_values
71
+ values.respond_to?(:join) ? values.join(',') : values
72
+ end
73
+
74
+ def to_yaml
75
+ to_hash.to_yaml
76
+ end
77
+
78
+ def to_hash
79
+ {name => {'type' => type, 'acceptable_values' => formatted_acceptable_values}}
80
+ end
81
+ private
82
+ def key(test)
83
+ "#{Definition.prefix}#{test}"
84
+ end
85
+
86
+ def to_boolean(value)
87
+ if value.is_a?(String)
88
+ !!(value =~ /^(true|t|yes|y|1)$/i)
89
+ else
90
+ value
91
+ end
92
+ end
93
+
94
+ def to_set(values)
95
+ values || []
96
+ end
97
+
98
+ def to_(values)
99
+ nil
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,18 @@
1
+ module ConfigManager
2
+ module Toggles
3
+ class Null
4
+ def self.active?(toggle_def)
5
+ false
6
+ end
7
+
8
+ def self.to_json(value)
9
+ nil
10
+ end
11
+
12
+ def self.from_json(value)
13
+ nil
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,21 @@
1
+ module ConfigManager
2
+ module Toggles
3
+ class Set
4
+ def self.active?(toggle_def, challenge)
5
+ if toggle_def.acceptable_values.is_a?(Array)
6
+ return toggle_def.acceptable_values.include?(challenge)
7
+ else
8
+ return false
9
+ end
10
+ end
11
+
12
+ def self.to_json(values)
13
+ values.to_json
14
+ end
15
+
16
+ def self.from_json(json)
17
+ json ? JSON.parse(json) : []
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module ConfigManager
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :config_manager do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,4 @@
1
+ class DummyController < ApplicationController
2
+ def index
3
+ end
4
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')