preferences 0.4.0 → 0.4.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 CHANGED
@@ -1,5 +1,10 @@
1
1
  == master
2
2
 
3
+ == 0.4.1 / 2010-03-07
4
+
5
+ * Add support for per-group default preferences
6
+ * Fix unsaved boolean preferences getting overridden by defaults if value is false
7
+
3
8
  == 0.4.0 / 2010-03-07
4
9
 
5
10
  * Add {preference}_changed?, {preference}_was, {preference}_changed, {preference}_will_change!, and reset_{preference}!
data/README.rdoc CHANGED
@@ -60,7 +60,7 @@ To define the preferences for a model, you can do so right within the model:
60
60
  preference :dark_chocolate, :default => true
61
61
  preference :color, :string
62
62
  preference :favorite_number
63
- preference :language, :string, :default => 'English'
63
+ preference :language, :string, :default => 'English', :group_defaults => {:chat => 'Spanish'}
64
64
  end
65
65
 
66
66
  In the above model, 5 preferences have been defined:
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/gempackagetask'
6
6
 
7
7
  spec = Gem::Specification.new do |s|
8
8
  s.name = 'preferences'
9
- s.version = '0.4.0'
9
+ s.version = '0.4.1'
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.summary = 'Adds support for easily creating custom preferences for ActiveRecord models'
12
12
  s.description = s.summary
data/lib/preferences.rb CHANGED
@@ -51,6 +51,9 @@ module Preferences
51
51
  #
52
52
  # Configuration options:
53
53
  # * <tt>:default</tt> - The default value for the preference. Default is nil.
54
+ # * <tt>:group_defaults</tt> - Defines the default values to use for various
55
+ # groups. This should map group_name -> defaults. For ActiveRecord groups,
56
+ # use the class name.
54
57
  #
55
58
  # == Examples
56
59
  #
@@ -59,7 +62,7 @@ module Preferences
59
62
  #
60
63
  # class User < ActiveRecord::Base
61
64
  # preference :notifications, :default => false
62
- # preference :color, :string, :default => 'red'
65
+ # preference :color, :string, :default => 'red', :group_defaults => {:car => 'black'}
63
66
  # preference :favorite_number, :integer
64
67
  # preference :data, :any # Allows any data type to be stored
65
68
  # end
@@ -152,9 +155,6 @@ module Preferences
152
155
  class_inheritable_hash :preference_definitions
153
156
  self.preference_definitions = {}
154
157
 
155
- class_inheritable_hash :default_preferences
156
- self.default_preferences = {}
157
-
158
158
  has_many :stored_preferences, :as => :owner, :class_name => 'Preference'
159
159
 
160
160
  after_save :update_preferences
@@ -171,7 +171,6 @@ module Preferences
171
171
  name = name.to_s
172
172
  definition = PreferenceDefinition.new(name, *args)
173
173
  self.preference_definitions[name] = definition
174
- self.default_preferences[name] = definition.default_value
175
174
 
176
175
  # Create short-hand accessor methods, making sure that the name
177
176
  # is method-safe in terms of what characters are allowed
@@ -249,11 +248,12 @@ module Preferences
249
248
  end
250
249
 
251
250
  preferences.each do |(group, preference), value|
251
+ group_id, group_type = Preference.split_group(group)
252
252
  preference = preference.to_s
253
- value = preference_definitions[preference.to_s].type_cast(value)
254
- is_default = default_preferences[preference.to_s] == value
253
+ definition = preference_definitions[preference.to_s]
254
+ value = definition.type_cast(value)
255
+ is_default = definition.default_value(group_type) == value
255
256
 
256
- group_id, group_type = Preference.split_group(group)
257
257
  table = "preferences_#{group_id}_#{group_type}_#{preference}"
258
258
 
259
259
  # Since each preference is a different record, they need their own
@@ -303,19 +303,21 @@ module Preferences
303
303
  # user.preferences(:cars)
304
304
  # => {"language=>"English", "color"=>"red"}
305
305
  def preferences(group = nil)
306
+ preferences = preferences_group(group)
307
+
306
308
  unless preferences_group_loaded?(group)
307
- preferences = preferences_group(group)
308
-
309
309
  group_id, group_type = Preference.split_group(group)
310
310
  find_preferences(:group_id => group_id, :group_type => group_type).each do |preference|
311
- preferences[preference.name] ||= preference.value
311
+ preferences[preference.name] = preference.value unless preferences.include?(preference.name)
312
312
  end
313
313
 
314
314
  # Add defaults
315
- preferences.reverse_merge!(self.class.default_preferences.dup)
315
+ preference_definitions.each do |name, definition|
316
+ preferences[name] = definition.default_value(group_type) unless preferences.include?(name)
317
+ end
316
318
  end
317
319
 
318
- preferences_group(group).dup
320
+ preferences.dup
319
321
  end
320
322
 
321
323
  # Queries whether or not a value is present for the given preference.
@@ -374,7 +376,7 @@ module Preferences
374
376
  group_id, group_type = Preference.split_group(group)
375
377
  preference = find_preferences(:name => name, :group_id => group_id, :group_type => group_type).first unless preferences_group_loaded?(group)
376
378
 
377
- value = preference ? preference.value : preference_definitions[name].default_value
379
+ value = preference ? preference.value : preference_definitions[name].default_value(group_type)
378
380
  preferences_group(group)[name] = value
379
381
  end
380
382
 
@@ -6,12 +6,17 @@ module Preferences
6
6
 
7
7
  def initialize(name, *args) #:nodoc:
8
8
  options = args.extract_options!
9
- options.assert_valid_keys(:default)
9
+ options.assert_valid_keys(:default, :group_defaults)
10
10
 
11
11
  @type = args.first ? args.first.to_sym : :boolean
12
12
 
13
13
  # Create a column that will be responsible for typecasting
14
14
  @column = ActiveRecord::ConnectionAdapters::Column.new(name.to_s, options[:default], @type == :any ? nil : @type.to_s)
15
+
16
+ @group_defaults = (options[:group_defaults] || {}).inject({}) do |defaults, (group, default)|
17
+ defaults[group.is_a?(Symbol) ? group.to_s : group] = type_cast(default)
18
+ defaults
19
+ end
15
20
  end
16
21
 
17
22
  # The name of the preference
@@ -21,8 +26,8 @@ module Preferences
21
26
 
22
27
  # The default value to use for the preference in case none have been
23
28
  # previously defined
24
- def default_value
25
- @column.default
29
+ def default_value(group = nil)
30
+ @group_defaults.include?(group) ? @group_defaults[group] : @column.default
26
31
  end
27
32
 
28
33
  # Determines whether column backing this preference stores numberic values
@@ -6,7 +6,6 @@ class ModelPreferenceTest < ActiveRecord::TestCase
6
6
 
7
7
  def teardown
8
8
  User.preference_definitions.clear
9
- User.default_preferences.clear
10
9
  end
11
10
  end
12
11
 
@@ -15,10 +14,6 @@ class ModelWithoutPreferencesTest < ActiveRecord::TestCase
15
14
  assert !Car.respond_to?(:preference_definitions)
16
15
  end
17
16
 
18
- def test_should_not_create_default_preferences
19
- assert !Car.respond_to?(:default_preferences)
20
- end
21
-
22
17
  def test_should_not_create_stored_preferences_association
23
18
  assert !Car.new.respond_to?(:stored_preferences)
24
19
  end
@@ -39,10 +34,6 @@ class PreferencesAfterFirstBeingDefinedTest < ModelPreferenceTest
39
34
  assert User.respond_to?(:preference_definitions)
40
35
  end
41
36
 
42
- def test_should_create_default_preferences
43
- assert User.respond_to?(:default_preferences)
44
- end
45
-
46
37
  def test_should_create_preference_scopes
47
38
  assert User.respond_to?(:with_preferences)
48
39
  assert User.respond_to?(:without_preferences)
@@ -136,10 +127,6 @@ class PreferencesAfterBeingDefinedTest < ModelPreferenceTest
136
127
  def test_should_include_new_definitions_in_preference_definitions
137
128
  assert_equal e = {'notifications' => @definition}, User.preference_definitions
138
129
  end
139
-
140
- def test_should_include_default_value_in_default_preferences
141
- assert_equal e = {'notifications' => nil}, User.default_preferences
142
- end
143
130
  end
144
131
 
145
132
  class PreferencesByDefaultTest < ModelPreferenceTest
@@ -156,10 +143,6 @@ class PreferencesByDefaultTest < ModelPreferenceTest
156
143
  assert_nil @definition.default_value
157
144
  end
158
145
 
159
- def test_should_include_in_default_preferences
160
- assert_equal e = {'notifications' => nil}, User.default_preferences
161
- end
162
-
163
146
  def test_should_only_have_default_preferences
164
147
  assert_equal e = {'notifications' => nil}, @user.preferences
165
148
  end
@@ -203,10 +186,6 @@ class PreferencesWithCustomTypeTest < ModelPreferenceTest
203
186
  assert_nil @definition.default_value
204
187
  end
205
188
 
206
- def test_should_include_in_default_preferences
207
- assert_equal e = {'vehicle_id' => nil}, User.default_preferences
208
- end
209
-
210
189
  def test_should_only_have_default_preferences
211
190
  assert_equal e = {'vehicle_id' => nil}, @user.preferences
212
191
  end
@@ -226,10 +205,6 @@ class PreferencesWithCustomDefaultTest < ModelPreferenceTest
226
205
  assert_equal 'red', @definition.default_value
227
206
  end
228
207
 
229
- def test_should_include_in_default_preferences
230
- assert_equal e = {'color' => 'red'}, User.default_preferences
231
- end
232
-
233
208
  def test_should_only_have_default_preferences
234
209
  assert_equal e = {'color' => 'red'}, @user.preferences
235
210
  end
@@ -242,10 +217,6 @@ class PreferencesWithMultipleDefinitionsTest < ModelPreferenceTest
242
217
  @user = new_user
243
218
  end
244
219
 
245
- def test_should_include_all_in_default_preferences
246
- assert_equal e = {'notifications' => true, 'color' => 'red'}, User.default_preferences
247
- end
248
-
249
220
  def test_should_only_have_default_preferences
250
221
  assert_equal e = {'notifications' => true, 'color' => 'red'}, @user.preferences
251
222
  end
@@ -277,6 +248,11 @@ class PreferencesReaderTest < ModelPreferenceTest
277
248
  assert_equal true, @user.preferred(:notifications)
278
249
  end
279
250
 
251
+ def test_should_use_group_default_value_if_not_stored
252
+ User.preference :language, :string, :default => 'English', :group_defaults => {:chat => 'Latin'}
253
+ assert_equal 'English', @user.preferred(:language)
254
+ end
255
+
280
256
  def test_should_use_stored_value_if_stored
281
257
  create_preference(:owner => @user, :name => 'notifications', :value => false)
282
258
  assert_equal false, @user.preferred(:notifications)
@@ -320,10 +296,15 @@ class PreferencesGroupReaderTest < ModelPreferenceTest
320
296
  @user = create_user
321
297
  end
322
298
 
323
- def test_use_default_value_if_not_stored
299
+ def test_should_use_default_value_if_not_stored
324
300
  assert_equal true, @user.preferred(:notifications, :chat)
325
301
  end
326
302
 
303
+ def test_should_use_group_default_value_if_not_stored
304
+ User.preference :language, :string, :default => 'English', :group_defaults => {:chat => 'Latin'}
305
+ assert_equal 'Latin', @user.preferred(:language, :chat)
306
+ end
307
+
327
308
  def test_should_use_stored_value_if_stored
328
309
  create_preference(:owner => @user, :group_type => 'chat', :name => 'notifications', :value => false)
329
310
  assert_equal false, @user.preferred(:notifications, :chat)
@@ -956,7 +937,7 @@ end
956
937
  class PreferencesLookupTest < ModelPreferenceTest
957
938
  def setup
958
939
  User.preference :notifications, :boolean, :default => true
959
- User.preference :language, :string, :default => 'English'
940
+ User.preference :language, :string, :default => 'English', :group_defaults => {:chat => 'Latin'}
960
941
 
961
942
  @user = create_user
962
943
  end
@@ -982,9 +963,9 @@ class PreferencesLookupTest < ModelPreferenceTest
982
963
  end
983
964
 
984
965
  def test_should_use_unsaved_changes_over_stored_preferences
985
- create_preference(:owner => @user, :name => 'notifications', :value => false)
986
- @user.write_preference(:notifications, true)
987
- assert_equal e = {'notifications' => true, 'language' => 'English'}, @user.preferences
966
+ create_preference(:owner => @user, :name => 'notifications', :value => true)
967
+ @user.write_preference(:notifications, false)
968
+ assert_equal e = {'notifications' => false, 'language' => 'English'}, @user.preferences
988
969
  end
989
970
 
990
971
  def test_should_cache_results
@@ -1013,29 +994,29 @@ end
1013
994
  class PreferencesGroupLookupTest < ModelPreferenceTest
1014
995
  def setup
1015
996
  User.preference :notifications, :boolean, :default => true
1016
- User.preference :language, :string, :default => 'English'
997
+ User.preference :language, :string, :default => 'English', :group_defaults => {:chat => 'Latin'}
1017
998
 
1018
999
  @user = create_user
1019
1000
  end
1020
1001
 
1021
1002
  def test_should_only_have_defaults_if_nothing_customized
1022
- assert_equal e = {'notifications' => true, 'language' => 'English'}, @user.preferences(:chat)
1003
+ assert_equal e = {'notifications' => true, 'language' => 'Latin'}, @user.preferences(:chat)
1023
1004
  end
1024
1005
 
1025
1006
  def test_should_merge_defaults_with_unsaved_changes
1026
1007
  @user.write_preference(:notifications, false, :chat)
1027
- assert_equal e = {'notifications' => false, 'language' => 'English'}, @user.preferences(:chat)
1008
+ assert_equal e = {'notifications' => false, 'language' => 'Latin'}, @user.preferences(:chat)
1028
1009
  end
1029
1010
 
1030
1011
  def test_should_merge_defaults_with_saved_changes
1031
1012
  create_preference(:owner => @user, :group_type => 'chat', :name => 'notifications', :value => false)
1032
- assert_equal e = {'notifications' => false, 'language' => 'English'}, @user.preferences(:chat)
1013
+ assert_equal e = {'notifications' => false, 'language' => 'Latin'}, @user.preferences(:chat)
1033
1014
  end
1034
1015
 
1035
1016
  def test_should_merge_stored_preferences_with_unsaved_changes
1036
1017
  create_preference(:owner => @user, :group_type => 'chat', :name => 'notifications', :value => false)
1037
- @user.write_preference(:language, 'Latin', :chat)
1038
- assert_equal e = {'notifications' => false, 'language' => 'Latin'}, @user.preferences(:chat)
1018
+ @user.write_preference(:language, 'Spanish', :chat)
1019
+ assert_equal e = {'notifications' => false, 'language' => 'Spanish'}, @user.preferences(:chat)
1039
1020
  end
1040
1021
 
1041
1022
  def test_should_cache_results
@@ -1252,6 +1233,14 @@ class PreferencesWithScopeTest < ModelPreferenceTest
1252
1233
  assert_equal [@user], User.with_preferences(:chat => {:language => 'English'})
1253
1234
  end
1254
1235
 
1236
+ def test_should_find_with_customized_default_group_preference
1237
+ User.preference :country, :string, :default => 'US', :group_defaults => {:chat => 'UK'}
1238
+ @customized_user.preferred_country = 'US', :chat
1239
+ @customized_user.save!
1240
+
1241
+ assert_equal [@user], User.with_preferences(:chat => {:country => 'UK'})
1242
+ end
1243
+
1255
1244
  def test_should_find_with_multiple_default_group_preferences
1256
1245
  assert_equal [@user], User.with_preferences(:chat => {:notifications => nil, :language => 'English'})
1257
1246
  end
@@ -1328,6 +1317,14 @@ class PreferencesWithoutScopeTest < ModelPreferenceTest
1328
1317
  assert_equal [@user], User.without_preferences(:chat => {:language => 'Latin'})
1329
1318
  end
1330
1319
 
1320
+ def test_should_find_with_customized_default_group_preference
1321
+ User.preference :country, :string, :default => 'US', :group_defaults => {:chat => 'UK'}
1322
+ @customized_user.preferred_country = 'US', :chat
1323
+ @customized_user.save!
1324
+
1325
+ assert_equal [@user], User.without_preferences(:chat => {:country => 'US'})
1326
+ end
1327
+
1331
1328
  def test_should_find_with_multiple_default_group_preferences
1332
1329
  assert_equal [@user], User.without_preferences(:chat => {:language => 'Latin', :notifications => false})
1333
1330
  end
@@ -42,6 +42,24 @@ class PreferenceDefinitionWithDefaultValueTest < ActiveSupport::TestCase
42
42
  end
43
43
  end
44
44
 
45
+ class PreferenceDefinitionWithGroupDefaultsTest < ActiveSupport::TestCase
46
+ def setup
47
+ @definition = Preferences::PreferenceDefinition.new(:notifications, :boolean, :default => 1, :group_defaults => {:chat => 0})
48
+ end
49
+
50
+ def test_should_use_default_for_default_group
51
+ assert_equal true, @definition.default_value
52
+ end
53
+
54
+ def test_should_use_default_for_unknown_group
55
+ assert_equal true, @definition.default_value('email')
56
+ end
57
+
58
+ def test_should_use_group_default_for_known_group
59
+ assert_equal false, @definition.default_value('chat')
60
+ end
61
+ end
62
+
45
63
  class PreferenceDefinitionWithStringifiedTypeTest < ActiveSupport::TestCase
46
64
  def setup
47
65
  @definition = Preferences::PreferenceDefinition.new(:notifications, 'any')
@@ -157,7 +157,6 @@ class PreferenceAfterBeingCreatedTest < ActiveSupport::TestCase
157
157
 
158
158
  def teardown
159
159
  User.preference_definitions.delete('notifications')
160
- User.default_preferences.delete('notifications')
161
160
  end
162
161
  end
163
162
 
@@ -210,7 +209,6 @@ class PreferenceWithBooleanTypeTest < ActiveSupport::TestCase
210
209
 
211
210
  def teardown
212
211
  User.preference_definitions.delete('notifications')
213
- User.default_preferences.delete('notifications')
214
212
  end
215
213
  end
216
214
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: preferences
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Pfeifer