preferences 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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