detour 0.0.1 → 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +6 -2
- data/Gemfile +5 -0
- data/README.md +41 -132
- data/Rake.md +108 -0
- data/Rakefile +21 -1
- data/app/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/app/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/app/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/app/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/app/assets/images/detour/.gitkeep +0 -0
- data/app/assets/javascripts/detour/application.js +16 -0
- data/app/assets/javascripts/detour/bootstrap.js +2006 -0
- data/app/assets/javascripts/detour/delete_feature.js +13 -0
- data/app/assets/javascripts/detour/delete_flag.js +13 -0
- data/app/assets/javascripts/detour/modals.js +3 -0
- data/app/assets/javascripts/detour/tooltips.js +3 -0
- data/app/assets/stylesheets/detour/application.css +14 -0
- data/app/assets/stylesheets/detour/bootstrap.css +7112 -0
- data/app/assets/stylesheets/detour/main.css +49 -0
- data/app/controllers/detour/application_controller.rb +12 -0
- data/app/controllers/detour/features_controller.rb +19 -0
- data/app/controllers/detour/flaggable_flags_controller.rb +90 -0
- data/app/controllers/detour/flags_controller.rb +18 -0
- data/app/helpers/detour/application_helper.rb +32 -0
- data/app/helpers/detour/flaggable_flags_helper.rb +5 -0
- data/app/helpers/detour/flags_helper.rb +7 -0
- data/app/models/detour/concerns/countable_flag.rb +19 -0
- data/app/models/detour/concerns/flag_actions.rb +141 -0
- data/app/models/detour/concerns/matchers.rb +73 -0
- data/app/models/detour/feature.rb +81 -0
- data/{lib → app/models}/detour/flag.rb +8 -2
- data/app/models/detour/flag_in_flag.rb +12 -0
- data/app/models/detour/group_flag.rb +13 -0
- data/{lib → app/models}/detour/opt_out_flag.rb +4 -2
- data/app/models/detour/percentage_flag.rb +9 -0
- data/app/views/detour/application/index.html.erb +0 -0
- data/app/views/detour/features/_errors.html.erb +11 -0
- data/app/views/detour/features/_success.html.erb +1 -0
- data/app/views/detour/features/error.js.erb +5 -0
- data/app/views/detour/features/success.js.erb +1 -0
- data/app/views/detour/flaggable_flags/_errors.html.erb +11 -0
- data/app/views/detour/flaggable_flags/_flaggable_flag.html.erb +11 -0
- data/app/views/detour/flaggable_flags/error.js.erb +5 -0
- data/app/views/detour/flaggable_flags/index.html.erb +34 -0
- data/app/views/detour/flaggable_flags/success.js.erb +1 -0
- data/app/views/detour/flags/_feature_form.html.erb +38 -0
- data/app/views/detour/flags/index.html.erb +76 -0
- data/app/views/detour/shared/_nav.html.erb +28 -0
- data/app/views/detour/shared/_spacer_cells.html.erb +3 -0
- data/app/views/layouts/detour/application.html.erb +29 -0
- data/config/routes.rb +16 -0
- data/detour.gemspec +15 -14
- data/lib/detour/acts_as_flaggable.rb +42 -3
- data/lib/detour/configuration.rb +35 -0
- data/lib/detour/engine.rb +5 -0
- data/lib/detour/flag_form.rb +87 -0
- data/lib/detour/version.rb +1 -1
- data/lib/detour.rb +10 -14
- data/lib/generators/templates/migration.rb +2 -0
- data/lib/tasks/detour.rake +16 -16
- data/script/rails +8 -0
- data/spec/controllers/detour/application_controller_spec.rb +15 -0
- data/spec/controllers/detour/features_controller_spec.rb +51 -0
- data/spec/controllers/detour/flaggable_flags_controller_spec.rb +100 -0
- data/spec/controllers/detour/flags_controller_spec.rb +77 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/app/models/widget.rb +5 -0
- data/spec/dummy/app/views/application/index.html.erb +22 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +19 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/detour.rb +36 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20131218015844_create_users.rb +10 -0
- data/spec/dummy/db/migrate/20131218023124_create_widgets.rb +9 -0
- data/spec/dummy/db/migrate/20131218055352_add_user_id_to_widgets.rb +6 -0
- data/spec/dummy/db/migrate/20131221052201_setup_detour.rb +32 -0
- data/spec/dummy/db/schema.rb +59 -0
- data/spec/dummy/db/seeds.rb +10 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/feature.rb +5 -0
- data/spec/factories/flag_in_flag.rb +6 -0
- data/spec/factories/group_flag.rb +7 -0
- data/spec/factories/opt_out_flag.rb +6 -0
- data/spec/factories/percentage_flag.rb +7 -0
- data/spec/factories/user.rb +6 -0
- data/spec/factories/widget.rb +5 -0
- data/spec/features/features_spec.rb +70 -0
- data/spec/features/flag_in_flags_spec.rb +118 -0
- data/spec/features/group_flags_spec.rb +49 -0
- data/spec/features/home_page_spec.rb +11 -0
- data/spec/features/opt_out_flags_spec.rb +105 -0
- data/spec/features/percentage_flags_spec.rb +63 -0
- data/spec/integration/group_rollout_spec.rb +1 -1
- data/spec/lib/detour/acts_as_flaggable_spec.rb +45 -0
- data/spec/lib/detour/configuration_spec.rb +23 -0
- data/spec/lib/detour/flag_form_spec.rb +84 -0
- data/spec/lib/{active_record/rollout → detour}/flaggable_spec.rb +19 -19
- data/spec/lib/tasks/{detour_rake_spec.rb → detour_spec.rb} +54 -54
- data/spec/{lib/active_record/rollout → models/detour}/feature_spec.rb +93 -67
- data/spec/models/detour/flag_in_flag_spec.rb +38 -0
- data/spec/{lib/active_record/rollout → models/detour}/flag_spec.rb +1 -1
- data/spec/models/detour/opt_out_flag_spec.rb +38 -0
- data/spec/{lib/active_record/rollout → models/detour}/percentage_flag_spec.rb +1 -1
- data/spec/spec_helper.rb +41 -21
- data/spec/support/shared_contexts/rake.rb +4 -14
- metadata +278 -95
- data/lib/detour/feature.rb +0 -312
- data/lib/detour/flaggable_flag.rb +0 -10
- data/lib/detour/group_flag.rb +0 -8
- data/lib/detour/percentage_flag.rb +0 -11
- data/spec/lib/active_record/rollout/acts_as_flaggable_spec.rb +0 -31
- data/spec/lib/active_record/rollout/flaggable_flag_spec.rb +0 -9
- data/spec/lib/active_record/rollout/opt_out_flag_spec.rb +0 -9
- data/spec/support/schema.rb +0 -13
- /data/lib/generators/{active_record_rollout_generator.rb → detour_generator.rb} +0 -0
- /data/lib/generators/templates/{active_record_rollout.rb → detour.rb} +0 -0
- /data/spec/{lib/active_record/rollout → models/detour}/group_flag_spec.rb +0 -0
data/lib/detour/feature.rb
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
# Represents an individual feature that may be rolled out to a set of records
|
|
2
|
-
# via individual flags, percentages, or defined groups.
|
|
3
|
-
class Detour::Feature < ActiveRecord::Base
|
|
4
|
-
# A hash representing the groups that have been defined.
|
|
5
|
-
@defined_groups = {}
|
|
6
|
-
|
|
7
|
-
# Directories to grep for feature tests
|
|
8
|
-
@grep_dirs = []
|
|
9
|
-
|
|
10
|
-
self.table_name = :detour_features
|
|
11
|
-
|
|
12
|
-
has_many :flaggable_flags
|
|
13
|
-
has_many :group_flags
|
|
14
|
-
has_many :percentage_flags
|
|
15
|
-
has_many :opt_out_flags
|
|
16
|
-
has_many :flags, dependent: :destroy
|
|
17
|
-
|
|
18
|
-
validates :name, presence: true, uniqueness: true
|
|
19
|
-
|
|
20
|
-
attr_accessible :name
|
|
21
|
-
|
|
22
|
-
# Returns an instance variable intended to hold an array of the lines of code
|
|
23
|
-
# that this feature appears on.
|
|
24
|
-
#
|
|
25
|
-
# @return [Array<String>] The lines that this rollout appears on (if
|
|
26
|
-
# {Detour::Feature.all_with_lines} has already been called).
|
|
27
|
-
def lines
|
|
28
|
-
@lines ||= []
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Determines whether or not the given instance has had the feature rolled out
|
|
32
|
-
# to it either via direct flagging-in, percentage, or by group membership.
|
|
33
|
-
#
|
|
34
|
-
# @example
|
|
35
|
-
# feature.match?(current_user)
|
|
36
|
-
#
|
|
37
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
|
38
|
-
# rollout.
|
|
39
|
-
#
|
|
40
|
-
# @return Whether or not the given instance has the feature rolled out to it.
|
|
41
|
-
def match?(instance)
|
|
42
|
-
match_id?(instance) || match_percentage?(instance) || match_groups?(instance)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Determines whether or not the given instance has had the feature rolled out
|
|
46
|
-
# to it via direct flagging-in.
|
|
47
|
-
#
|
|
48
|
-
# @example
|
|
49
|
-
# feature.match_id?(current_user)
|
|
50
|
-
#
|
|
51
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
|
52
|
-
# rollout.
|
|
53
|
-
#
|
|
54
|
-
# @return Whether or not the given instance has the feature rolled out to it
|
|
55
|
-
# via direct flagging-in.
|
|
56
|
-
def match_id?(instance)
|
|
57
|
-
flaggable_flags.where(flaggable_type: instance.class.to_s, flaggable_id: instance.id).any?
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Determines whether or not the given instance has had the feature rolled out
|
|
61
|
-
# to it via percentage.
|
|
62
|
-
#
|
|
63
|
-
# @example
|
|
64
|
-
# feature.match_percentage?(current_user)
|
|
65
|
-
#
|
|
66
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
|
67
|
-
# rollout.
|
|
68
|
-
#
|
|
69
|
-
# @return Whether or not the given instance has the feature rolled out to it
|
|
70
|
-
# via direct percentage.
|
|
71
|
-
def match_percentage?(instance)
|
|
72
|
-
flag = percentage_flags.find(:first, conditions: ["flaggable_type = ?", instance.class.to_s])
|
|
73
|
-
percentage = flag ? flag.percentage : 0
|
|
74
|
-
|
|
75
|
-
instance.id % 10 < percentage / 10
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Determines whether or not the given instance has had the feature rolled out
|
|
79
|
-
# to it via group membership.
|
|
80
|
-
#
|
|
81
|
-
# @example
|
|
82
|
-
# feature.match_groups?(current_user)
|
|
83
|
-
#
|
|
84
|
-
# @param [ActiveRecord::Base] instance A record to be tested for feature
|
|
85
|
-
# rollout.
|
|
86
|
-
#
|
|
87
|
-
# @return Whether or not the given instance has the feature rolled out to it
|
|
88
|
-
# via direct group membership.
|
|
89
|
-
def match_groups?(instance)
|
|
90
|
-
klass = instance.class.to_s
|
|
91
|
-
|
|
92
|
-
return unless self.class.defined_groups[klass]
|
|
93
|
-
|
|
94
|
-
group_names = group_flags.find_all_by_flaggable_type(klass).collect(&:group_name)
|
|
95
|
-
|
|
96
|
-
self.class.defined_groups[klass].collect { |group_name, block|
|
|
97
|
-
block.call(instance) if group_names.include? group_name
|
|
98
|
-
}.any?
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
class << self
|
|
102
|
-
# Returns the defined groups.
|
|
103
|
-
def defined_groups
|
|
104
|
-
@defined_groups
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Returns the default flaggable class.
|
|
108
|
-
def default_flaggable_class_name
|
|
109
|
-
@default_flaggable_class_name
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Sets the default flaggable class.
|
|
113
|
-
def default_flaggable_class_name=(klass)
|
|
114
|
-
@default_flaggable_class_name = klass
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# A list of directories to search through when finding feature checks.
|
|
118
|
-
def grep_dirs
|
|
119
|
-
@grep_dirs
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Set the list of directories to search through when finding feature checks.
|
|
123
|
-
def grep_dirs=(grep_dirs)
|
|
124
|
-
@grep_dirs = grep_dirs
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Return an array of both every feature in the database as well as every
|
|
128
|
-
# feature that is checked for in `@grep_dirs`. Features that are checked
|
|
129
|
-
# for but not persisted will be returned as unpersisted instances of this
|
|
130
|
-
# class. Each instance returned will have its `@lines` set to an array
|
|
131
|
-
# containing every line in `@grep_dirs` where it is checked for.
|
|
132
|
-
#
|
|
133
|
-
# @return [Array<Detour::Feature>] Every persisted and
|
|
134
|
-
# checked-for feature.
|
|
135
|
-
def all_with_lines
|
|
136
|
-
obj = all.each_with_object({}) { |feature, obj| obj[feature.name] = feature }
|
|
137
|
-
|
|
138
|
-
Dir[*@grep_dirs].each do |path|
|
|
139
|
-
next if File.directory? path
|
|
140
|
-
|
|
141
|
-
File.open path do |file|
|
|
142
|
-
file.each_line.with_index(1) do |line, i|
|
|
143
|
-
line.scan(/\.has_feature\?\s*\(*:(\w+)/).each do |match|
|
|
144
|
-
match = match[0]
|
|
145
|
-
obj[match] ||= find_or_initialize_by_name(match)
|
|
146
|
-
obj[match].lines << "#{path}#L#{i}"
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
obj.values
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Add a record to the given feature. If the feature is not found, an
|
|
156
|
-
# ActiveRecord::RecordNotFound will be raised.
|
|
157
|
-
#
|
|
158
|
-
# @example
|
|
159
|
-
# Detour::Feature.add_record_to_feature user, :new_ui
|
|
160
|
-
#
|
|
161
|
-
# @param [ActiveRecord::Base] record A record to add the feature to.
|
|
162
|
-
# @param [String,Symbol] feature_name The feature to be added to the record.
|
|
163
|
-
#
|
|
164
|
-
# @return [Detour::Flag] The
|
|
165
|
-
# {Detour::Flag Flag} created.
|
|
166
|
-
def add_record_to_feature(record, feature_name)
|
|
167
|
-
feature = find_by_name!(feature_name)
|
|
168
|
-
feature.flaggable_flags.where(flaggable_type: record.class.to_s, flaggable_id: record.id).first_or_create!
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Remove a record from the given feature. If the feature is not found, an
|
|
172
|
-
# ActiveRecord::RecordNotFound will be raised.
|
|
173
|
-
#
|
|
174
|
-
# @example
|
|
175
|
-
# Detour::Feature.remove_record_from_feature user, :new_ui
|
|
176
|
-
#
|
|
177
|
-
# @param [ActiveRecord::Base] record A record to remove the feature from.
|
|
178
|
-
# @param [String,Symbol] feature_name The feature to be removed from the
|
|
179
|
-
# record.
|
|
180
|
-
def remove_record_from_feature(record, feature_name)
|
|
181
|
-
feature = find_by_name!(feature_name)
|
|
182
|
-
feature.flaggable_flags.where(flaggable_type: record.class.to_s, flaggable_id: record.id).destroy_all
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# Opt the given record out of a feature. If the feature is not found, an
|
|
186
|
-
# ActiveRecord::RecordNotFound will be raised. An opt out ensures that no
|
|
187
|
-
# matter what, `record.rollout?(:rollout)` will always return false for any
|
|
188
|
-
# opted-out-of features.
|
|
189
|
-
#
|
|
190
|
-
# @param [ActiveRecord::Base] record A record to opt out of the feature.
|
|
191
|
-
# @param [String,Symbol] feature_name The feature to be opted out of.
|
|
192
|
-
#
|
|
193
|
-
# @example
|
|
194
|
-
# Detour::Feature.opt_record_out_of_feature user, :new_ui
|
|
195
|
-
#
|
|
196
|
-
# @return [Detour::OptOut] The
|
|
197
|
-
# {Detour::OptOut OptOut} created.
|
|
198
|
-
def opt_record_out_of_feature(record, feature_name)
|
|
199
|
-
feature = find_by_name!(feature_name)
|
|
200
|
-
feature.opt_out_flags.where(flaggable_type: record.class.to_s, flaggable_id: record.id).first_or_create!
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
# Remove any opt out for the given record out of a feature. If the feature
|
|
204
|
-
# is not found, an ActiveRecord::RecordNotFound will be raised.
|
|
205
|
-
#
|
|
206
|
-
# @example
|
|
207
|
-
# Detour::Feature.un_opt_record_out_of_feature user, :new_ui
|
|
208
|
-
#
|
|
209
|
-
# @param [ActiveRecord::Base] record A record to un-opt-out of the feature.
|
|
210
|
-
# @param [String,Symbol] feature_name The feature to be un-opted-out of.
|
|
211
|
-
def un_opt_record_out_of_feature(record, feature_name)
|
|
212
|
-
feature = find_by_name!(feature_name)
|
|
213
|
-
feature.opt_out_flags.where(flaggable_type: record.class.to_s, flaggable_id: record.id).destroy_all
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# Add a group to the given feature. If the feature is not found, an
|
|
217
|
-
# ActiveRecord::RecordNotFound will be raised.
|
|
218
|
-
#
|
|
219
|
-
# @example
|
|
220
|
-
# Detour::Feature.add_group_to_feature "User", "admin", :delete_records
|
|
221
|
-
#
|
|
222
|
-
# @param [String] flaggable_type The class (as a string) that the group
|
|
223
|
-
# should be associated with.
|
|
224
|
-
# @param [String] group_name The name of the group to have the feature
|
|
225
|
-
# added to it.
|
|
226
|
-
# @param [String,Symbol] feature_name The feature to be added to the group.
|
|
227
|
-
#
|
|
228
|
-
# @return [Detour::Flag] The
|
|
229
|
-
# {Detour::Flag Flag} created.
|
|
230
|
-
def add_group_to_feature(flaggable_type, group_name, feature_name)
|
|
231
|
-
feature = find_by_name!(feature_name)
|
|
232
|
-
feature.group_flags.where(flaggable_type: flaggable_type, group_name: group_name).first_or_create!
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
# Remove a group from agiven feature. If the feature is not found, an
|
|
236
|
-
# ActiveRecord::RecordNotFound will be raised.
|
|
237
|
-
#
|
|
238
|
-
# @example
|
|
239
|
-
# Detour::Feature.remove_group_from_feature "User", "admin", :delete_records
|
|
240
|
-
#
|
|
241
|
-
# @param [String] flaggable_type The class (as a string) that the group should
|
|
242
|
-
# be removed from.
|
|
243
|
-
# @param [String] group_name The name of the group to have the feature
|
|
244
|
-
# removed from it.
|
|
245
|
-
# @param [String,Symbol] feature_name The feature to be removed from the
|
|
246
|
-
# group.
|
|
247
|
-
def remove_group_from_feature(flaggable_type, group_name, feature_name)
|
|
248
|
-
feature = find_by_name!(feature_name)
|
|
249
|
-
feature.group_flags.where(flaggable_type: flaggable_type, group_name: group_name).destroy_all
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
# Add a percentage of records to the given feature. If the feature is not
|
|
253
|
-
# found, an ActiveRecord::RecordNotFound will be raised.
|
|
254
|
-
#
|
|
255
|
-
# @example
|
|
256
|
-
# Detour::Feature.add_percentage_to_feature "User", 75, :delete_records
|
|
257
|
-
#
|
|
258
|
-
# @param [String] flaggable_type The class (as a string) that the percetnage
|
|
259
|
-
# should be associated with.
|
|
260
|
-
# @param [Integer] percentage The percentage of `flaggable_type` records
|
|
261
|
-
# that the feature will be available for.
|
|
262
|
-
# @param [String,Symbol] feature_name The feature to be added to the
|
|
263
|
-
# percentage of records.
|
|
264
|
-
#
|
|
265
|
-
# @return [Detour::Flag] The
|
|
266
|
-
# {Detour::Flag Flag} created.
|
|
267
|
-
def add_percentage_to_feature(flaggable_type, percentage, feature_name)
|
|
268
|
-
feature = find_by_name!(feature_name)
|
|
269
|
-
|
|
270
|
-
flag = feature.percentage_flags.where(flaggable_type: flaggable_type).first_or_initialize
|
|
271
|
-
flag.update_attributes!(percentage: percentage)
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# Remove any percentage flags for the given feature. If the feature is not
|
|
275
|
-
# found, an ActiveRecord::RecordNotFound will be raised.
|
|
276
|
-
#
|
|
277
|
-
# @example
|
|
278
|
-
# Detour::Feature.remove_percentage_from_feature "User", delete_records
|
|
279
|
-
#
|
|
280
|
-
# @param [String] flaggable_type The class (as a string) that the percetnage
|
|
281
|
-
# should be removed from.
|
|
282
|
-
# @param [String,Symbol] feature_name The feature to have the percentage
|
|
283
|
-
# flag removed from.
|
|
284
|
-
def remove_percentage_from_feature(flaggable_type, feature_name)
|
|
285
|
-
feature = find_by_name!(feature_name)
|
|
286
|
-
feature.percentage_flags.where(flaggable_type: flaggable_type).destroy_all
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# Allows for methods of the form `define_user_group` that call the private
|
|
290
|
-
# method `define_group_for_class`. A new group for any `User` records will
|
|
291
|
-
# be created that rollouts can be attached to.
|
|
292
|
-
#
|
|
293
|
-
# @example
|
|
294
|
-
# Detour::Feature.define_user_group :admins do |user|
|
|
295
|
-
# user.admin?
|
|
296
|
-
# end
|
|
297
|
-
def method_missing(method, *args, &block)
|
|
298
|
-
if /^define_(?<klass>[a-z0-9_]+)_group/ =~ method
|
|
299
|
-
define_group_for_class(klass.classify, args[0], &block)
|
|
300
|
-
else
|
|
301
|
-
super
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
private
|
|
306
|
-
|
|
307
|
-
def define_group_for_class(klass, group_name, &block)
|
|
308
|
-
@defined_groups[klass] ||= {}
|
|
309
|
-
@defined_groups[klass][group_name] = block
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
end
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# An individual record of a certain type may be flagged into a feature with
|
|
2
|
-
# this class.
|
|
3
|
-
class Detour::FlaggableFlag < Detour::Flag
|
|
4
|
-
belongs_to :flaggable, polymorphic: true
|
|
5
|
-
|
|
6
|
-
validates :flaggable_id, presence: true
|
|
7
|
-
validates :feature_id, uniqueness: { scope: [:flaggable_type, :flaggable_id] }
|
|
8
|
-
|
|
9
|
-
attr_accessible :flaggable
|
|
10
|
-
end
|
data/lib/detour/group_flag.rb
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# A group of flaggable records of a given class may be flagged into a feature
|
|
2
|
-
# with this class.
|
|
3
|
-
class Detour::GroupFlag < Detour::Flag
|
|
4
|
-
validates :group_name, presence: true
|
|
5
|
-
|
|
6
|
-
attr_accessible :group_name
|
|
7
|
-
validates :feature_id, uniqueness: { scope: [:flaggable_type, :group_name] }
|
|
8
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# A percentage of flaggable records of a given class may be flagged into a feature
|
|
2
|
-
# with this class.
|
|
3
|
-
class Detour::PercentageFlag < Detour::Flag
|
|
4
|
-
validates :percentage,
|
|
5
|
-
presence: true,
|
|
6
|
-
numericality: { greater_than: 0, less_than_or_equal_to: 100 }
|
|
7
|
-
|
|
8
|
-
validates :feature_id, uniqueness: { scope: :flaggable_type }
|
|
9
|
-
|
|
10
|
-
attr_accessible :percentage
|
|
11
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe Detour::ActsAsFlaggable do
|
|
4
|
-
subject { User.new }
|
|
5
|
-
|
|
6
|
-
it { should have_many :flaggable_flags }
|
|
7
|
-
it { should have_many :opt_out_flags }
|
|
8
|
-
it { should have_many(:features).through(:flaggable_flags) }
|
|
9
|
-
|
|
10
|
-
it "includes Detour::Flaggable" do
|
|
11
|
-
subject.class.ancestors.should include Detour::Flaggable
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe "#acts_as_flaggable" do
|
|
15
|
-
context "when given a :find_by parameter" do
|
|
16
|
-
class Foo < ActiveRecord::Base
|
|
17
|
-
acts_as_flaggable find_by: :email
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "sets the appropriate class variable on the class" do
|
|
21
|
-
Foo.instance_variable_get("@detour_flaggable_find_by").should eq :email
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
context "when not given a :find_by parameter" do
|
|
26
|
-
it "uses the default :id value for flaggable_find_by" do
|
|
27
|
-
User.instance_variable_get("@detour_flaggable_find_by").should eq :id
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe Detour::FlaggableFlag do
|
|
4
|
-
it { should be_a Detour::Flag }
|
|
5
|
-
it { should belong_to :flaggable }
|
|
6
|
-
it { should validate_presence_of :flaggable_id }
|
|
7
|
-
it { should allow_mass_assignment_of :flaggable }
|
|
8
|
-
it { should validate_uniqueness_of :feature_id }
|
|
9
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe Detour::OptOutFlag do
|
|
4
|
-
it { should be_a Detour::Flag }
|
|
5
|
-
it { should belong_to :flaggable }
|
|
6
|
-
it { should validate_presence_of :flaggable_id }
|
|
7
|
-
it { should allow_mass_assignment_of :flaggable}
|
|
8
|
-
it { should validate_uniqueness_of :feature_id }
|
|
9
|
-
end
|
data/spec/support/schema.rb
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|