preferences 0.1.5 → 0.2.0

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,9 @@
1
1
  == master
2
2
 
3
+ == 0.2.0 / 2008-12-14
4
+
5
+ * Remove the PluginAWeek namespace
6
+
3
7
  == 0.1.5 / 2008-11-16
4
8
 
5
9
  * Add all prefers/preferred accessors for preferences to be analogous to ActiveRecord column accessors
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/contrib/sshpublisher'
5
5
 
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = 'preferences'
8
- s.version = '0.1.5'
8
+ s.version = '0.2.0'
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.summary = 'Adds support for easily creating custom preferences for models'
11
11
 
@@ -1,44 +1,42 @@
1
- module PluginAWeek #:nodoc:
2
- module Preferences
3
- # Represents the definition of a preference for a particular model
4
- class PreferenceDefinition
5
- def initialize(attribute, *args) #:nodoc:
6
- options = args.extract_options!
7
- options.assert_valid_keys(:default)
8
-
9
- @type = args.first ? args.first.to_s : 'boolean'
10
-
11
- # Create a column that will be responsible for typecasting
12
- @column = ActiveRecord::ConnectionAdapters::Column.new(attribute.to_s, options[:default], @type == 'any' ? nil : @type)
13
- end
14
-
15
- # The attribute which is being preferenced
16
- def attribute
17
- @column.name
18
- end
19
-
20
- # The default value to use for the preference in case none have been
21
- # previously defined
22
- def default_value
23
- @column.default
24
- end
1
+ module Preferences
2
+ # Represents the definition of a preference for a particular model
3
+ class PreferenceDefinition
4
+ def initialize(attribute, *args) #:nodoc:
5
+ options = args.extract_options!
6
+ options.assert_valid_keys(:default)
25
7
 
26
- # Typecasts the value based on the type of preference that was defined.
27
- # This uses ActiveRecord's typecast functionality so the same rules for
28
- # typecasting a model's columns apply here.
29
- def type_cast(value)
30
- @type == 'any' ? value : @column.type_cast(value)
31
- end
8
+ @type = args.first ? args.first.to_s : 'boolean'
32
9
 
33
- # Typecasts the value to true/false depending on the type of preference
34
- def query(value)
35
- if !(value = type_cast(value))
36
- false
37
- elsif @column.number?
38
- !value.zero?
39
- else
40
- !value.blank?
41
- end
10
+ # Create a column that will be responsible for typecasting
11
+ @column = ActiveRecord::ConnectionAdapters::Column.new(attribute.to_s, options[:default], @type == 'any' ? nil : @type)
12
+ end
13
+
14
+ # The attribute which is being preferenced
15
+ def attribute
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?
42
40
  end
43
41
  end
44
42
  end
data/lib/preferences.rb CHANGED
@@ -1,336 +1,334 @@
1
1
  require 'preferences/preference_definition'
2
2
 
3
- module PluginAWeek #:nodoc:
4
- # Adds support for defining preferences on ActiveRecord models.
5
- #
6
- # == Saving preferences
7
- #
8
- # Preferences are not automatically saved when they are set. You must save
9
- # the record that the preferences were set on.
10
- #
11
- # For example,
12
- #
13
- # class User < ActiveRecord::Base
14
- # preference :notifications
15
- # end
16
- #
17
- # u = User.new(:login => 'admin', :prefers_notifications => false)
18
- # u.save!
19
- #
20
- # u = User.find_by_login('admin')
21
- # u.attributes = {:prefers_notifications => true}
22
- # u.save!
23
- #
24
- # == Validations
25
- #
26
- # Since the generated accessors for a preference allow the preference to be
27
- # treated just like regular ActiveRecord column attributes, they can also be
28
- # validated against in the same way. For example,
29
- #
30
- # class User < ActiveRecord::Base
31
- # preference :color, :string
32
- #
33
- # validates_presence_of :preferred_color
34
- # validates_inclusion_of :preferred_color, :in => %w(red green blue)
35
- # end
36
- #
37
- # u = User.new
38
- # u.valid? # => false
39
- # u.errors.on(:preferred_color) # => "can't be blank"
40
- #
41
- # u.preferred_color = 'white'
42
- # u.valid? # => false
43
- # u.errors.on(:preferred_color) # => "is not included in the list"
44
- #
45
- # u.preferred_color = 'red'
46
- # u.valid? # => true
47
- module Preferences
48
- module MacroMethods
49
- # Defines a new preference for all records in the model. By default,
50
- # preferences are assumed to have a boolean data type, so all values will
51
- # be typecasted to true/false based on ActiveRecord rules.
52
- #
53
- # Configuration options:
54
- # * +default+ - The default value for the preference. Default is nil.
55
- #
56
- # == Examples
57
- #
58
- # The example below shows the various ways to define a preference for a
59
- # particular model.
60
- #
61
- # class User < ActiveRecord::Base
62
- # preference :notifications, :default => false
63
- # preference :color, :string, :default => 'red'
64
- # preference :favorite_number, :integer
65
- # preference :data, :any # Allows any data type to be stored
66
- # end
67
- #
68
- # All preferences are also inherited by subclasses.
69
- #
70
- # == Associations
71
- #
72
- # After the first preference is defined, the following associations are
73
- # created for the model:
74
- # * +stored_preferences+ - A collection of all the custom preferences specified for a record. This will not include default preferences unless they have been explicitly set.
75
- #
76
- # == Generated accessors
77
- #
78
- # In addition to calling <tt>prefers?</tt> and +preferred+ on a record, you
79
- # can also use the shortcut accessor methods that are generated when a
80
- # preference is defined. For example,
81
- #
82
- # class User < ActiveRecord::Base
83
- # preference :notifications
84
- # end
85
- #
86
- # ...generates the following methods:
87
- # * <tt>prefers_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.prefers?(:notifications)</tt>
88
- # * <tt>prefers_notifications</tt> - The actual value stored, i.e. <tt>record.prefers(:notifications)</tt>
89
- # * <tt>prefers_notifications=(value)</tt> - Sets a new value, i.e. <tt>record.set_preference(:notifications, value)</tt>
90
- # * <tt>preferred_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.preferred?(:notifications)</tt>
91
- # * <tt>preferred_notifications</tt> - The actual value stored, i.e. <tt>record.preferred(:notifications)</tt>
92
- # * <tt>preferred_notifications=(value)</tt> - Sets a new value, i.e. <tt>record.set_preference(:notifications, value)</tt>
93
- #
94
- # Notice that there are two tenses used depending on the context of the
95
- # preference. Conventionally, <tt>prefers_notifications?</tt> is better
96
- # for accessing boolean preferences, while +preferred_color+ is better for
97
- # accessing non-boolean preferences.
98
- #
99
- # Example:
100
- #
101
- # user = User.find(:first)
102
- # user.prefers_notifications? # => false
103
- # user.prefers_notifications # => false
104
- # user.preferred_color? # => true
105
- # user.preferred_color # => 'red'
106
- # user.preferred_color = 'blue' # => 'blue'
107
- #
108
- # user.prefers_notifications = true
109
- #
110
- # car = Car.find(:first)
111
- # user.preferred_color = 'red', car # => 'red'
112
- # user.preferred_color(car) # => 'red'
113
- # user.preferred_color?(car) # => true
114
- #
115
- # user.save! # => true
116
- def preference(attribute, *args)
117
- unless included_modules.include?(InstanceMethods)
118
- class_inheritable_hash :preference_definitions
119
- self.preference_definitions = {}
120
-
121
- class_inheritable_hash :default_preferences
122
- self.default_preferences = {}
123
-
124
- has_many :stored_preferences,
125
- :as => :owner,
126
- :class_name => 'Preference'
127
-
128
- after_save :update_preferences
129
-
130
- include PluginAWeek::Preferences::InstanceMethods
131
- end
3
+ # Adds support for defining preferences on ActiveRecord models.
4
+ #
5
+ # == Saving preferences
6
+ #
7
+ # Preferences are not automatically saved when they are set. You must save
8
+ # the record that the preferences were set on.
9
+ #
10
+ # For example,
11
+ #
12
+ # class User < ActiveRecord::Base
13
+ # preference :notifications
14
+ # end
15
+ #
16
+ # u = User.new(:login => 'admin', :prefers_notifications => false)
17
+ # u.save!
18
+ #
19
+ # u = User.find_by_login('admin')
20
+ # u.attributes = {:prefers_notifications => true}
21
+ # u.save!
22
+ #
23
+ # == Validations
24
+ #
25
+ # Since the generated accessors for a preference allow the preference to be
26
+ # treated just like regular ActiveRecord column attributes, they can also be
27
+ # validated against in the same way. For example,
28
+ #
29
+ # class User < ActiveRecord::Base
30
+ # preference :color, :string
31
+ #
32
+ # validates_presence_of :preferred_color
33
+ # validates_inclusion_of :preferred_color, :in => %w(red green blue)
34
+ # end
35
+ #
36
+ # u = User.new
37
+ # u.valid? # => false
38
+ # u.errors.on(:preferred_color) # => "can't be blank"
39
+ #
40
+ # u.preferred_color = 'white'
41
+ # u.valid? # => false
42
+ # u.errors.on(:preferred_color) # => "is not included in the list"
43
+ #
44
+ # u.preferred_color = 'red'
45
+ # u.valid? # => true
46
+ module Preferences
47
+ module MacroMethods
48
+ # Defines a new preference for all records in the model. By default,
49
+ # preferences are assumed to have a boolean data type, so all values will
50
+ # be typecasted to true/false based on ActiveRecord rules.
51
+ #
52
+ # Configuration options:
53
+ # * +default+ - The default value for the preference. Default is nil.
54
+ #
55
+ # == Examples
56
+ #
57
+ # The example below shows the various ways to define a preference for a
58
+ # particular model.
59
+ #
60
+ # class User < ActiveRecord::Base
61
+ # preference :notifications, :default => false
62
+ # preference :color, :string, :default => 'red'
63
+ # preference :favorite_number, :integer
64
+ # preference :data, :any # Allows any data type to be stored
65
+ # end
66
+ #
67
+ # All preferences are also inherited by subclasses.
68
+ #
69
+ # == Associations
70
+ #
71
+ # After the first preference is defined, the following associations are
72
+ # created for the model:
73
+ # * +stored_preferences+ - A collection of all the custom preferences specified for a record. This will not include default preferences unless they have been explicitly set.
74
+ #
75
+ # == Generated accessors
76
+ #
77
+ # In addition to calling <tt>prefers?</tt> and +preferred+ on a record, you
78
+ # can also use the shortcut accessor methods that are generated when a
79
+ # preference is defined. For example,
80
+ #
81
+ # class User < ActiveRecord::Base
82
+ # preference :notifications
83
+ # end
84
+ #
85
+ # ...generates the following methods:
86
+ # * <tt>prefers_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.prefers?(:notifications)</tt>
87
+ # * <tt>prefers_notifications</tt> - The actual value stored, i.e. <tt>record.prefers(:notifications)</tt>
88
+ # * <tt>prefers_notifications=(value)</tt> - Sets a new value, i.e. <tt>record.set_preference(:notifications, value)</tt>
89
+ # * <tt>preferred_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.preferred?(:notifications)</tt>
90
+ # * <tt>preferred_notifications</tt> - The actual value stored, i.e. <tt>record.preferred(:notifications)</tt>
91
+ # * <tt>preferred_notifications=(value)</tt> - Sets a new value, i.e. <tt>record.set_preference(:notifications, value)</tt>
92
+ #
93
+ # Notice that there are two tenses used depending on the context of the
94
+ # preference. Conventionally, <tt>prefers_notifications?</tt> is better
95
+ # for accessing boolean preferences, while +preferred_color+ is better for
96
+ # accessing non-boolean preferences.
97
+ #
98
+ # Example:
99
+ #
100
+ # user = User.find(:first)
101
+ # user.prefers_notifications? # => false
102
+ # user.prefers_notifications # => false
103
+ # user.preferred_color? # => true
104
+ # user.preferred_color # => 'red'
105
+ # user.preferred_color = 'blue' # => 'blue'
106
+ #
107
+ # user.prefers_notifications = true
108
+ #
109
+ # car = Car.find(:first)
110
+ # user.preferred_color = 'red', car # => 'red'
111
+ # user.preferred_color(car) # => 'red'
112
+ # user.preferred_color?(car) # => true
113
+ #
114
+ # user.save! # => true
115
+ def preference(attribute, *args)
116
+ unless included_modules.include?(InstanceMethods)
117
+ class_inheritable_hash :preference_definitions
118
+ self.preference_definitions = {}
132
119
 
133
- # Create the definition
134
- attribute = attribute.to_s
135
- definition = PreferenceDefinition.new(attribute, *args)
136
- self.preference_definitions[attribute] = definition
137
- self.default_preferences[attribute] = definition.default_value
120
+ class_inheritable_hash :default_preferences
121
+ self.default_preferences = {}
138
122
 
139
- # Create short-hand accessor methods, making sure that the attribute
140
- # is method-safe in terms of what characters are allowed
141
- attribute = attribute.gsub(/[^A-Za-z0-9_-]/, '').underscore
123
+ has_many :stored_preferences,
124
+ :as => :owner,
125
+ :class_name => 'Preference'
142
126
 
143
- # Query lookup
144
- define_method("preferred_#{attribute}?") do |*group|
145
- preferred?(attribute, group.first)
146
- end
147
- alias_method "prefers_#{attribute}?", "preferred_#{attribute}?"
127
+ after_save :update_preferences
148
128
 
149
- # Reader
150
- define_method("preferred_#{attribute}") do |*group|
151
- preferred(attribute, group.first)
152
- end
153
- alias_method "prefers_#{attribute}", "preferred_#{attribute}"
154
-
155
- # Writer
156
- define_method("preferred_#{attribute}=") do |*args|
157
- set_preference(*([attribute] + [args].flatten))
158
- end
159
- alias_method "prefers_#{attribute}=", "preferred_#{attribute}="
160
-
161
- definition
129
+ include Preferences::InstanceMethods
162
130
  end
163
- end
164
-
165
- module InstanceMethods
166
- def self.included(base) #:nodoc:
167
- base.class_eval do
168
- alias_method :prefs, :preferences
169
- end
131
+
132
+ # Create the definition
133
+ attribute = attribute.to_s
134
+ definition = PreferenceDefinition.new(attribute, *args)
135
+ self.preference_definitions[attribute] = definition
136
+ self.default_preferences[attribute] = definition.default_value
137
+
138
+ # Create short-hand accessor methods, making sure that the attribute
139
+ # is method-safe in terms of what characters are allowed
140
+ attribute = attribute.gsub(/[^A-Za-z0-9_-]/, '').underscore
141
+
142
+ # Query lookup
143
+ define_method("preferred_#{attribute}?") do |*group|
144
+ preferred?(attribute, group.first)
170
145
  end
146
+ alias_method "prefers_#{attribute}?", "preferred_#{attribute}?"
171
147
 
172
- # Finds all preferences, including defaults, for the current record. If
173
- # any custom group preferences have been stored, then this will include
174
- # all default preferences within that particular group.
175
- #
176
- # == Examples
177
- #
178
- # A user with no stored values:
179
- # user = User.find(:first)
180
- # user.preferences
181
- # => {"language"=>"English", "color"=>nil}
182
- #
183
- # A user with stored values for a particular group:
184
- # user.preferred_color = 'red', 'cars'
185
- # user.preferences
186
- # => {"language"=>"English", "color"=>nil, "cars"=>{"language=>"English", "color"=>"red"}}
187
- #
188
- # Getting preference values *just* for the owning record (i.e. excluding groups):
189
- # user.preferences(nil)
190
- # => {"language"=>"English", "color"=>nil}
191
- #
192
- # Getting preference values for a particular group:
193
- # user.preferences('cars')
194
- # => {"language"=>"English", "color"=>"red"}
195
- def preferences(*args)
196
- if args.empty?
197
- group = nil
198
- conditions = {}
199
- else
200
- group = args.first
201
-
202
- # Split the actual group into its different parts (id/type) in case
203
- # a record is passed in
204
- group_id, group_type = Preference.split_group(group)
205
- conditions = {:group_id => group_id, :group_type => group_type}
206
- end
207
-
208
- # Find all of the stored preferences
209
- stored_preferences = self.stored_preferences.find(:all, :conditions => conditions)
210
-
211
- # Hashify attribute -> value or group -> attribute -> value
212
- stored_preferences.inject(self.class.default_preferences.dup) do |all_preferences, preference|
213
- if !group && (preference_group = preference.group)
214
- preferences = all_preferences[preference_group] ||= self.class.default_preferences.dup
215
- else
216
- preferences = all_preferences
217
- end
218
-
219
- preferences[preference.attribute] = preference.value
220
- all_preferences
221
- end
148
+ # Reader
149
+ define_method("preferred_#{attribute}") do |*group|
150
+ preferred(attribute, group.first)
222
151
  end
152
+ alias_method "prefers_#{attribute}", "preferred_#{attribute}"
223
153
 
224
- # Queries whether or not a value is present for the given attribute. This
225
- # is dependent on how the value is type-casted.
226
- #
227
- # == Examples
228
- #
229
- # class User < ActiveRecord::Base
230
- # preference :color, :string, :default => 'red'
231
- # end
232
- #
233
- # user = User.create
234
- # user.preferred(:color) # => "red"
235
- # user.preferred?(:color) # => true
236
- # user.preferred?(:color, 'cars') # => true
237
- # user.preferred?(:color, Car.first) # => true
238
- #
239
- # user.set_preference(:color, nil)
240
- # user.preferred(:color) # => nil
241
- # user.preferred?(:color) # => false
242
- def preferred?(attribute, group = nil)
243
- attribute = attribute.to_s
244
-
245
- value = preferred(attribute, group)
246
- preference_definitions[attribute].query(value)
154
+ # Writer
155
+ define_method("preferred_#{attribute}=") do |*args|
156
+ set_preference(*([attribute] + [args].flatten))
247
157
  end
248
- alias_method :prefers?, :preferred?
158
+ alias_method "prefers_#{attribute}=", "preferred_#{attribute}="
249
159
 
250
- # Gets the actual value stored for the given attribute, or the default
251
- # value if nothing is present.
252
- #
253
- # == Examples
254
- #
255
- # class User < ActiveRecord::Base
256
- # preference :color, :string, :default => 'red'
257
- # end
258
- #
259
- # user = User.create
260
- # user.preferred(:color) # => "red"
261
- # user.preferred(:color, 'cars') # => "red"
262
- # user.preferred(:color, Car.first) # => "red"
263
- #
264
- # user.set_preference(:color, 'blue')
265
- # user.preferred(:color) # => "blue"
266
- def preferred(attribute, group = nil)
267
- attribute = attribute.to_s
160
+ definition
161
+ end
162
+ end
163
+
164
+ module InstanceMethods
165
+ def self.included(base) #:nodoc:
166
+ base.class_eval do
167
+ alias_method :prefs, :preferences
168
+ end
169
+ end
170
+
171
+ # Finds all preferences, including defaults, for the current record. If
172
+ # any custom group preferences have been stored, then this will include
173
+ # all default preferences within that particular group.
174
+ #
175
+ # == Examples
176
+ #
177
+ # A user with no stored values:
178
+ # user = User.find(:first)
179
+ # user.preferences
180
+ # => {"language"=>"English", "color"=>nil}
181
+ #
182
+ # A user with stored values for a particular group:
183
+ # user.preferred_color = 'red', 'cars'
184
+ # user.preferences
185
+ # => {"language"=>"English", "color"=>nil, "cars"=>{"language=>"English", "color"=>"red"}}
186
+ #
187
+ # Getting preference values *just* for the owning record (i.e. excluding groups):
188
+ # user.preferences(nil)
189
+ # => {"language"=>"English", "color"=>nil}
190
+ #
191
+ # Getting preference values for a particular group:
192
+ # user.preferences('cars')
193
+ # => {"language"=>"English", "color"=>"red"}
194
+ def preferences(*args)
195
+ if args.empty?
196
+ group = nil
197
+ conditions = {}
198
+ else
199
+ group = args.first
268
200
 
269
- if @preference_values && @preference_values[attribute] && @preference_values[attribute].include?(group)
270
- # Value for this attribute/group has been written, but not saved yet:
271
- # grab from the pending values
272
- value = @preference_values[attribute][group]
201
+ # Split the actual group into its different parts (id/type) in case
202
+ # a record is passed in
203
+ group_id, group_type = Preference.split_group(group)
204
+ conditions = {:group_id => group_id, :group_type => group_type}
205
+ end
206
+
207
+ # Find all of the stored preferences
208
+ stored_preferences = self.stored_preferences.find(:all, :conditions => conditions)
209
+
210
+ # Hashify attribute -> value or group -> attribute -> value
211
+ stored_preferences.inject(self.class.default_preferences.dup) do |all_preferences, preference|
212
+ if !group && (preference_group = preference.group)
213
+ preferences = all_preferences[preference_group] ||= self.class.default_preferences.dup
273
214
  else
274
- # Split the group being filtered
275
- group_id, group_type = Preference.split_group(group)
276
-
277
- # Grab the first preference; if it doesn't exist, use the default value
278
- preference = stored_preferences.find(:first, :conditions => {:attribute => attribute, :group_id => group_id, :group_type => group_type})
279
- value = preference ? preference.value : preference_definitions[attribute].default_value
215
+ preferences = all_preferences
280
216
  end
281
217
 
282
- value
218
+ preferences[preference.attribute] = preference.value
219
+ all_preferences
283
220
  end
284
- alias_method :prefers, :preferred
221
+ end
222
+
223
+ # Queries whether or not a value is present for the given attribute. This
224
+ # is dependent on how the value is type-casted.
225
+ #
226
+ # == Examples
227
+ #
228
+ # class User < ActiveRecord::Base
229
+ # preference :color, :string, :default => 'red'
230
+ # end
231
+ #
232
+ # user = User.create
233
+ # user.preferred(:color) # => "red"
234
+ # user.preferred?(:color) # => true
235
+ # user.preferred?(:color, 'cars') # => true
236
+ # user.preferred?(:color, Car.first) # => true
237
+ #
238
+ # user.set_preference(:color, nil)
239
+ # user.preferred(:color) # => nil
240
+ # user.preferred?(:color) # => false
241
+ def preferred?(attribute, group = nil)
242
+ attribute = attribute.to_s
285
243
 
286
- # Sets a new value for the given attribute. The actual Preference record
287
- # is *not* created until this record is saved. In this way, preferences
288
- # act *exactly* the same as attributes. They can be written to and
289
- # validated against, but won't actually be written to the database until
290
- # the record is saved.
291
- #
292
- # == Examples
293
- #
294
- # user = User.find(:first)
295
- # user.set_preference(:color, 'red') # => "red"
296
- # user.save!
297
- #
298
- # user.set_preference(:color, 'blue', Car.first) # => "blue"
299
- # user.save!
300
- def set_preference(attribute, value, group = nil)
301
- attribute = attribute.to_s
302
-
303
- @preference_values ||= {}
304
- @preference_values[attribute] ||= {}
305
- @preference_values[attribute][group] = value
244
+ value = preferred(attribute, group)
245
+ preference_definitions[attribute].query(value)
246
+ end
247
+ alias_method :prefers?, :preferred?
248
+
249
+ # Gets the actual value stored for the given attribute, or the default
250
+ # value if nothing is present.
251
+ #
252
+ # == Examples
253
+ #
254
+ # class User < ActiveRecord::Base
255
+ # preference :color, :string, :default => 'red'
256
+ # end
257
+ #
258
+ # user = User.create
259
+ # user.preferred(:color) # => "red"
260
+ # user.preferred(:color, 'cars') # => "red"
261
+ # user.preferred(:color, Car.first) # => "red"
262
+ #
263
+ # user.set_preference(:color, 'blue')
264
+ # user.preferred(:color) # => "blue"
265
+ def preferred(attribute, group = nil)
266
+ attribute = attribute.to_s
267
+
268
+ if @preference_values && @preference_values[attribute] && @preference_values[attribute].include?(group)
269
+ # Value for this attribute/group has been written, but not saved yet:
270
+ # grab from the pending values
271
+ value = @preference_values[attribute][group]
272
+ else
273
+ # Split the group being filtered
274
+ group_id, group_type = Preference.split_group(group)
306
275
 
307
- value
276
+ # Grab the first preference; if it doesn't exist, use the default value
277
+ preference = stored_preferences.find(:first, :conditions => {:attribute => attribute, :group_id => group_id, :group_type => group_type})
278
+ value = preference ? preference.value : preference_definitions[attribute].default_value
308
279
  end
309
280
 
310
- private
311
- # Updates any preferences that have been changed/added since the record
312
- # was last saved
313
- def update_preferences
314
- if @preference_values
315
- @preference_values.each do |attribute, grouped_records|
316
- grouped_records.each do |group, value|
317
- group_id, group_type = Preference.split_group(group)
318
- attributes = {:attribute => attribute, :group_id => group_id, :group_type => group_type}
319
-
320
- # Find an existing preference or build a new one
321
- preference = stored_preferences.find(:first, :conditions => attributes) || stored_preferences.build(attributes)
322
- preference.value = value
323
- preference.save!
324
- end
281
+ value
282
+ end
283
+ alias_method :prefers, :preferred
284
+
285
+ # Sets a new value for the given attribute. The actual Preference record
286
+ # is *not* created until this record is saved. In this way, preferences
287
+ # act *exactly* the same as attributes. They can be written to and
288
+ # validated against, but won't actually be written to the database until
289
+ # the record is saved.
290
+ #
291
+ # == Examples
292
+ #
293
+ # user = User.find(:first)
294
+ # user.set_preference(:color, 'red') # => "red"
295
+ # user.save!
296
+ #
297
+ # user.set_preference(:color, 'blue', Car.first) # => "blue"
298
+ # user.save!
299
+ def set_preference(attribute, value, group = nil)
300
+ attribute = attribute.to_s
301
+
302
+ @preference_values ||= {}
303
+ @preference_values[attribute] ||= {}
304
+ @preference_values[attribute][group] = value
305
+
306
+ value
307
+ end
308
+
309
+ private
310
+ # Updates any preferences that have been changed/added since the record
311
+ # was last saved
312
+ def update_preferences
313
+ if @preference_values
314
+ @preference_values.each do |attribute, grouped_records|
315
+ grouped_records.each do |group, value|
316
+ group_id, group_type = Preference.split_group(group)
317
+ attributes = {:attribute => attribute, :group_id => group_id, :group_type => group_type}
318
+
319
+ # Find an existing preference or build a new one
320
+ preference = stored_preferences.find(:first, :conditions => attributes) || stored_preferences.build(attributes)
321
+ preference.value = value
322
+ preference.save!
325
323
  end
326
-
327
- @preference_values = nil
328
324
  end
325
+
326
+ @preference_values = nil
329
327
  end
330
- end
328
+ end
331
329
  end
332
330
  end
333
331
 
334
332
  ActiveRecord::Base.class_eval do
335
- extend PluginAWeek::Preferences::MacroMethods
333
+ extend Preferences::MacroMethods
336
334
  end
@@ -2,7 +2,7 @@ require "#{File.dirname(__FILE__)}/../test_helper"
2
2
 
3
3
  class PreferenceDefinitionByDefaultTest < Test::Unit::TestCase
4
4
  def setup
5
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications)
5
+ @definition = Preferences::PreferenceDefinition.new(:notifications)
6
6
  end
7
7
 
8
8
  def test_should_have_an_attribute
@@ -24,13 +24,13 @@ end
24
24
 
25
25
  class PreferenceDefinitionTest < Test::Unit::TestCase
26
26
  def test_should_raise_exception_if_invalid_option_specified
27
- assert_raise(ArgumentError) {PluginAWeek::Preferences::PreferenceDefinition.new(:notifications, :invalid => true)}
27
+ assert_raise(ArgumentError) {Preferences::PreferenceDefinition.new(:notifications, :invalid => true)}
28
28
  end
29
29
  end
30
30
 
31
31
  class PreferenceDefinitionWithDefaultValueTest < Test::Unit::TestCase
32
32
  def setup
33
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications, :boolean, :default => 1)
33
+ @definition = Preferences::PreferenceDefinition.new(:notifications, :boolean, :default => 1)
34
34
  end
35
35
 
36
36
  def test_should_type_cast_default_values
@@ -40,7 +40,7 @@ end
40
40
 
41
41
  class PreferenceDefinitionWithAnyTypeTest < Test::Unit::TestCase
42
42
  def setup
43
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications, :any)
43
+ @definition = Preferences::PreferenceDefinition.new(:notifications, :any)
44
44
  end
45
45
 
46
46
  def test_should_not_type_cast
@@ -76,7 +76,7 @@ end
76
76
 
77
77
  class PreferenceDefinitionWithBooleanTypeTest < Test::Unit::TestCase
78
78
  def setup
79
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications)
79
+ @definition = Preferences::PreferenceDefinition.new(:notifications)
80
80
  end
81
81
 
82
82
  def test_should_not_type_cast_if_value_is_nil
@@ -122,7 +122,7 @@ end
122
122
 
123
123
  class PreferenceDefinitionWithNumericTypeTest < Test::Unit::TestCase
124
124
  def setup
125
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications, :integer)
125
+ @definition = Preferences::PreferenceDefinition.new(:notifications, :integer)
126
126
  end
127
127
 
128
128
  def test_should_type_cast_true_to_integer
@@ -152,7 +152,7 @@ end
152
152
 
153
153
  class PreferenceDefinitionWithStringTypeTest < Test::Unit::TestCase
154
154
  def setup
155
- @definition = PluginAWeek::Preferences::PreferenceDefinition.new(:notifications, :string)
155
+ @definition = Preferences::PreferenceDefinition.new(:notifications, :string)
156
156
  end
157
157
 
158
158
  def test_should_type_cast_integers_to_strings
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.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Pfeifer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-04 00:00:00 -05:00
12
+ date: 2008-12-14 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15