detour 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -1
  3. data/.travis.yml +6 -2
  4. data/Gemfile +5 -0
  5. data/README.md +41 -132
  6. data/Rake.md +108 -0
  7. data/Rakefile +21 -1
  8. data/app/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  9. data/app/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  10. data/app/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  11. data/app/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  12. data/app/assets/images/detour/.gitkeep +0 -0
  13. data/app/assets/javascripts/detour/application.js +16 -0
  14. data/app/assets/javascripts/detour/bootstrap.js +2006 -0
  15. data/app/assets/javascripts/detour/delete_feature.js +13 -0
  16. data/app/assets/javascripts/detour/delete_flag.js +13 -0
  17. data/app/assets/javascripts/detour/modals.js +3 -0
  18. data/app/assets/javascripts/detour/tooltips.js +3 -0
  19. data/app/assets/stylesheets/detour/application.css +14 -0
  20. data/app/assets/stylesheets/detour/bootstrap.css +7112 -0
  21. data/app/assets/stylesheets/detour/main.css +49 -0
  22. data/app/controllers/detour/application_controller.rb +12 -0
  23. data/app/controllers/detour/features_controller.rb +19 -0
  24. data/app/controllers/detour/flaggable_flags_controller.rb +90 -0
  25. data/app/controllers/detour/flags_controller.rb +18 -0
  26. data/app/helpers/detour/application_helper.rb +32 -0
  27. data/app/helpers/detour/flaggable_flags_helper.rb +5 -0
  28. data/app/helpers/detour/flags_helper.rb +7 -0
  29. data/app/models/detour/concerns/countable_flag.rb +19 -0
  30. data/app/models/detour/concerns/flag_actions.rb +141 -0
  31. data/app/models/detour/concerns/matchers.rb +73 -0
  32. data/app/models/detour/feature.rb +81 -0
  33. data/{lib → app/models}/detour/flag.rb +8 -2
  34. data/app/models/detour/flag_in_flag.rb +12 -0
  35. data/app/models/detour/group_flag.rb +13 -0
  36. data/{lib → app/models}/detour/opt_out_flag.rb +4 -2
  37. data/app/models/detour/percentage_flag.rb +9 -0
  38. data/app/views/detour/application/index.html.erb +0 -0
  39. data/app/views/detour/features/_errors.html.erb +11 -0
  40. data/app/views/detour/features/_success.html.erb +1 -0
  41. data/app/views/detour/features/error.js.erb +5 -0
  42. data/app/views/detour/features/success.js.erb +1 -0
  43. data/app/views/detour/flaggable_flags/_errors.html.erb +11 -0
  44. data/app/views/detour/flaggable_flags/_flaggable_flag.html.erb +11 -0
  45. data/app/views/detour/flaggable_flags/error.js.erb +5 -0
  46. data/app/views/detour/flaggable_flags/index.html.erb +34 -0
  47. data/app/views/detour/flaggable_flags/success.js.erb +1 -0
  48. data/app/views/detour/flags/_feature_form.html.erb +38 -0
  49. data/app/views/detour/flags/index.html.erb +76 -0
  50. data/app/views/detour/shared/_nav.html.erb +28 -0
  51. data/app/views/detour/shared/_spacer_cells.html.erb +3 -0
  52. data/app/views/layouts/detour/application.html.erb +29 -0
  53. data/config/routes.rb +16 -0
  54. data/detour.gemspec +15 -14
  55. data/lib/detour/acts_as_flaggable.rb +42 -3
  56. data/lib/detour/configuration.rb +35 -0
  57. data/lib/detour/engine.rb +5 -0
  58. data/lib/detour/flag_form.rb +87 -0
  59. data/lib/detour/version.rb +1 -1
  60. data/lib/detour.rb +10 -14
  61. data/lib/generators/templates/migration.rb +2 -0
  62. data/lib/tasks/detour.rake +16 -16
  63. data/script/rails +8 -0
  64. data/spec/controllers/detour/application_controller_spec.rb +15 -0
  65. data/spec/controllers/detour/features_controller_spec.rb +51 -0
  66. data/spec/controllers/detour/flaggable_flags_controller_spec.rb +100 -0
  67. data/spec/controllers/detour/flags_controller_spec.rb +77 -0
  68. data/spec/dummy/README.rdoc +261 -0
  69. data/spec/dummy/Rakefile +7 -0
  70. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  71. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  72. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  73. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  74. data/spec/dummy/app/mailers/.gitkeep +0 -0
  75. data/spec/dummy/app/models/.gitkeep +0 -0
  76. data/spec/dummy/app/models/user.rb +5 -0
  77. data/spec/dummy/app/models/widget.rb +5 -0
  78. data/spec/dummy/app/views/application/index.html.erb +22 -0
  79. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  80. data/spec/dummy/config/application.rb +65 -0
  81. data/spec/dummy/config/boot.rb +10 -0
  82. data/spec/dummy/config/database.yml +19 -0
  83. data/spec/dummy/config/environment.rb +5 -0
  84. data/spec/dummy/config/environments/development.rb +37 -0
  85. data/spec/dummy/config/environments/production.rb +67 -0
  86. data/spec/dummy/config/environments/test.rb +37 -0
  87. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  88. data/spec/dummy/config/initializers/detour.rb +36 -0
  89. data/spec/dummy/config/initializers/inflections.rb +15 -0
  90. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  91. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  92. data/spec/dummy/config/initializers/session_store.rb +8 -0
  93. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  94. data/spec/dummy/config/locales/en.yml +5 -0
  95. data/spec/dummy/config/routes.rb +4 -0
  96. data/spec/dummy/config.ru +4 -0
  97. data/spec/dummy/db/migrate/20131218015844_create_users.rb +10 -0
  98. data/spec/dummy/db/migrate/20131218023124_create_widgets.rb +9 -0
  99. data/spec/dummy/db/migrate/20131218055352_add_user_id_to_widgets.rb +6 -0
  100. data/spec/dummy/db/migrate/20131221052201_setup_detour.rb +32 -0
  101. data/spec/dummy/db/schema.rb +59 -0
  102. data/spec/dummy/db/seeds.rb +10 -0
  103. data/spec/dummy/lib/assets/.gitkeep +0 -0
  104. data/spec/dummy/log/.gitkeep +0 -0
  105. data/spec/dummy/public/404.html +26 -0
  106. data/spec/dummy/public/422.html +26 -0
  107. data/spec/dummy/public/500.html +25 -0
  108. data/spec/dummy/public/favicon.ico +0 -0
  109. data/spec/dummy/script/rails +6 -0
  110. data/spec/factories/feature.rb +5 -0
  111. data/spec/factories/flag_in_flag.rb +6 -0
  112. data/spec/factories/group_flag.rb +7 -0
  113. data/spec/factories/opt_out_flag.rb +6 -0
  114. data/spec/factories/percentage_flag.rb +7 -0
  115. data/spec/factories/user.rb +6 -0
  116. data/spec/factories/widget.rb +5 -0
  117. data/spec/features/features_spec.rb +70 -0
  118. data/spec/features/flag_in_flags_spec.rb +118 -0
  119. data/spec/features/group_flags_spec.rb +49 -0
  120. data/spec/features/home_page_spec.rb +11 -0
  121. data/spec/features/opt_out_flags_spec.rb +105 -0
  122. data/spec/features/percentage_flags_spec.rb +63 -0
  123. data/spec/integration/group_rollout_spec.rb +1 -1
  124. data/spec/lib/detour/acts_as_flaggable_spec.rb +45 -0
  125. data/spec/lib/detour/configuration_spec.rb +23 -0
  126. data/spec/lib/detour/flag_form_spec.rb +84 -0
  127. data/spec/lib/{active_record/rollout → detour}/flaggable_spec.rb +19 -19
  128. data/spec/lib/tasks/{detour_rake_spec.rb → detour_spec.rb} +54 -54
  129. data/spec/{lib/active_record/rollout → models/detour}/feature_spec.rb +93 -67
  130. data/spec/models/detour/flag_in_flag_spec.rb +38 -0
  131. data/spec/{lib/active_record/rollout → models/detour}/flag_spec.rb +1 -1
  132. data/spec/models/detour/opt_out_flag_spec.rb +38 -0
  133. data/spec/{lib/active_record/rollout → models/detour}/percentage_flag_spec.rb +1 -1
  134. data/spec/spec_helper.rb +41 -21
  135. data/spec/support/shared_contexts/rake.rb +4 -14
  136. metadata +278 -95
  137. data/lib/detour/feature.rb +0 -312
  138. data/lib/detour/flaggable_flag.rb +0 -10
  139. data/lib/detour/group_flag.rb +0 -8
  140. data/lib/detour/percentage_flag.rb +0 -11
  141. data/spec/lib/active_record/rollout/acts_as_flaggable_spec.rb +0 -31
  142. data/spec/lib/active_record/rollout/flaggable_flag_spec.rb +0 -9
  143. data/spec/lib/active_record/rollout/opt_out_flag_spec.rb +0 -9
  144. data/spec/support/schema.rb +0 -13
  145. /data/lib/generators/{active_record_rollout_generator.rb → detour_generator.rb} +0 -0
  146. /data/lib/generators/templates/{active_record_rollout.rb → detour.rb} +0 -0
  147. /data/spec/{lib/active_record/rollout → models/detour}/group_flag_spec.rb +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa9eb669cbe85bcf6e060065aa53924ec688e7be
4
+ data.tar.gz: ede70af5253bf7438872a8f9059bf05159b68c31
5
+ SHA512:
6
+ metadata.gz: 79eaf748749d194e084fb6e42bd5bdca11dc86b5543051fb517c78cab35bd9338264187060453964320d7c0a736bac9277d6100d34be244dbc4843213bc234d5
7
+ data.tar.gz: d47913a017eb2cb3de39e58d41e0c62b409113ff2657e74717bbfc123059e60009f5b67bc7c8e45f6ab595f2e6901519bcac4fff440f68656865dc87143574ea
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  *.rbc
3
+ *.log
3
4
  .bundle
4
5
  .config
5
6
  .yardoc
@@ -12,7 +13,7 @@ lib/bundler/man
12
13
  pkg
13
14
  rdoc
14
15
  spec/reports
15
- spec/spec.sqlite3
16
+ *.sqlite3
16
17
  test/tmp
17
18
  test/version_tmp
18
19
  tmp
data/.travis.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.2
4
3
  - 1.9.3
5
4
  - 2.0.0
6
- script: bundle exec rspec
5
+ - 2.1.0
6
+ before_install: gem install bundler --version '>= 1.5.1'
7
+ script:
8
+ - RAILS_ENV=test bundle exec rake db:create
9
+ - RAILS_ENV=test bundle exec rake db:migrate
10
+ - bundle exec rspec
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in detour.gemspec
4
4
  gemspec
5
+
6
+ gem "jquery-rails"
7
+ gem "indefinite_article", ">= 0.2.0"
8
+
9
+ gem "fakefs", require: false
data/README.md CHANGED
@@ -16,24 +16,12 @@ Rollouts for `ActiveRecord` models. It is a spiritual fork of [ArRollout](https:
16
16
 
17
17
  - [Installation](#installation)
18
18
  - [Usage](#usage)
19
+ - [Configuration](#configuration)
19
20
  - [Marking a model as flaggable](#marking-a-model-as-flaggable)
20
21
  - [Determining if a record is flagged into a feature](#determining-if-a-record-is-flagged-into-a-feature)
21
- - [Feature operations](#feature-operations)
22
- - [Creating features](#creating-features)
23
- - [Destroying features](#destroying-features)
24
- - [Flagging a record into a feature](#flagging-a-record-into-a-feature)
25
- - [Removing a flag-in for a record for a feature](#removing-a-flag-in-for-a-record-for-a-feature)
26
- - [Opt a record out of a feature](#opt-a-record-out-of-a-feature)
27
- - [Un-opt out a record from a feature](#un-opt-out-a-record-from-a-feature)
28
- - [Flag a programmatic group into a feature](#flag-a-programmatic-group-into-a-feature)
29
- - [Remove a flag-in for a programmatic group for a feature](#remove-a-flag-in-for-a-programmatic-group-for-a-feature)
30
- - [Flag a percentage of records into a feature](#flag-a-percentage-of-records-into-a-feature)
31
- - [Remove a flag-in for a percentage of records for a feature](#remove-a-flag-in-for-a-percentage-of-records-for-a-feature)
32
- - [Defining a default class](#defining-a-default-class)
33
22
  - [Defining programmatic groups](#defining-programmatic-groups)
34
23
  - [Contributing](#contributing)
35
24
 
36
-
37
25
  ## Installation
38
26
 
39
27
  Add this line to your application's Gemfile:
@@ -44,9 +32,13 @@ And then execute:
44
32
 
45
33
  $ bundle
46
34
 
47
- Or install it yourself as:
35
+ In your rails app:
36
+
37
+ $ bundle exec rails generate detour
38
+
39
+ Run the Detour migrations:
48
40
 
49
- $ gem install detour
41
+ $ bundle exec rake db:migrate
50
42
 
51
43
  ## Usage
52
44
 
@@ -54,8 +46,42 @@ Or install it yourself as:
54
46
  should have features accessible to it based on individual flags, flags for a
55
47
  percentage of records, or flags for a programmable group of records.
56
48
 
49
+ ### Configuration
50
+
51
+ Edit `config/initializers/detour.rb`:
52
+
53
+ ```ruby
54
+ Detour.configure do |config|
55
+ # Detour needs to know at boot which models will
56
+ # have flags defined for them:
57
+ config.flaggable_types = %w[User Widget]
58
+
59
+ # Detour needs to know what directories to search
60
+ # through in order to find places where you're
61
+ # checking for flags in your code. Provide it an
62
+ # array of glob strings:
63
+ config.grep_dirs = %w[app/**/*.{rb,erb}]
64
+
65
+ # Provide a default class to manage rollouts for, if
66
+ # desired. This means you can omit the class name from
67
+ # rake tasks:
68
+ config.default_flaggable_class_name = "User"
69
+ end
70
+ ```
71
+
72
+ Mount the app in `config/routes.rb`:
73
+
74
+ ```ruby
75
+ Rails.application.routes.draw do
76
+ mount Detour::Engine => "/detour"
77
+ end
78
+ ```
79
+
57
80
  ### Marking a model as flaggable
58
81
 
82
+ In addition to listing classes that are flaggable in your initializer, add
83
+ `acts_as_flaggable` to the class definitions themselves:
84
+
59
85
  ```ruby
60
86
  class User < ActiveRecord::Base
61
87
  acts_as_flaggable
@@ -113,123 +139,6 @@ end; else
113
139
  end
114
140
  ```
115
141
 
116
- ### Feature operations
117
-
118
- Features and flags are intended to be controlled by a rake tasks. To create
119
- them programmatically, consult the documentation.
120
-
121
- #### Creating features
122
-
123
- ```sh
124
- $ bundle exec rake detour:create[new_ui]
125
- ```
126
-
127
- #### Destroying features
128
-
129
- ```sh
130
- $ bundle exec rake detour:destroy[new_ui]
131
- ```
132
-
133
- #### Flagging a record into a feature
134
-
135
- This task requires passing the feature name, the record's class, and the
136
- record's ID.
137
-
138
- ```sh
139
- $ bundle exec rake detour:activate[new_ui,User,2]
140
- ```
141
-
142
- #### Removing a flag-in for a record for a feature
143
-
144
- This task requires passing the feature name, the record's class, and the
145
- record's ID.
146
-
147
- ```sh
148
- $ bundle exec rake detour:deactivate[new_ui,User,2]
149
- ```
150
-
151
- #### Opt a record out of a feature
152
-
153
- This will ensure that `record.has_feature?(:feature)` will always be false for
154
- the given feature, regardless of other individual flag, percentage, or group
155
- rollouts that would otherwise target this record.
156
-
157
- This task requires passing the feature name, the record's class, and the
158
- record's ID.
159
-
160
- ```sh
161
- $ bundle exec rake detour:opt_out[new_ui,User,2]
162
- ```
163
-
164
- #### Un-opt out a record from a feature
165
-
166
- This task requires passing the feature name, the record's class, and the
167
- record's ID.
168
-
169
- ```sh
170
- $ bundle exec rake detour:un_opt_out[new_ui,User,2]
171
- ```
172
-
173
- #### Flag a programmatic group into a feature
174
-
175
- This task requires passing the feature name, the record class for the group,
176
- and the name of the group.
177
-
178
- ```sh
179
- $ bundle exec rake detour:activate_group[new_ui,User,admins]
180
- ```
181
-
182
- #### Remove a flag-in for a programmatic group for a feature
183
-
184
- This task requires passing the feature name, the record class for the group,
185
- and the name of the group.
186
-
187
- ```sh
188
- $ bundle exec rake detour:deactivate_group[new_ui,User,admins]
189
- ```
190
-
191
- #### Flag a percentage of records into a feature
192
-
193
- This relies on the following formula to determine if a record is flagged in to
194
- a feature based on percentage:
195
-
196
- ```ruby
197
- record.id % 10 < percentage / 10
198
- ```
199
-
200
- This task requires passing the feature name, the record class for the group,
201
- and the percentage of records to be flagged in.
202
-
203
- ```sh
204
- $ bundle exec rake detour:activate_percentage[new_ui,User,20]
205
- ```
206
-
207
- #### Remove a flag-in for a percentage of records for a feature
208
-
209
- This task requires passing the feature name, and the record class for the group.
210
-
211
- ```sh
212
- $ bundle exec rake detour:deactivate_percentage[new_ui,User]
213
- ```
214
-
215
- ### Defining a default class
216
-
217
- In order to provide passing a class name into rake tasks, a default class can
218
- be set:
219
-
220
- ```ruby
221
- Detour.configure do |config|
222
- config.default_flaggable_class_name = "User"
223
- end
224
- ```
225
-
226
- Then, in your rake tasks:
227
-
228
- ```sh
229
- # Will activate feature "foo" for all instances of User that match the admins group.
230
- $ bundle exec rake detour:activate_group[foo,admins]
231
- ```
232
-
233
142
  ### Defining programmatic groups
234
143
 
235
144
  A specific group of records matching a given block can be flagged into a
data/Rake.md ADDED
@@ -0,0 +1,108 @@
1
+ # Detour Rake Tasks
2
+
3
+ ## Contents
4
+
5
+ - [Creating features](#creating-features)
6
+ - [Destroying features](#destroying-features)
7
+ - [Flagging a record into a feature](#flagging-a-record-into-a-feature)
8
+ - [Removing a flag-in for a record for a feature](#removing-a-flag-in-for-a-record-for-a-feature)
9
+ - [Opt a record out of a feature](#opt-a-record-out-of-a-feature)
10
+ - [Un-opt out a record from a feature](#un-opt-out-a-record-from-a-feature)
11
+ - [Flag a programmatic group into a feature](#flag-a-programmatic-group-into-a-feature)
12
+ - [Remove a flag-in for a programmatic group for a feature](#remove-a-flag-in-for-a-programmatic-group-for-a-feature)
13
+ - [Flag a percentage of records into a feature](#flag-a-percentage-of-records-into-a-feature)
14
+ - [Remove a flag-in for a percentage of records for a feature](#remove-a-flag-in-for-a-percentage-of-records-for-a-feature)
15
+
16
+ ## Creating features
17
+
18
+ ```sh
19
+ $ bundle exec rake detour:create[new_ui]
20
+ ```
21
+
22
+ ## Destroying features
23
+
24
+ ```sh
25
+ $ bundle exec rake detour:destroy[new_ui]
26
+ ```
27
+
28
+ ## Flagging a record into a feature
29
+
30
+ This task requires passing the feature name, the record's class, and the
31
+ record's ID.
32
+
33
+ ```sh
34
+ $ bundle exec rake detour:activate[new_ui,User,2]
35
+ ```
36
+
37
+ ## Removing a flag-in for a record for a feature
38
+
39
+ This task requires passing the feature name, the record's class, and the
40
+ record's ID.
41
+
42
+ ```sh
43
+ $ bundle exec rake detour:deactivate[new_ui,User,2]
44
+ ```
45
+
46
+ ## Opt a record out of a feature
47
+
48
+ This will ensure that `record.has_feature?(:feature)` will always be false for
49
+ the given feature, regardless of other individual flag, percentage, or group
50
+ rollouts that would otherwise target this record.
51
+
52
+ This task requires passing the feature name, the record's class, and the
53
+ record's ID.
54
+
55
+ ```sh
56
+ $ bundle exec rake detour:opt_out[new_ui,User,2]
57
+ ```
58
+
59
+ ## Un-opt out a record from a feature
60
+
61
+ This task requires passing the feature name, the record's class, and the
62
+ record's ID.
63
+
64
+ ```sh
65
+ $ bundle exec rake detour:un_opt_out[new_ui,User,2]
66
+ ```
67
+
68
+ ## Flag a programmatic group into a feature
69
+
70
+ This task requires passing the feature name, the record class for the group,
71
+ and the name of the group.
72
+
73
+ ```sh
74
+ $ bundle exec rake detour:activate_group[new_ui,User,admins]
75
+ ```
76
+
77
+ ## Remove a flag-in for a programmatic group for a feature
78
+
79
+ This task requires passing the feature name, the record class for the group,
80
+ and the name of the group.
81
+
82
+ ```sh
83
+ $ bundle exec rake detour:deactivate_group[new_ui,User,admins]
84
+ ```
85
+
86
+ ## Flag a percentage of records into a feature
87
+
88
+ This relies on the following formula to determine if a record is flagged in to
89
+ a feature based on percentage:
90
+
91
+ ```ruby
92
+ record.id % 10 < percentage / 10
93
+ ```
94
+
95
+ This task requires passing the feature name, the record class for the group,
96
+ and the percentage of records to be flagged in.
97
+
98
+ ```sh
99
+ $ bundle exec rake detour:activate_percentage[new_ui,User,20]
100
+ ```
101
+
102
+ ## Remove a flag-in for a percentage of records for a feature
103
+
104
+ This task requires passing the feature name, and the record class for the group.
105
+
106
+ ```sh
107
+ $ bundle exec rake detour:deactivate_percentage[new_ui,User]
108
+ ```
data/Rakefile CHANGED
@@ -1 +1,21 @@
1
- require "bundler/gem_tasks"
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require "bundler/setup"
4
+ rescue LoadError
5
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
6
+ end
7
+
8
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
9
+ load "rails/tasks/engine.rake"
10
+
11
+ Bundler::GemHelper.install_tasks
12
+
13
+ Dir[File.join(File.dirname(__FILE__), "tasks/**/*.rake")].each {|f| load f }
14
+
15
+ require "rspec/core"
16
+ require "rspec/core/rake_task"
17
+
18
+ desc "Run all specs in spec directory (excluding plugin specs)"
19
+ RSpec::Core::RakeTask.new(:spec => "app:db:test:prepare")
20
+
21
+ task :default => :spec