module ActiveRecord::EavHashes::Util

Public Class Methods

class_from_string(str) click to toggle source

Find a class even if it's contained in one or more modules. See stackoverflow.com/questions/3163641/get-a-class-by-name-in-ruby

# File lib/eav_hashes/util.rb, line 96
def self.class_from_string(str)
  str.split('::').inject(Object) do |mod, class_name|
    mod.const_get(class_name)
  end
end
class_from_string_exists?(str) click to toggle source

Check whether a class exists, even if it's contained in one or more modules.

# File lib/eav_hashes/util.rb, line 103
def self.class_from_string_exists?(str)
  begin
    class_from_string(str)
  rescue
    return false
  end
  true
end
create_eav_table_class(options) click to toggle source

Creates a new type subclassed from ActiveRecord::EavHashes::EavEntry which represents an eav_hash key-value pair

# File lib/eav_hashes/util.rb, line 45
      def self.create_eav_table_class (options)
        sanity_check options

        # Don't overwrite an existing type
        return class_from_string(options[:entry_class_name].to_s) if class_from_string_exists?(options[:entry_class_name])

        # Create our type
        klass = set_constant_from_string options[:entry_class_name].to_s, Class.new(ActiveRecord::EavHashes::EavEntry)

        # Fill in the associations and specify the table it belongs to
        klass.class_eval <<-END_EVAL
          self.table_name = "#{options[:table_name]}"
          belongs_to :#{options[:parent_assoc_name]}
        END_EVAL

        return klass
      end
fill_options_hash(options) click to toggle source

Fills in any options not explicitly passed to eav_hash_for and creates an EavEntry type for the table @param [Hash] options the options hash to be filled with defaults on unset keys.

# File lib/eav_hashes/util.rb, line 13
def self.fill_options_hash(options)
  sanity_check options

  # Generate a unique class name based on the eav_hash's name and owner
  options[:entry_class_name] ||= "#{options[:parent_class_name]}_#{options[:hash_name]}_entry".camelize.to_sym

  # Strip "_entries" from the table name
  if /Entry$/.match options[:entry_class_name]
    options[:table_name] ||= options[:entry_class_name].to_s.tableize.slice(0..-9).to_sym
  else
    options[:table_name] ||= options[:entry_class_name].to_s.tableize.to_sym
  end

  # Create the symbol name for the "belongs_to" association in the entry model
  options[:parent_assoc_name] ||= "#{options[:parent_class_name].to_s.underscore}".to_sym

  # Create the symbol name for the "has_many" association in the parent model
  options[:entry_assoc_name] = options[:entry_class_name].to_s.tableize.to_sym

  # Change slashes to underscores in options to match what's output by the generator
  # TODO: Refactor table naming into one location
  options[:table_name] = options[:table_name].to_s.gsub(/\//,'_').to_sym
  options[:parent_assoc_name] = options[:parent_assoc_name].to_s.gsub(/\//,'_').to_sym
  options[:entry_assoc_name] = options[:entry_assoc_name].to_s.gsub(/\//,'_').to_sym

  # Create our custom type if it doesn't exist already
  options[:entry_class] = create_eav_table_class options

  return options
end
run_find_expression(key, value, options) click to toggle source

Searches an EavEntry's table for the specified key/value pair and returns an array containing the IDs of the models whose eav_hash key/value pair. You should not run this directly. @param [String, Symbol] key the key to search by @param [Object] value the value to search by. if this is nil, it will return all models which contain `key` @param [Hash] options the options hash which eav_hash_for hash generated.

# File lib/eav_hashes/util.rb, line 69
def self.run_find_expression (key, value, options)
  sanity_check options
  raise "Can't search for a nil key!" if key.nil?
  if value.nil?
    options[:entry_class].where(
        "entry_key = ? and symbol_key = ?",
        key.to_s,
        key.is_a?(Symbol)
    ).pluck("#{options[:parent_assoc_name]}_id".to_sym)
  else
    val_type = EavEntry.get_value_type value
    if val_type == EavEntry::SUPPORTED_TYPES[:Object]
      raise "Can't search by Objects/Hashes/Arrays!"
    else
      options[:entry_class].where(
          "entry_key = ? and symbol_key = ? and value = ? and value_type = ?",
          key.to_s,
          key.is_a?(Symbol),
          value.to_s,
          val_type
      ).pluck("#{options[:parent_assoc_name]}_id".to_sym)
    end
  end
end
sanity_check(options) click to toggle source

Sanity checks! @param [Hash] options the options hash to check for emptyness and Hashiness

# File lib/eav_hashes/util.rb, line 6
def self.sanity_check(options)
  raise "options cannot be empty (and you shouldn't be calling this since you left options blank)" if
      (!options.is_a? Hash) or options.empty?
end
set_constant_from_string(str, val) click to toggle source

Set a constant from a string, even if the string contains modules. Modules are created if necessary.

# File lib/eav_hashes/util.rb, line 114
def self.set_constant_from_string(str, val)
  parent = str.deconstantize.split('::').inject(Object) do |mod, class_name|
    mod.const_defined?(class_name) ? mod.const_get(class_name) : mod.const_set(class_name, Module.new())
  end
  parent.const_set(str.demodulize.to_sym, val)
end