module Preferences::InstanceMethods
Public Instance Methods
A map of the preferences that have changed in the current object.
Examples¶ ↑
user = User.find(:first) user.preferred(:color) # => nil user.preference_changes # => {} user.write_preference(:color, 'red') user.preference_changes # => {"color" => [nil, "red"]} user.save user.preference_changes # => {} # Groups user.preferred(:color, :car) # => nil user.preference_changes(:car) # => {} user.write_preference(:color, 'red', :car) user.preference_changes(:car) # => {"color" => [nil, "red"]}
# File lib/preferences.rb 497 def preference_changes(group = nil) 498 preferences_changed(group).inject({}) do |changes, preference| 499 changes[preference] = preference_change(preference, group) 500 changes 501 end 502 end
Finds all preferences, including defaults, for the current record. If looking up custom group preferences, then this will include all default preferences within that particular group as well.
Examples¶ ↑
A user with no stored values:
user = User.find(:first) user.preferences => {"language"=>"English", "color"=>nil}
A user with stored values for a particular group:
user.preferred_color = 'red', :cars user.preferences(:cars) => {"language=>"English", "color"=>"red"}
# File lib/preferences.rb 320 def preferences(group = nil) 321 preferences = preferences_group(group) 322 323 unless preferences_group_loaded?(group) 324 group_id, group_type = Preference.split_group(group) 325 find_preferences(:group_id => group_id, :group_type => group_type).each do |preference| 326 # fixed: ignore entries in database that are not present in the definition 327 preferences[preference.name] = preference.value unless (preferences.include?(preference.name) || !preference_definitions[preference.name]) 328 end 329 330 # Add defaults 331 preference_definitions.each do |name, definition| 332 preferences[name] = definition.default_value(group_type) unless preferences.include?(name) 333 end 334 end 335 336 preferences.inject({}) do |typed_preferences, (name, value)| 337 typed_preferences[name] = value.nil? ? value : preference_definitions[name].type_cast(value) 338 typed_preferences 339 end 340 end
A list of the preferences that have unsaved changes.
Examples¶ ↑
user = User.find(:first) user.preferences_changed # => [] user.write_preference(:color, 'red') user.preferences_changed # => ["color"] user.save user.preferences_changed # => [] # Groups user.preferences_changed(:car) # => [] user.write_preference(:color, 'red', :car) user.preferences_changed(:car) # => ["color"]
# File lib/preferences.rb 475 def preferences_changed(group = nil) 476 preferences_changed_group(group).keys 477 end
Whether any attributes have unsaved changes.
Examples¶ ↑
user = User.find(:first) user.preferences_changed? # => false user.write_preference(:color, 'red') user.preferences_changed? # => true user.save user.preferences_changed? # => false # Groups user.preferences_changed?(:car) # => false user.write_preference(:color, 'red', :car) user.preferences_changed(:car) # => true
# File lib/preferences.rb 456 def preferences_changed?(group = nil) 457 !preferences_changed_group(group).empty? 458 end
Gets the actual value stored for the given preference, or the default value if nothing is present.
Examples¶ ↑
class User < ActiveRecord::Base preference :color, :string, :default => 'red' end user = User.create user.preferred(:color) # => "red" user.preferred(:color, 'cars') # => "red" user.preferred(:color, Car.first) # => "red" user.write_preference(:color, 'blue') user.preferred(:color) # => "blue"
# File lib/preferences.rb 385 def preferred(name, group = nil) 386 name = name.to_s 387 assert_valid_preference(name) 388 389 if preferences_group(group).include?(name) 390 # Value for this group/name has been written, but not saved yet: 391 # grab from the pending values 392 value = preferences_group(group)[name] 393 else 394 # Grab the first preference; if it doesn't exist, use the default value 395 group_id, group_type = Preference.split_group(group) 396 preference = find_preferences(:name => name, :group_id => group_id, :group_type => group_type).first unless preferences_group_loaded?(group) 397 398 value = preference ? preference.value : preference_definitions[name].default_value(group_type) 399 preferences_group(group)[name] = value 400 end 401 402 definition = preference_definitions[name] 403 value = definition.type_cast(value) unless value.nil? 404 value 405 end
Queries whether or not a value is present for the given preference. This is dependent on how the value is type-casted.
Examples¶ ↑
class User < ActiveRecord::Base preference :color, :string, :default => 'red' end user = User.create user.preferred(:color) # => "red" user.preferred?(:color) # => true user.preferred?(:color, 'cars') # => true user.preferred?(:color, Car.first) # => true user.write_preference(:color, nil) user.preferred(:color) # => nil user.preferred?(:color) # => false
# File lib/preferences.rb 360 def preferred?(name, group = nil) 361 name = name.to_s 362 assert_valid_preference(name) 363 364 value = preferred(name, group) 365 preference_definitions[name].query(value) 366 end
Sets a new value for the given preference. The actual Preference record is not created until this record is saved. In this way, preferences act exactly the same as attributes. They can be written to and validated against, but won't actually be written to the database until the record is saved.
Examples¶ ↑
user = User.find(:first) user.write_preference(:color, 'red') # => "red" user.save! user.write_preference(:color, 'blue', Car.first) # => "blue" user.save!
# File lib/preferences.rb 422 def write_preference(name, value, group = nil) 423 name = name.to_s 424 assert_valid_preference(name) 425 426 preferences_changed = preferences_changed_group(group) 427 if preferences_changed.include?(name) 428 old = preferences_changed[name] 429 preferences_changed.delete(name) unless preference_value_changed?(name, old, value) 430 else 431 old = clone_preference_value(name, group) 432 preferences_changed[name] = old if preference_value_changed?(name, old, value) 433 end 434 435 value = convert_number_column_value(value) if preference_definitions[name].number? 436 preferences_group(group)[name] = preference_definitions[name].type_cast(value) 437 438 value 439 end
Private Instance Methods
Asserts that the given name is a valid preference in this model. If it is not, then an ArgumentError exception is raised.
# File lib/preferences.rb 518 def assert_valid_preference(name) 519 raise(ArgumentError, "Unknown preference: #{name}") unless preference_definitions.include?(name) 520 end
Generates a clone of the current value stored for the preference with the given name / group
# File lib/preferences.rb 536 def clone_preference_value(name, group) 537 value = preferred(name, group) 538 value.duplicable? ? value.clone : value 539 rescue TypeError, NoMethodError 540 value 541 end
Was removed from Rails 4, so inlne it here
# File lib/preferences.rb 638 def convert_number_column_value(value) 639 case value 640 when FalseClass 641 0 642 when TrueClass 643 1 644 when String 645 value.presence 646 else 647 value 648 end 649 end
Finds all stored preferences with the given attributes. This will do a smart lookup by looking at the in-memory collection if it was eager- loaded.
# File lib/preferences.rb 621 def find_preferences(attributes) 622 if stored_preferences.loaded? 623 stored_preferences.select do |preference| 624 attributes.all? do |attribute, value| 625 if value.is_a?(Array) 626 value.include?(preference[attribute]) 627 else 628 preference[attribute] == value 629 end 630 end 631 end 632 else 633 stored_preferences.where(attributes) 634 end 635 end
Builds an array of [original_value, new_value] for the given preference. If the perference did not change, this will return nil.
# File lib/preferences.rb 557 def preference_change(name, group) 558 [preferences_changed_group(group)[name], preferred(name, group)] if preference_changed?(name, group) 559 end
Determines whether a preference changed in the given group
# File lib/preferences.rb 551 def preference_changed?(name, group) 552 preferences_changed_group(group).include?(name) 553 end
Determines whether the old value is different from the new value for the given preference. This will use the typecasted value to determine equality.
# File lib/preferences.rb 580 def preference_value_changed?(name, old, value) 581 definition = preference_definitions[name] 582 if definition.type == :integer && (old.nil? || old == 0) 583 # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values. 584 # Hence we don't record it as a change if the value changes from nil to ''. 585 # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll 586 # be typecast back to 0 (''.to_i => 0) 587 value = nil if value.blank? 588 else 589 value = definition.type_cast(value) 590 end 591 592 old != value 593 end
Gets the last saved value for the given preference
# File lib/preferences.rb 562 def preference_was(name, group) 563 preference_changed?(name, group) ? preferences_changed_group(group)[name] : preferred(name, group) 564 end
Forces the given preference to be saved regardless of whether the value is actually diferent
# File lib/preferences.rb 568 def preference_will_change!(name, group) 569 preferences_changed_group(group)[name] = clone_preference_value(name, group) 570 end
Keeps track of all preferences that have been changed so that they can be properly updated in the database. Maps group -> preference -> value.
# File lib/preferences.rb 545 def preferences_changed_group(group) 546 @preferences_changed ||= {} 547 @preferences_changed[group.is_a?(Symbol) ? group.to_s : group] ||= {} 548 end
Gets the set of preferences identified by the given group
# File lib/preferences.rb 523 def preferences_group(group) 524 @preferences ||= {} 525 @preferences[group.is_a?(Symbol) ? group.to_s : group] ||= {} 526 end
Determines whether the given group of preferences has already been loaded from the database
# File lib/preferences.rb 530 def preferences_group_loaded?(group) 531 preference_definitions.length == preferences_group(group).length 532 end
Reverts any unsaved changes to the given preference
# File lib/preferences.rb 573 def reset_preference!(name, group) 574 write_preference(name, preferences_changed_group(group)[name], group) if preference_changed?(name, group) 575 end
Updates any preferences that have been changed/added since the record was last saved
# File lib/preferences.rb 597 def update_preferences 598 if @preferences_changed 599 @preferences_changed.each do |group, preferences| 600 group_id, group_type = Preference.split_group(group) 601 602 preferences.keys.each do |name| 603 # Find an existing preference or build a new one 604 attributes = {:name => name, :group_id => group_id, :group_type => group_type} 605 unless (preference = find_preferences(attributes).first) 606 preference = stored_preferences.build 607 attributes.each_pair { |attribute, value| preference[attribute] = value } 608 end 609 preference.value = preferred(name, group) 610 preference.save! 611 end 612 end 613 614 @preferences_changed.clear 615 end 616 end