class ActiveRecord::EavHashes::EavHash
Wraps a bunch of EavEntries and lets you use them like you would a hash This class should not be used directly and you should instead let eav_hash_for create one for you
Public Class Methods
Creates a new EavHash
. You should really let eav_hash_for do this for you… @param [ActiveRecord::Base] owner the Model which will own this hash @param [Hash] options the options hash which eav_hash generated
# File lib/eav_hashes/eav_hash.rb, line 9 def initialize(owner, options) Util::sanity_check options @owner = owner @options = options end
Public Instance Methods
I don't know why Ruby hashes don't have a shovel operator, but I will make damn sure that I fight the power and stick it to the man by implementing it. @param [Hash, EavHash] dirt the dirt to shovel (ba dum, tss)
# File lib/eav_hashes/eav_hash.rb, line 49 def <<(dirt) if dirt.is_a? Hash dirt.each do |key, value| update_or_create_entry key, value end elsif dirt.is_a? EavHash dirt.entries.each do |key, entry| update_or_create_entry key, entry.value end else raise "You can't shovel something that's not a Hash or EavHash here!" end self end
Gets the value of an EAV attribute @param [String, Symbol] key
# File lib/eav_hashes/eav_hash.rb, line 32 def [](key) raise "Key must be a string or a symbol!" unless key.is_a?(String) or key.is_a?(Symbol) load_entries_if_needed return @entries[key].value if @entries[key] nil end
Sets the value of the EAV attribute `key` to `value` @param [String, Symbol] key the attribute @param [Object] value the value
# File lib/eav_hashes/eav_hash.rb, line 42 def []=(key, value) update_or_create_entry key, value end
Returns a hash with each entry key mapped to its actual value, not the internal EavEntry
# File lib/eav_hashes/eav_hash.rb, line 109 def as_hash load_entries_if_needed hsh = {} @entries.each do |k, entry| hsh[k] = entry.value end hsh end
Empties the hash by setting all the values to nil (without committing them, of course)
# File lib/eav_hashes/eav_hash.rb, line 100 def clear load_entries_if_needed @entries.each do |_, entry| entry.value = nil end end
Emulates Hash.each
# File lib/eav_hashes/eav_hash.rb, line 89 def each (&block) as_hash.each &block end
Emulates Hash.each_pair (same as each)
# File lib/eav_hashes/eav_hash.rb, line 94 def each_pair (&block) each &block end
Gets the raw hash containing EavEntries by their keys
# File lib/eav_hashes/eav_hash.rb, line 66 def entries load_entries_if_needed end
Take the crap out of inspect
calls
# File lib/eav_hashes/eav_hash.rb, line 120 def inspect as_hash end
Gets the keys this EavHash
manages
# File lib/eav_hashes/eav_hash.rb, line 83 def keys load_entries_if_needed @entries.keys end
Saves any modified entries and deletes any which have been nil'd to save DB space
# File lib/eav_hashes/eav_hash.rb, line 16 def save_entries # The entries are lazy-loaded, so don't do anything if they haven't been accessed or modified return unless (@entries and @changes_made) @entries.values.each do |entry| if entry.value.nil? entry.delete else set_entry_owner(entry) entry.save end end end
Gets the actual values this EavHash
contains
# File lib/eav_hashes/eav_hash.rb, line 71 def values load_entries_if_needed ret = [] @entries.values.each do |value| ret << value end ret end
Private Instance Methods
Since entries are lazy-loaded, this is called just before an operation on an entry happens and loads the rows only once per EavHash
lifetime.
# File lib/eav_hashes/eav_hash.rb, line 148 def load_entries_if_needed if @entries.nil? @entries = {} rows_from_model = @owner.send("#{@options[:entry_assoc_name]}") rows_from_model.each do |row| @entries[row.key] = row end end @entries end
Sets an entry's owner ID. This is called when we save attributes for a model which has just been created and not committed to the DB prior to having its EAV hash(es) modified @param [EavEntry] entry the entry whose owner to change
# File lib/eav_hashes/eav_hash.rb, line 163 def set_entry_owner(entry) entry.send "#{@options[:parent_assoc_name]}_id=", @owner.id end
# File lib/eav_hashes/eav_hash.rb, line 125 def update_or_create_entry(key, value) raise "Key must be a string or a symbol!" unless key.is_a?(String) or key.is_a?(Symbol) load_entries_if_needed @changes_made = true @owner.updated_at = Time.now if @entries[key] @entries[key].value = value else new_entry = @options[:entry_class].new set_entry_owner(new_entry) new_entry.key = key new_entry.value = value @entries[key] = new_entry value end end