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

new(owner, options) click to toggle source

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

<<(dirt) click to toggle source

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
[](key) click to toggle source

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
[]=(key, value) click to toggle source

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
as_hash() click to toggle source

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
clear() click to toggle source

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
each(&block) click to toggle source

Emulates Hash.each

# File lib/eav_hashes/eav_hash.rb, line 89
def each (&block)
  as_hash.each &block
end
each_pair(&block) click to toggle source

Emulates Hash.each_pair (same as each)

# File lib/eav_hashes/eav_hash.rb, line 94
def each_pair (&block)
  each &block
end
entries() click to toggle source

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
inspect() click to toggle source

Take the crap out of inspect calls

# File lib/eav_hashes/eav_hash.rb, line 120
def inspect
  as_hash
end
keys() click to toggle source

Gets the keys this EavHash manages

# File lib/eav_hashes/eav_hash.rb, line 83
def keys
  load_entries_if_needed
  @entries.keys
end
save_entries() click to toggle source

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
values() click to toggle source

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

load_entries_if_needed() click to toggle source

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
set_entry_owner(entry) click to toggle source

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
update_or_create_entry(key, value) click to toggle source
# 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