# Only needs to be an Include module for the generated classes, not for all ARs module ActiveRecord class Base class << self alias old_new new def new(*args) obj = old_new(*args) unless self.methods.include? 'generate_validations' self.send(:include, DrNicMagicModels::Validations) self.generate_validations end obj end alias old_allocate allocate def allocate obj = old_allocate unless self.methods.include? 'generate_validations' self.send(:include, DrNicMagicModels::Validations) self.generate_validations end obj end # Returns the AssociationReflection object for the named +aggregation+ (use the symbol). Example: # Account.reflect_on_association(:owner) # returns the owner AssociationReflection # Invoice.reflect_on_association(:line_items).macro # returns :has_many def reflect_on_association(association) unless reflections[association] # See if an assocation can be generated self.new.send(association) rescue nil end reflections[association].is_a?(ActiveRecord::Reflection::AssociationReflection) ? reflections[association] : nil end end class_eval do alias :normal_method_missing :method_missing def method_missing(method, *args, &block) if unknown_method? method result = find_belongs_to method, *args, &block result = find_has_some method, *args, &block if not result result = find_has_some_indirect method, *args, &block if not result return result if result end add_known_unknown method normal_method_missing(method, *args, &block) end def add_known_unknown(method) @known_unknowns ||= {} @known_unknowns[method] = true end def unknown_method?(method) @known_unknowns.nil? or @known_unknowns.include? method end def find_belongs_to(method, *args, &block) foreign_key = self.class.columns.select {|column| column.name == method.to_s.foreign_key}.first return add_belongs_to(method, *args, &block) if foreign_key end def add_belongs_to(method, *args, &block) self.class.send 'belongs_to', method self.send(method, *args, &block) end def find_has_some(method, *args, &block) klass = Module.const_get method.to_s.downcase.singularize.camelize rescue nil foreign_key = klass.columns.select {|column| column.name == self.class.name.foreign_key}.first if klass return add_has_some(method, *args, &block) if foreign_key end def add_has_some(method, *args, &block) _method = method.to_s association = _method.singularize == _method ? 'has_one' : 'has_many' self.class.send association, method self.send(method, *args, &block) end def find_has_some_indirect(method, *args, &block) klass = Module.const_get method.to_s.downcase.singularize.camelize rescue return join_table = nil self.connection.tables.each do |table| unless [self.class.table_name, klass.table_name].include? table columns = self.connection.columns(table).map(&:name) join_table = table if columns.include?(self.class.to_s.foreign_key) and columns.include?(klass.to_s.foreign_key) end break if join_table end return add_has_some_through(join_table, method, *args, &block) if join_table end def add_has_some_through(join_table, method, *args, &block) self.class.send 'has_many', method, :through => join_table.to_sym self.send(method, *args, &block) end end end end