module ActiveRecord module EavHashes def self.included (base) base.extend ActiveRecord::EavHashes::ClassMethods end module ClassMethods def eav_hash_for (hash_name, options={}) # Fill in default options not otherwise specified options[:hash_name] = hash_name options[:parent_class_name] = self.name.to_sym options = ActiveRecord::EavHashes::Util::fill_options_hash options # Store the options hash in a class variable to create the EavHash object # if and when it's actually used. class_variable_set "@@#{hash_name}_hash_options".to_sym, options # Create the association, the entry update hook, and a helper method to lazy-load the entries class_eval <<-END_EVAL has_many :#{options[:entry_assoc_name]}, class_name: "#{options[:entry_class_name]}", foreign_key: "#{options[:parent_assoc_name]}_id", dependent: :delete_all after_save :save_#{hash_name} def #{hash_name} @#{hash_name} ||= ActiveRecord::EavHashes::EavHash.new(self, @@#{hash_name}_hash_options) end def save_#{hash_name} @#{hash_name}.save_entries if @#{hash_name} end def self.find_by_#{hash_name} (key, value=nil) self.find (ActiveRecord::EavHashes::Util::run_find_expression(key, value, @@#{hash_name}_hash_options)) end END_EVAL end end end end