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, line 483 def preference_changes(group = nil) preferences_changed(group).inject({}) do |changes, preference| changes[preference] = preference_change(preference, group) changes end 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, line 307 def preferences(group = nil) preferences = preferences_group(group) unless preferences_group_loaded?(group) group_id, group_type = Preference.split_group(group) find_preferences(:group_id => group_id, :group_type => group_type).each do |preference| preferences[preference.name] = preference.value unless preferences.include?(preference.name) end # Add defaults preference_definitions.each do |name, definition| preferences[name] = definition.default_value(group_type) unless preferences.include?(name) end end preferences.inject({}) do |typed_preferences, (name, value)| typed_preferences[name] = value.nil? ? value : preference_definitions[name].type_cast(value) typed_preferences end 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, line 461 def preferences_changed(group = nil) preferences_changed_group(group).keys 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, line 442 def preferences_changed?(group = nil) !preferences_changed_group(group).empty? 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, line 371 def preferred(name, group = nil) name = name.to_s assert_valid_preference(name) if preferences_group(group).include?(name) # Value for this group/name has been written, but not saved yet: # grab from the pending values value = preferences_group(group)[name] else # Grab the first preference; if it doesn't exist, use the default value group_id, group_type = Preference.split_group(group) preference = find_preferences(:name => name, :group_id => group_id, :group_type => group_type).first unless preferences_group_loaded?(group) value = preference ? preference.value : preference_definitions[name].default_value(group_type) preferences_group(group)[name] = value end definition = preference_definitions[name] value = definition.type_cast(value) unless value.nil? value 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, line 346 def preferred?(name, group = nil) name = name.to_s assert_valid_preference(name) value = preferred(name, group) preference_definitions[name].query(value) 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, line 408 def write_preference(name, value, group = nil) name = name.to_s assert_valid_preference(name) preferences_changed = preferences_changed_group(group) if preferences_changed.include?(name) old = preferences_changed[name] preferences_changed.delete(name) unless preference_value_changed?(name, old, value) else old = clone_preference_value(name, group) preferences_changed[name] = old if preference_value_changed?(name, old, value) end value = value.to_i if preference_definitions[name].number? preferences_group(group)[name] = value value 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, line 503 def assert_valid_preference(name) raise(ArgumentError, "Unknown preference: #{name}") unless preference_definitions.include?(name) end
Generates a clone of the current value stored for the preference with the given name / group
# File lib/preferences.rb, line 521 def clone_preference_value(name, group) value = preferred(name, group) value.duplicable? ? value.clone : value rescue TypeError, NoMethodError value end
Destroys preferences before the owning object is destroyed.
# File lib/preferences.rb, line 618 def destroy_preferences stored_preferences.destroy_all 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, line 608 def find_preferences(attributes) if stored_preferences.loaded? stored_preferences.select do |preference| attributes.all? {|attribute, value| preference[attribute] == value} end else stored_preferences.where(attributes) end 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, line 542 def preference_change(name, group) [preferences_changed_group(group)[name], preferred(name, group)] if preference_changed?(name, group) end
Determines whether a preference changed in the given group
# File lib/preferences.rb, line 536 def preference_changed?(name, group) preferences_changed_group(group).include?(name) 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, line 565 def preference_value_changed?(name, old, value) definition = preference_definitions[name] if definition.type == :integer && (old.nil? || old == 0) # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values. # Hence we don't record it as a change if the value changes from nil to ''. # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll # be typecast back to 0 (''.to_i => 0) value = nil if value.blank? else value = definition.type_cast(value) end old != value end
Gets the last saved value for the given preference
# File lib/preferences.rb, line 547 def preference_was(name, group) preference_changed?(name, group) ? preferences_changed_group(group)[name] : preferred(name, group) end
Forces the given preference to be saved regardless of whether the value is actually diferent
# File lib/preferences.rb, line 553 def preference_will_change!(name, group) preferences_changed_group(group)[name] = clone_preference_value(name, group) 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, line 530 def preferences_changed_group(group) @preferences_changed ||= {} @preferences_changed[group.is_a?(Symbol) ? group.to_s : group] ||= {} end
Gets the set of preferences identified by the given group
# File lib/preferences.rb, line 508 def preferences_group(group) @preferences ||= {} @preferences[group.is_a?(Symbol) ? group.to_s : group] ||= {} end
Determines whether the given group of preferences has already been loaded from the database
# File lib/preferences.rb, line 515 def preferences_group_loaded?(group) preference_definitions.length == preferences_group(group).length end
Reverts any unsaved changes to the given preference
# File lib/preferences.rb, line 558 def reset_preference!(name, group) write_preference(name, preferences_changed_group(group)[name], group) if preference_changed?(name, group) end
Updates any preferences that have been changed/added since the record was last saved
# File lib/preferences.rb, line 582 def update_preferences if @preferences_changed @preferences_changed.each do |group, preferences| group_id, group_type = Preference.split_group(group) preferences.keys.each do |name| # Find an existing preference or build a new one attributes = {:name => name, :group_id => group_id, :group_type => group_type} unless (preference = find_preferences(attributes).first) preference = stored_preferences.build attributes.each_pair { |attribute, value| preference[attribute] = value } end preference.value = preferred(name, group) preference.save! end end @preferences_changed.clear end end