pluginaweek-preferences 0.3.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.
- data/CHANGELOG.rdoc +56 -0
- data/LICENSE +20 -0
- data/README.rdoc +185 -0
- data/Rakefile +96 -0
- data/app/models/preference.rb +65 -0
- data/init.rb +1 -0
- data/lib/preferences.rb +339 -0
- data/lib/preferences/preference_definition.rb +43 -0
- data/test/app_root/app/models/car.rb +2 -0
- data/test/app_root/app/models/employee.rb +2 -0
- data/test/app_root/app/models/manager.rb +3 -0
- data/test/app_root/app/models/user.rb +7 -0
- data/test/app_root/db/migrate/001_create_users.rb +11 -0
- data/test/app_root/db/migrate/002_create_cars.rb +11 -0
- data/test/app_root/db/migrate/003_create_employees.rb +12 -0
- data/test/app_root/db/migrate/004_migrate_preferences_to_version_1.rb +13 -0
- data/test/factory.rb +65 -0
- data/test/functional/preferences_test.rb +426 -0
- data/test/test_helper.rb +13 -0
- data/test/unit/preference_definition_test.rb +185 -0
- data/test/unit/preference_test.rb +234 -0
- metadata +84 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Preferences
|
2
|
+
# Represents the definition of a preference for a particular model
|
3
|
+
class PreferenceDefinition
|
4
|
+
def initialize(name, *args) #:nodoc:
|
5
|
+
options = args.extract_options!
|
6
|
+
options.assert_valid_keys(:default)
|
7
|
+
|
8
|
+
@type = args.first ? args.first.to_s : 'boolean'
|
9
|
+
|
10
|
+
# Create a column that will be responsible for typecasting
|
11
|
+
@column = ActiveRecord::ConnectionAdapters::Column.new(name.to_s, options[:default], @type == 'any' ? nil : @type)
|
12
|
+
end
|
13
|
+
|
14
|
+
# The name of the preference
|
15
|
+
def name
|
16
|
+
@column.name
|
17
|
+
end
|
18
|
+
|
19
|
+
# The default value to use for the preference in case none have been
|
20
|
+
# previously defined
|
21
|
+
def default_value
|
22
|
+
@column.default
|
23
|
+
end
|
24
|
+
|
25
|
+
# Typecasts the value based on the type of preference that was defined.
|
26
|
+
# This uses ActiveRecord's typecast functionality so the same rules for
|
27
|
+
# typecasting a model's columns apply here.
|
28
|
+
def type_cast(value)
|
29
|
+
@type == 'any' ? value : @column.type_cast(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Typecasts the value to true/false depending on the type of preference
|
33
|
+
def query(value)
|
34
|
+
if !(value = type_cast(value))
|
35
|
+
false
|
36
|
+
elsif @column.number?
|
37
|
+
!value.zero?
|
38
|
+
else
|
39
|
+
!value.blank?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class MigratePreferencesToVersion1 < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
ActiveRecord::Migrator.new(:up, "#{Rails.root}/../../db/migrate", 0).migrations.each do |migration|
|
4
|
+
migration.migrate(:up)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
ActiveRecord::Migrator.new(:up, "#{Rails.root}/../../db/migrate", 0).migrations.each do |migration|
|
10
|
+
migration.migrate(:down)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/test/factory.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Factory
|
2
|
+
# Build actions for the model
|
3
|
+
def self.build(model, &block)
|
4
|
+
name = model.to_s.underscore
|
5
|
+
|
6
|
+
define_method("#{name}_attributes", block)
|
7
|
+
define_method("valid_#{name}_attributes") {|*args| valid_attributes_for(model, *args)}
|
8
|
+
define_method("new_#{name}") {|*args| new_record(model, *args)}
|
9
|
+
define_method("create_#{name}") {|*args| create_record(model, *args)}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get valid attributes for the model
|
13
|
+
def valid_attributes_for(model, attributes = {})
|
14
|
+
name = model.to_s.underscore
|
15
|
+
send("#{name}_attributes", attributes)
|
16
|
+
attributes.stringify_keys!
|
17
|
+
attributes
|
18
|
+
end
|
19
|
+
|
20
|
+
# Build an unsaved record
|
21
|
+
def new_record(model, *args)
|
22
|
+
attributes = valid_attributes_for(model, *args)
|
23
|
+
record = model.new(attributes)
|
24
|
+
attributes.each {|attr, value| record.send("#{attr}=", value) if model.accessible_attributes && !model.accessible_attributes.include?(attr) || model.protected_attributes && model.protected_attributes.include?(attr)}
|
25
|
+
record
|
26
|
+
end
|
27
|
+
|
28
|
+
# Build and save/reload a record
|
29
|
+
def create_record(model, *args)
|
30
|
+
record = new_record(model, *args)
|
31
|
+
record.save!
|
32
|
+
record.reload
|
33
|
+
record
|
34
|
+
end
|
35
|
+
|
36
|
+
build Car do |attributes|
|
37
|
+
attributes.reverse_merge!(
|
38
|
+
:name => 'Porsche'
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
build Employee do |attributes|
|
43
|
+
attributes.reverse_merge!(
|
44
|
+
:name => 'John Smith'
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
build Manager do |attributes|
|
49
|
+
valid_employee_attributes(attributes)
|
50
|
+
end
|
51
|
+
|
52
|
+
build Preference do |attributes|
|
53
|
+
attributes[:owner] = create_user unless attributes.include?(:owner)
|
54
|
+
attributes.reverse_merge!(
|
55
|
+
:name => 'notifications',
|
56
|
+
:value => false
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
build User do |attributes|
|
61
|
+
attributes.reverse_merge!(
|
62
|
+
:login => 'admin'
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,426 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../test_helper"
|
2
|
+
|
3
|
+
class PreferencesTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
User.preference :notifications, :boolean
|
6
|
+
|
7
|
+
@user = User.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_should_raise_exception_if_invalid_options_specified
|
11
|
+
assert_raise(ArgumentError) {User.preference :notifications, :invalid => true}
|
12
|
+
assert_raise(ArgumentError) {User.preference :notifications, :boolean, :invalid => true}
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_create_preferred_query_method
|
16
|
+
assert @user.respond_to?(:preferred_notifications?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_create_prefers_query_method
|
20
|
+
assert @user.respond_to?(:prefers_notifications?)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_create_preferred_reader
|
24
|
+
assert @user.respond_to?(:preferred_notifications)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_create_prefers_reader
|
28
|
+
assert @user.respond_to?(:prefers_notifications)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_create_preferred_writer
|
32
|
+
assert @user.respond_to?(:preferred_notifications=)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_create_prefers_writer
|
36
|
+
assert @user.respond_to?(:prefers_notifications=)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_create_preference_definitions
|
40
|
+
assert User.respond_to?(:preference_definitions)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_create_default_preferences
|
44
|
+
assert User.respond_to?(:default_preferences)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_include_new_definitions_in_preference_definitions
|
48
|
+
assert_not_nil User.preference_definitions['notifications']
|
49
|
+
end
|
50
|
+
|
51
|
+
def teardown
|
52
|
+
User.preference_definitions.delete('notifications')
|
53
|
+
User.default_preferences.delete('notifications')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class UserByDefaultTest < ActiveSupport::TestCase
|
58
|
+
def setup
|
59
|
+
@user = User.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_not_prefer_hot_salsa
|
63
|
+
assert_nil @user.preferred_hot_salsa
|
64
|
+
assert_nil @user.prefers_hot_salsa
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_should_prefer_dark_chocolate
|
68
|
+
assert_equal true, @user.preferred_dark_chocolate
|
69
|
+
assert_equal true, @user.prefers_dark_chocolate
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_should_not_have_a_preferred_color
|
73
|
+
assert_nil @user.preferred_color
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_should_not_have_a_preferred_car
|
77
|
+
assert_nil @user.preferred_car
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_should_have_a_preferred_language
|
81
|
+
assert_equal 'English', @user.preferred_language
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_should_have_only_default_preferences
|
85
|
+
expected = {
|
86
|
+
'hot_salsa' => nil,
|
87
|
+
'dark_chocolate' => true,
|
88
|
+
'color' => nil,
|
89
|
+
'car' => nil,
|
90
|
+
'language' => 'English'
|
91
|
+
}
|
92
|
+
|
93
|
+
assert_equal expected, @user.preferences
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class UserTest < ActiveSupport::TestCase
|
98
|
+
def setup
|
99
|
+
@user = new_user
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_should_be_able_to_change_hot_salsa_preference
|
103
|
+
@user.prefers_hot_salsa = false
|
104
|
+
assert_equal false, @user.prefers_hot_salsa?
|
105
|
+
|
106
|
+
@user.prefers_hot_salsa = true
|
107
|
+
assert_equal true, @user.prefers_hot_salsa?
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_should_be_able_to_change_dark_chocolate_preference
|
111
|
+
@user.prefers_dark_chocolate = false
|
112
|
+
assert_equal false, @user.prefers_dark_chocolate?
|
113
|
+
|
114
|
+
@user.prefers_dark_chocolate = true
|
115
|
+
assert_equal true, @user.prefers_dark_chocolate?
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_be_able_to_change_color_preference
|
119
|
+
@user.preferred_color = 'blue'
|
120
|
+
assert_equal 'blue', @user.preferred_color
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_should_be_able_to_change_car_preference
|
124
|
+
@user.preferred_car = 1
|
125
|
+
assert_equal 1, @user.preferred_car
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_should_be_able_to_change_language_preference
|
129
|
+
@user.preferred_language = 'Latin'
|
130
|
+
assert_equal 'Latin', @user.preferred_language
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_should_be_able_to_use_generic_preferred_query_method
|
134
|
+
@user.prefers_hot_salsa = true
|
135
|
+
assert @user.preferred?(:hot_salsa)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_should_be_able_to_use_generic_prefers_query_method
|
139
|
+
@user.prefers_hot_salsa = true
|
140
|
+
assert @user.prefers?(:hot_salsa)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_should_be_able_to_use_generic_preferred_method
|
144
|
+
@user.preferred_color = 'blue'
|
145
|
+
assert_equal 'blue', @user.preferred(:color)
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_should_be_able_to_use_generic_prefers_method
|
149
|
+
@user.preferred_color = 'blue'
|
150
|
+
assert_equal 'blue', @user.prefers(:color)
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_should_be_able_to_use_generic_set_preference_method
|
154
|
+
@user.set_preference(:color, 'blue')
|
155
|
+
assert_equal 'blue', @user.preferred(:color)
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_should_still_be_new_record_after_changing_preference
|
159
|
+
@user.preferred_color = 'blue'
|
160
|
+
assert @user.new_record?
|
161
|
+
assert @user.stored_preferences.empty?
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class UserAfterBeingCreatedTest < ActiveSupport::TestCase
|
166
|
+
def setup
|
167
|
+
@user = create_user
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_should_not_have_any_stored_preferences
|
171
|
+
assert @user.stored_preferences.empty?
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class UserWithoutStoredPreferencesTest < ActiveSupport::TestCase
|
176
|
+
def setup
|
177
|
+
@user = create_user
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_should_not_prefer_hot_salsa
|
181
|
+
assert_nil @user.preferred_hot_salsa
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_should_prefer_dark_chocolate
|
185
|
+
assert_equal true, @user.preferred_dark_chocolate
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_should_not_have_a_preferred_color
|
189
|
+
assert_nil @user.preferred_color
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_should_not_have_a_preferred_car
|
193
|
+
assert_nil @user.preferred_car
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_should_have_a_preferred_language
|
197
|
+
assert_equal 'English', @user.preferred_language
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_should_not_save_record_after_changing_preference
|
201
|
+
@user.preferred_language = 'Latin'
|
202
|
+
|
203
|
+
user = User.find(@user.id)
|
204
|
+
assert_equal 'English', user.preferred_language
|
205
|
+
assert user.stored_preferences.empty?
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class UserWithStoredPreferencesTest < ActiveSupport::TestCase
|
210
|
+
def setup
|
211
|
+
@user = create_user
|
212
|
+
@user.preferred_language = 'Latin'
|
213
|
+
@user.save!
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_should_have_stored_preferences
|
217
|
+
assert_equal 1, @user.stored_preferences.size
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_should_include_custom_and_default_preferences_in_preferences
|
221
|
+
expected = {
|
222
|
+
'hot_salsa' => nil,
|
223
|
+
'dark_chocolate' => true,
|
224
|
+
'color' => nil,
|
225
|
+
'car' => nil,
|
226
|
+
'language' => 'Latin'
|
227
|
+
}
|
228
|
+
|
229
|
+
assert_equal expected, @user.preferences
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_should_use_preferences_for_prefs
|
233
|
+
expected = {
|
234
|
+
'hot_salsa' => nil,
|
235
|
+
'dark_chocolate' => true,
|
236
|
+
'color' => nil,
|
237
|
+
'car' => nil,
|
238
|
+
'language' => 'Latin'
|
239
|
+
}
|
240
|
+
|
241
|
+
assert_equal expected, @user.prefs
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_should_not_remove_preference_if_set_to_default
|
245
|
+
@user.preferred_language = 'English'
|
246
|
+
@user.save!
|
247
|
+
@user.reload
|
248
|
+
assert_equal 1, @user.stored_preferences.size
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_should_not_remove_preference_if_set_to_nil
|
252
|
+
@user.preferred_language = nil
|
253
|
+
@user.save!
|
254
|
+
@user.reload
|
255
|
+
assert_equal 1, @user.stored_preferences.size
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_should_not_save_preference_if_model_is_not_saved
|
259
|
+
@user.preferred_language = 'English'
|
260
|
+
|
261
|
+
user = User.find(@user.id)
|
262
|
+
assert_equal 'Latin', user.preferred_language
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_should_modify_existing_preferences_when_saved
|
266
|
+
@user.preferred_language = 'Spanish'
|
267
|
+
assert @user.save
|
268
|
+
|
269
|
+
@user.reload
|
270
|
+
assert_equal 'Spanish', @user.preferred_language
|
271
|
+
assert_equal 1, @user.stored_preferences.size
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_should_add_new_preferences_when_saved
|
275
|
+
@user.preferred_color = 'blue'
|
276
|
+
assert @user.save
|
277
|
+
|
278
|
+
@user.reload
|
279
|
+
assert_equal 'blue', @user.preferred_color
|
280
|
+
assert_equal 2, @user.stored_preferences.size
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class UserWithStoredPreferencesForBasicGroupsTest < ActiveSupport::TestCase
|
285
|
+
def setup
|
286
|
+
@user = create_user
|
287
|
+
@user.preferred_color = 'red', 'cars'
|
288
|
+
@user.save!
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_should_have_stored_preferences
|
292
|
+
assert_equal 1, @user.stored_preferences.size
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_should_include_group_in_preferences
|
296
|
+
expected = {
|
297
|
+
'hot_salsa' => nil,
|
298
|
+
'dark_chocolate' => true,
|
299
|
+
'color' => nil,
|
300
|
+
'car' => nil,
|
301
|
+
'language' => 'English',
|
302
|
+
'cars' => {
|
303
|
+
'hot_salsa' => nil,
|
304
|
+
'dark_chocolate' => true,
|
305
|
+
'color' => 'red',
|
306
|
+
'car' => nil,
|
307
|
+
'language' => 'English'
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
assert_equal expected, @user.preferences
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_should_be_able_to_show_all_preferences_just_for_the_owner
|
315
|
+
expected = {
|
316
|
+
'hot_salsa' => nil,
|
317
|
+
'dark_chocolate' => true,
|
318
|
+
'color' => nil,
|
319
|
+
'car' => nil,
|
320
|
+
'language' => 'English'
|
321
|
+
}
|
322
|
+
|
323
|
+
assert_equal expected, @user.preferences(nil)
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_should_be_able_to_show_all_preferences_for_a_single_group
|
327
|
+
expected = {
|
328
|
+
'hot_salsa' => nil,
|
329
|
+
'dark_chocolate' => true,
|
330
|
+
'color' => 'red',
|
331
|
+
'car' => nil,
|
332
|
+
'language' => 'English'
|
333
|
+
}
|
334
|
+
|
335
|
+
assert_equal expected, @user.preferences('cars')
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_should_not_have_preference_without_group
|
339
|
+
assert_nil @user.preferred_color
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_should_have_preference_with_group
|
343
|
+
assert_equal 'red', @user.preferred_color('cars')
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_should_modify_existing_preferences_when_saved
|
347
|
+
@user.preferred_color = 'blue', 'cars'
|
348
|
+
assert @user.save
|
349
|
+
|
350
|
+
@user.reload
|
351
|
+
assert_equal 'blue', @user.preferred_color('cars')
|
352
|
+
assert_equal 1, @user.stored_preferences.size
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_should_be_able_to_differentiate_between_groups
|
356
|
+
@user.preferred_color = 'blue', 'boats'
|
357
|
+
assert @user.save
|
358
|
+
|
359
|
+
@user.reload
|
360
|
+
assert_equal 'red', @user.preferred_color('cars')
|
361
|
+
assert_equal 'blue', @user.preferred_color('boats')
|
362
|
+
assert_equal 2, @user.stored_preferences.size
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class UserWithStoredPreferencesForActiveRecordGroupsTest < ActiveSupport::TestCase
|
367
|
+
def setup
|
368
|
+
@car = create_car
|
369
|
+
|
370
|
+
@user = create_user
|
371
|
+
@user.preferred_color = 'red', @car
|
372
|
+
@user.save!
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_should_have_stored_preferences
|
376
|
+
assert_equal 1, @user.stored_preferences.size
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_should_have_preferences_for_group
|
380
|
+
expected = {
|
381
|
+
'hot_salsa' => nil,
|
382
|
+
'dark_chocolate' => true,
|
383
|
+
'color' => nil,
|
384
|
+
'car' => nil,
|
385
|
+
'language' => 'English',
|
386
|
+
@car => {
|
387
|
+
'hot_salsa' => nil,
|
388
|
+
'dark_chocolate' => true,
|
389
|
+
'color' => 'red',
|
390
|
+
'car' => nil,
|
391
|
+
'language' => 'English'
|
392
|
+
}
|
393
|
+
}
|
394
|
+
|
395
|
+
assert_equal expected, @user.preferences
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_should_not_have_preference_without_group
|
399
|
+
assert_nil @user.preferred_color
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_should_have_preference_with_group
|
403
|
+
assert_equal 'red', @user.preferred_color(@car)
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_should_modify_existing_preferences_when_saved
|
407
|
+
@user.preferred_color = 'blue', @car
|
408
|
+
assert @user.save
|
409
|
+
|
410
|
+
@user.reload
|
411
|
+
assert_equal 'blue', @user.preferred_color(@car)
|
412
|
+
assert_equal 1, @user.stored_preferences.size
|
413
|
+
end
|
414
|
+
|
415
|
+
def test_should_be_able_to_differentiate_between_groups
|
416
|
+
@different_car = create_car
|
417
|
+
|
418
|
+
@user.preferred_color = 'blue', @different_car
|
419
|
+
assert @user.save
|
420
|
+
|
421
|
+
@user.reload
|
422
|
+
assert_equal 'red', @user.preferred_color(@car)
|
423
|
+
assert_equal 'blue', @user.preferred_color(@different_car)
|
424
|
+
assert_equal 2, @user.stored_preferences.size
|
425
|
+
end
|
426
|
+
end
|