ee_preferences 0.4.3

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.
@@ -0,0 +1,616 @@
1
+ require 'preferences/preference_definition'
2
+
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 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
+ # * <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.
57
+ #
58
+ # == Examples
59
+ #
60
+ # The example below shows the various ways to define a preference for a
61
+ # particular model.
62
+ #
63
+ # class User < ActiveRecord::Base
64
+ # preference :notifications, :default => false
65
+ # preference :color, :string, :default => 'red', :group_defaults => {:car => 'black'}
66
+ # preference :favorite_number, :integer
67
+ # preference :data, :any # Allows any data type to be stored
68
+ # end
69
+ #
70
+ # All preferences are also inherited by subclasses.
71
+ #
72
+ # == Associations
73
+ #
74
+ # After the first preference is defined, the following associations are
75
+ # created for the model:
76
+ # * +stored_preferences+ - A collection of all the custom preferences
77
+ # specified for a record. This will not include default preferences
78
+ # unless they have been explicitly set.
79
+ #
80
+ # == Named scopes
81
+ #
82
+ # In addition to the above associations, the following named scopes get
83
+ # generated for the model:
84
+ # * +with_preferences+ - Finds all records with a given set of preferences
85
+ # * +without_preferences+ - Finds all records without a given set of preferences
86
+ #
87
+ # In addition to utilizing preferences stored in the database, each of the
88
+ # above scopes also take into account the defaults that have been defined
89
+ # for each preference.
90
+ #
91
+ # Example:
92
+ #
93
+ # User.with_preferences(:notifications => true)
94
+ # User.with_preferences(:notifications => true, :color => 'blue')
95
+ #
96
+ # # Searching with group preferences
97
+ # car = Car.find(:first)
98
+ # User.with_preferences(car => {:color => 'blue'})
99
+ # User.with_preferences(:notifications => true, car => {:color => 'blue'})
100
+ #
101
+ # == Generated accessors
102
+ #
103
+ # In addition to calling <tt>prefers?</tt> and +preferred+ on a record,
104
+ # you can also use the shortcut accessor methods that are generated when a
105
+ # preference is defined. For example,
106
+ #
107
+ # class User < ActiveRecord::Base
108
+ # preference :notifications
109
+ # end
110
+ #
111
+ # ...generates the following methods:
112
+ # * <tt>prefers_notifications?</tt> - Whether a value has been specified, i.e. <tt>record.prefers?(:notifications)</tt>
113
+ # * <tt>prefers_notifications</tt> - The actual value stored, i.e. <tt>record.prefers(:notifications)</tt>
114
+ # * <tt>prefers_notifications=(value)</tt> - Sets a new value, i.e. <tt>record.write_preference(:notifications, value)</tt>
115
+ # * <tt>prefers_notifications_changed?</tt> - Whether the preference has unsaved changes
116
+ # * <tt>prefers_notifications_was</tt> - The last saved value for the preference
117
+ # * <tt>prefers_notifications_change</tt> - A list of [original_value, new_value] if the preference has changed
118
+ # * <tt>prefers_notifications_will_change!</tt> - Forces the preference to get updated
119
+ # * <tt>reset_prefers_notifications!</tt> - Reverts any unsaved changes to the preference
120
+ #
121
+ # ...and the equivalent +preferred+ methods:
122
+ # * <tt>preferred_notifications?</tt>
123
+ # * <tt>preferred_notifications</tt>
124
+ # * <tt>preferred_notifications=(value)</tt>
125
+ # * <tt>preferred_notifications_changed?</tt>
126
+ # * <tt>preferred_notifications_was</tt>
127
+ # * <tt>preferred_notifications_change</tt>
128
+ # * <tt>preferred_notifications_will_change!</tt>
129
+ # * <tt>reset_preferred_notifications!</tt>
130
+ #
131
+ # Notice that there are two tenses used depending on the context of the
132
+ # preference. Conventionally, <tt>prefers_notifications?</tt> is better
133
+ # for accessing boolean preferences, while +preferred_color+ is better for
134
+ # accessing non-boolean preferences.
135
+ #
136
+ # Example:
137
+ #
138
+ # user = User.find(:first)
139
+ # user.prefers_notifications? # => false
140
+ # user.prefers_notifications # => false
141
+ # user.preferred_color? # => true
142
+ # user.preferred_color # => 'red'
143
+ # user.preferred_color = 'blue' # => 'blue'
144
+ #
145
+ # user.prefers_notifications = true
146
+ #
147
+ # car = Car.find(:first)
148
+ # user.preferred_color = 'red', car # => 'red'
149
+ # user.preferred_color(car) # => 'red'
150
+ # user.preferred_color?(car) # => true
151
+ #
152
+ # user.save! # => true
153
+ def preference(name, *args)
154
+ unless included_modules.include?(InstanceMethods)
155
+ class_inheritable_hash :preference_definitions
156
+ self.preference_definitions = {}
157
+
158
+ has_many :stored_preferences, :as => :owner, :class_name => 'Preference'
159
+
160
+ after_save :update_preferences
161
+ before_destroy :destroy_preferences
162
+
163
+ # Named scopes
164
+ scope :with_preferences, lambda {|preferences| build_preference_scope(preferences)}
165
+ scope :without_preferences, lambda {|preferences| build_preference_scope(preferences, true)}
166
+
167
+ extend Preferences::ClassMethods
168
+ include Preferences::InstanceMethods
169
+ end
170
+
171
+ # Create the definition
172
+ name = name.to_s
173
+ definition = PreferenceDefinition.new(name, *args)
174
+ self.preference_definitions[name] = definition
175
+
176
+ # Create short-hand accessor methods, making sure that the name
177
+ # is method-safe in terms of what characters are allowed
178
+ name = name.gsub(/[^A-Za-z0-9_-]/, '').underscore
179
+
180
+ # Query lookup
181
+ define_method("preferred_#{name}?") do |*group|
182
+ preferred?(name, group.first)
183
+ end
184
+ alias_method "prefers_#{name}?", "preferred_#{name}?"
185
+
186
+ # Reader
187
+ define_method("preferred_#{name}") do |*group|
188
+ preferred(name, group.first)
189
+ end
190
+ alias_method "prefers_#{name}", "preferred_#{name}"
191
+
192
+ # Writer
193
+ define_method("preferred_#{name}=") do |*args|
194
+ write_preference(*args.flatten.unshift(name))
195
+ end
196
+ alias_method "prefers_#{name}=", "preferred_#{name}="
197
+
198
+ # Changes
199
+ define_method("preferred_#{name}_changed?") do |*group|
200
+ preference_changed?(name, group.first)
201
+ end
202
+ alias_method "prefers_#{name}_changed?", "preferred_#{name}_changed?"
203
+
204
+ define_method("preferred_#{name}_was") do |*group|
205
+ preference_was(name, group.first)
206
+ end
207
+ alias_method "prefers_#{name}_was", "preferred_#{name}_was"
208
+
209
+ define_method("preferred_#{name}_change") do |*group|
210
+ preference_change(name, group.first)
211
+ end
212
+ alias_method "prefers_#{name}_change", "preferred_#{name}_change"
213
+
214
+ define_method("preferred_#{name}_will_change!") do |*group|
215
+ preference_will_change!(name, group.first)
216
+ end
217
+ alias_method "prefers_#{name}_will_change!", "preferred_#{name}_will_change!"
218
+
219
+ define_method("reset_preferred_#{name}!") do |*group|
220
+ reset_preference!(name, group.first)
221
+ end
222
+ alias_method "reset_prefers_#{name}!", "reset_preferred_#{name}!"
223
+
224
+ definition
225
+ end
226
+ end
227
+
228
+ module ClassMethods #:nodoc:
229
+ # Generates the scope for looking under records with a specific set of
230
+ # preferences associated with them.
231
+ #
232
+ # Note thate this is a bit more complicated than usual since the preference
233
+ # definitions aren't in the database for joins, defaults need to be accounted
234
+ # for, and querying for the the presence of multiple preferences requires
235
+ # multiple joins.
236
+ def build_preference_scope(preferences, inverse = false)
237
+ joins = []
238
+ statements = []
239
+ values = []
240
+
241
+ # Flatten the preferences for easier processing
242
+ preferences = preferences.inject({}) do |result, (group, value)|
243
+ if value.is_a?(Hash)
244
+ value.each {|preference, value| result[[group, preference]] = value}
245
+ else
246
+ result[[nil, group]] = value
247
+ end
248
+ result
249
+ end
250
+
251
+ preferences.each do |(group, preference), value|
252
+ group_id, group_type = Preference.split_group(group)
253
+ preference = preference.to_s
254
+ definition = preference_definitions[preference.to_s]
255
+ value = definition.type_cast(value)
256
+ is_default = definition.default_value(group_type) == value
257
+
258
+ table = "preferences_#{group_id}_#{group_type}_#{preference}"
259
+
260
+ # Since each preference is a different record, they need their own
261
+ # join so that the proper conditions can be set
262
+ joins << "LEFT JOIN preferences AS #{table} ON #{table}.owner_id = #{table_name}.#{primary_key} AND " + sanitize_sql(
263
+ "#{table}.owner_type" => base_class.name.to_s,
264
+ "#{table}.group_id" => group_id,
265
+ "#{table}.group_type" => group_type,
266
+ "#{table}.name" => preference
267
+ )
268
+
269
+ if inverse
270
+ statements << "#{table}.id IS NOT NULL AND #{table}.value " + (value.nil? ? ' IS NOT NULL' : ' != ?') + (!is_default ? " OR #{table}.id IS NULL" : '')
271
+ else
272
+ statements << "#{table}.id IS NOT NULL AND #{table}.value " + (value.nil? ? ' IS NULL' : ' = ?') + (is_default ? " OR #{table}.id IS NULL" : '')
273
+ end
274
+ values << value unless value.nil?
275
+ end
276
+
277
+ sql = statements.map! {|statement| "(#{statement})"} * ' AND '
278
+ {:joins => joins, :conditions => values.unshift(sql)}
279
+ end
280
+ end
281
+
282
+ module InstanceMethods
283
+ def self.included(base) #:nodoc:
284
+ base.class_eval do
285
+ alias_method :prefs, :preferences
286
+ end
287
+ end
288
+
289
+ # Finds all preferences, including defaults, for the current record. If
290
+ # looking up custom group preferences, then this will include all default
291
+ # preferences within that particular group as well.
292
+ #
293
+ # == Examples
294
+ #
295
+ # A user with no stored values:
296
+ #
297
+ # user = User.find(:first)
298
+ # user.preferences
299
+ # => {"language"=>"English", "color"=>nil}
300
+ #
301
+ # A user with stored values for a particular group:
302
+ #
303
+ # user.preferred_color = 'red', :cars
304
+ # user.preferences(:cars)
305
+ # => {"language=>"English", "color"=>"red"}
306
+ def preferences(group = nil)
307
+ preferences = preferences_group(group)
308
+
309
+ unless preferences_group_loaded?(group)
310
+ group_id, group_type = Preference.split_group(group)
311
+ find_preferences(:group_id => group_id, :group_type => group_type).each do |preference|
312
+ preferences[preference.name] = preference.value unless preferences.include?(preference.name)
313
+ end
314
+
315
+ # Add defaults
316
+ preference_definitions.each do |name, definition|
317
+ preferences[name] = definition.default_value(group_type) unless preferences.include?(name)
318
+ end
319
+ end
320
+
321
+ preferences.inject({}) do |typed_preferences, (name, value)|
322
+ typed_preferences[name] = value.nil? ? value : preference_definitions[name].type_cast(value)
323
+ typed_preferences
324
+ end
325
+ end
326
+
327
+ # Queries whether or not a value is present for the given preference.
328
+ # This is dependent on how the value is type-casted.
329
+ #
330
+ # == Examples
331
+ #
332
+ # class User < ActiveRecord::Base
333
+ # preference :color, :string, :default => 'red'
334
+ # end
335
+ #
336
+ # user = User.create
337
+ # user.preferred(:color) # => "red"
338
+ # user.preferred?(:color) # => true
339
+ # user.preferred?(:color, 'cars') # => true
340
+ # user.preferred?(:color, Car.first) # => true
341
+ #
342
+ # user.write_preference(:color, nil)
343
+ # user.preferred(:color) # => nil
344
+ # user.preferred?(:color) # => false
345
+ def preferred?(name, group = nil)
346
+ name = name.to_s
347
+ assert_valid_preference(name)
348
+
349
+ value = preferred(name, group)
350
+ preference_definitions[name].query(value)
351
+ end
352
+ alias_method :prefers?, :preferred?
353
+
354
+ # Gets the actual value stored for the given preference, or the default
355
+ # value if nothing is present.
356
+ #
357
+ # == Examples
358
+ #
359
+ # class User < ActiveRecord::Base
360
+ # preference :color, :string, :default => 'red'
361
+ # end
362
+ #
363
+ # user = User.create
364
+ # user.preferred(:color) # => "red"
365
+ # user.preferred(:color, 'cars') # => "red"
366
+ # user.preferred(:color, Car.first) # => "red"
367
+ #
368
+ # user.write_preference(:color, 'blue')
369
+ # user.preferred(:color) # => "blue"
370
+ def preferred(name, group = nil)
371
+ name = name.to_s
372
+ assert_valid_preference(name)
373
+
374
+ if preferences_group(group).include?(name)
375
+ # Value for this group/name has been written, but not saved yet:
376
+ # grab from the pending values
377
+ value = preferences_group(group)[name]
378
+ else
379
+ # Grab the first preference; if it doesn't exist, use the default value
380
+ group_id, group_type = Preference.split_group(group)
381
+ preference = find_preferences(:name => name, :group_id => group_id, :group_type => group_type).first unless preferences_group_loaded?(group)
382
+
383
+ value = preference ? preference.value : preference_definitions[name].default_value(group_type)
384
+ preferences_group(group)[name] = value
385
+ end
386
+
387
+ definition = preference_definitions[name]
388
+ value = definition.type_cast(value) unless value.nil?
389
+ value
390
+ end
391
+ alias_method :prefers, :preferred
392
+
393
+ # Sets a new value for the given preference. The actual Preference record
394
+ # is *not* created until this record is saved. In this way, preferences
395
+ # act *exactly* the same as attributes. They can be written to and
396
+ # validated against, but won't actually be written to the database until
397
+ # the record is saved.
398
+ #
399
+ # == Examples
400
+ #
401
+ # user = User.find(:first)
402
+ # user.write_preference(:color, 'red') # => "red"
403
+ # user.save!
404
+ #
405
+ # user.write_preference(:color, 'blue', Car.first) # => "blue"
406
+ # user.save!
407
+ def write_preference(name, value, group = nil)
408
+ name = name.to_s
409
+ assert_valid_preference(name)
410
+
411
+ preferences_changed = preferences_changed_group(group)
412
+ if preferences_changed.include?(name)
413
+ old = preferences_changed[name]
414
+ preferences_changed.delete(name) unless preference_value_changed?(name, old, value)
415
+ else
416
+ old = clone_preference_value(name, group)
417
+ preferences_changed[name] = old if preference_value_changed?(name, old, value)
418
+ end
419
+
420
+ value = convert_number_column_value(value) if preference_definitions[name].number?
421
+ preferences_group(group)[name] = value
422
+
423
+ value
424
+ end
425
+
426
+ # Whether any attributes have unsaved changes.
427
+ #
428
+ # == Examples
429
+ #
430
+ # user = User.find(:first)
431
+ # user.preferences_changed? # => false
432
+ # user.write_preference(:color, 'red')
433
+ # user.preferences_changed? # => true
434
+ # user.save
435
+ # user.preferences_changed? # => false
436
+ #
437
+ # # Groups
438
+ # user.preferences_changed?(:car) # => false
439
+ # user.write_preference(:color, 'red', :car)
440
+ # user.preferences_changed(:car) # => true
441
+ def preferences_changed?(group = nil)
442
+ !preferences_changed_group(group).empty?
443
+ end
444
+
445
+ # A list of the preferences that have unsaved changes.
446
+ #
447
+ # == Examples
448
+ #
449
+ # user = User.find(:first)
450
+ # user.preferences_changed # => []
451
+ # user.write_preference(:color, 'red')
452
+ # user.preferences_changed # => ["color"]
453
+ # user.save
454
+ # user.preferences_changed # => []
455
+ #
456
+ # # Groups
457
+ # user.preferences_changed(:car) # => []
458
+ # user.write_preference(:color, 'red', :car)
459
+ # user.preferences_changed(:car) # => ["color"]
460
+ def preferences_changed(group = nil)
461
+ preferences_changed_group(group).keys
462
+ end
463
+
464
+ # A map of the preferences that have changed in the current object.
465
+ #
466
+ # == Examples
467
+ #
468
+ # user = User.find(:first)
469
+ # user.preferred(:color) # => nil
470
+ # user.preference_changes # => {}
471
+ #
472
+ # user.write_preference(:color, 'red')
473
+ # user.preference_changes # => {"color" => [nil, "red"]}
474
+ # user.save
475
+ # user.preference_changes # => {}
476
+ #
477
+ # # Groups
478
+ # user.preferred(:color, :car) # => nil
479
+ # user.preference_changes(:car) # => {}
480
+ # user.write_preference(:color, 'red', :car)
481
+ # user.preference_changes(:car) # => {"color" => [nil, "red"]}
482
+ def preference_changes(group = nil)
483
+ preferences_changed(group).inject({}) do |changes, preference|
484
+ changes[preference] = preference_change(preference, group)
485
+ changes
486
+ end
487
+ end
488
+
489
+ # Reloads the pereferences of this object as well as its attributes
490
+ def reload(*args) #:nodoc:
491
+ result = super
492
+
493
+ @preferences.clear if @preferences
494
+ @preferences_changed.clear if @preferences_changed
495
+
496
+ result
497
+ end
498
+
499
+ private
500
+ # Asserts that the given name is a valid preference in this model. If it
501
+ # is not, then an ArgumentError exception is raised.
502
+ def assert_valid_preference(name)
503
+ raise(ArgumentError, "Unknown preference: #{name}") unless preference_definitions.include?(name)
504
+ end
505
+
506
+ # Gets the set of preferences identified by the given group
507
+ def preferences_group(group)
508
+ @preferences ||= {}
509
+ @preferences[group.is_a?(Symbol) ? group.to_s : group] ||= {}
510
+ end
511
+
512
+ # Determines whether the given group of preferences has already been
513
+ # loaded from the database
514
+ def preferences_group_loaded?(group)
515
+ preference_definitions.length == preferences_group(group).length
516
+ end
517
+
518
+ # Generates a clone of the current value stored for the preference with
519
+ # the given name / group
520
+ def clone_preference_value(name, group)
521
+ value = preferred(name, group)
522
+ value.duplicable? ? value.clone : value
523
+ rescue TypeError, NoMethodError
524
+ value
525
+ end
526
+
527
+ # Keeps track of all preferences that have been changed so that they can
528
+ # be properly updated in the database. Maps group -> preference -> value.
529
+ def preferences_changed_group(group)
530
+ @preferences_changed ||= {}
531
+ @preferences_changed[group.is_a?(Symbol) ? group.to_s : group] ||= {}
532
+ end
533
+
534
+ # Determines whether a preference changed in the given group
535
+ def preference_changed?(name, group)
536
+ preferences_changed_group(group).include?(name)
537
+ end
538
+
539
+ # Builds an array of [original_value, new_value] for the given preference.
540
+ # If the perference did not change, this will return nil.
541
+ def preference_change(name, group)
542
+ [preferences_changed_group(group)[name], preferred(name, group)] if preference_changed?(name, group)
543
+ end
544
+
545
+ # Gets the last saved value for the given preference
546
+ def preference_was(name, group)
547
+ preference_changed?(name, group) ? preferences_changed_group(group)[name] : preferred(name, group)
548
+ end
549
+
550
+ # Forces the given preference to be saved regardless of whether the value
551
+ # is actually diferent
552
+ def preference_will_change!(name, group)
553
+ preferences_changed_group(group)[name] = clone_preference_value(name, group)
554
+ end
555
+
556
+ # Reverts any unsaved changes to the given preference
557
+ def reset_preference!(name, group)
558
+ write_preference(name, preferences_changed_group(group)[name], group) if preference_changed?(name, group)
559
+ end
560
+
561
+ # Determines whether the old value is different from the new value for the
562
+ # given preference. This will use the typecasted value to determine
563
+ # equality.
564
+ def preference_value_changed?(name, old, value)
565
+ definition = preference_definitions[name]
566
+ if definition.type == :integer && (old.nil? || old == 0)
567
+ # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values.
568
+ # Hence we don't record it as a change if the value changes from nil to ''.
569
+ # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
570
+ # be typecast back to 0 (''.to_i => 0)
571
+ value = nil if value.blank?
572
+ else
573
+ value = definition.type_cast(value)
574
+ end
575
+
576
+ old != value
577
+ end
578
+
579
+ # Updates any preferences that have been changed/added since the record
580
+ # was last saved
581
+ def update_preferences
582
+ if @preferences_changed
583
+ @preferences_changed.each do |group, preferences|
584
+ group_id, group_type = Preference.split_group(group)
585
+
586
+ preferences.keys.each do |name|
587
+ # Find an existing preference or build a new one
588
+ attributes = {:name => name, :group_id => group_id, :group_type => group_type}
589
+ preference = find_preferences(attributes).first || stored_preferences.build(attributes)
590
+ preference.value = preferred(name, group)
591
+ preference.save!
592
+ end
593
+ end
594
+
595
+ @preferences_changed.clear
596
+ end
597
+ end
598
+
599
+ # Finds all stored preferences with the given attributes. This will do a
600
+ # smart lookup by looking at the in-memory collection if it was eager-
601
+ # loaded.
602
+ def find_preferences(attributes)
603
+ if stored_preferences.loaded?
604
+ stored_preferences.select do |preference|
605
+ attributes.all? {|attribute, value| preference[attribute] == value}
606
+ end
607
+ else
608
+ stored_preferences.find(:all, :conditions => attributes)
609
+ end
610
+ end
611
+ end
612
+ end
613
+
614
+ ActiveRecord::Base.class_eval do
615
+ extend Preferences::MacroMethods
616
+ end
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'preferences/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "ee_preferences"
6
+ s.version = Preferences::VERSION
7
+ s.authors = ["Aaron Pfeifer"]
8
+ s.email = "aaron@pluginaweek.org"
9
+ s.homepage = "http://www.pluginaweek.org"
10
+ s.description = "Adds support for easily creating custom preferences for ActiveRecord models"
11
+ s.summary = "Custom preferences for ActiveRecord models"
12
+ s.require_paths = ["lib"]
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- test/*`.split("\n")
15
+ s.rdoc_options = %w(--line-numbers --inline-source --title preferences --main README.rdoc)
16
+ s.extra_rdoc_files = %w(README.rdoc CHANGELOG.rdoc LICENSE)
17
+
18
+ s.add_development_dependency("rake")
19
+ s.add_development_dependency("plugin_test_helper", ">= 0.3.1")
20
+ end
@@ -0,0 +1,2 @@
1
+ class Car < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class Employee < ActiveRecord::Base
2
+ end
@@ -0,0 +1,3 @@
1
+ class Manager < Employee
2
+ preference :health_insurance
3
+ end
@@ -0,0 +1,8 @@
1
+ class User < ActiveRecord::Base
2
+ # preference :hot_salsa
3
+ # preference :dark_chocolate, :default => true
4
+ # preference :color, :string
5
+ # preference :car, :integer
6
+ # preference :language, :string, :default => 'English'
7
+ # preference :data, :any
8
+ end
@@ -0,0 +1,11 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :login, :null => false
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :users
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class CreateCars < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :cars do |t|
4
+ t.string :name, :null => false
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :cars
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ class CreateEmployees < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :employees do |t|
4
+ t.string :name, :null => false
5
+ t.string :type
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :employees
11
+ end
12
+ end