lib/og/relation.rb in og-0.31.0 vs lib/og/relation.rb in og-0.40.0

- old
+ new

@@ -1,11 +1,12 @@ require 'facet/kernel/constant' require 'facet/string/capitalized' require 'facet/ormsupport' require 'facet/inheritor' -require 'facet/annotation' +require 'facets/core/module/class_extension' + module Og # A relation between Entities. #-- # Relations are resolved in multiple passes. First @@ -51,13 +52,10 @@ end # Inflect target_class if not provided. @options[:target_class] ||= @options[target_name].to_s.singular.camelize.intern - - # FIXME: this is a hack! - # setup() rescue nil end # Get an option. def [](key) @@ -77,10 +75,12 @@ end # Is this a polymorphic relation ? def polymorphic? + # hack fix! + return false unless target_class.is_a?(Class) target_class.ann.self[:polymorphic] end # Resolve a polymorphic target class. # Overrided in subclasses. @@ -114,27 +114,35 @@ # To avoid forward declarations, references to undefined # (at the time of the creation of the relation) classes are # stored as symbols. These symbols are resolved by this # method. + # + # First attempts to find a class in the form: + # + # owner_class::class + # (ie, Article::Category) + # + # then a class of the form: + # + # class + # (ie, ::Category) #-- - # FIXME: do something more elegant here. + # The lookup is handled automatically by the #constant Facets + # method. #++ - + def symbol_to_class(sym, owner_class) - c = owner_class.name.dup - c = "::" + c unless c =~ /::/ - c.gsub!(/::[^:]*$/, '::') - c << sym.to_s + owner_class = owner_class.name + begin - return constant(c) - rescue - unless c == sym - c = sym - retry - end - end + c = "#{owner_class}::#{sym}" + const = constant(c) + owner_class = owner_class.to_s.scan(/^(.*)::(?:[^:])*$/) + end while const.class != Class && !owner_class.empty? + + return const.class == Class ? const : nil end alias_method :resolve_symbol, :symbol_to_class def resolve_targets(klass) for r in klass.relations @@ -173,36 +181,49 @@ # owner namespace. # # For example: # # class Article - # has_many Comment + # has_many :comments # ... # end + # + # generates: + # + # class Article::Comment < Comment + # end def resolve_polymorphic_relations(klass) + generated = [] + for r in klass.relations if r.polymorphic? - target_dm = r.target_class.to_s.demodulize - - r.owner_class.module_eval %{ - class #{r.owner_class}::#{target_dm} < #{r.target_class} - end - } - - # Replace the target class. - - r[:target_class] = eval("#{r.owner_class}::#{target_dm}") + + # Replace the target class by either creating or getting the + # polymorphic child if it already exists. + + r[:target_class] = if r.owner_class.constants.include?(target_dm) + r.owner_class.const_get(target_dm) + else + r.owner_class.const_set(target_dm, Class.new(r.target_class)) + end + + r.resolve_polymorphic + + generated << r[:target_class] end - - r.resolve_polymorphic end + + return generated end # Resolve the names of the relations. - + #-- + # For the target name it uses the demodulized class name. + #++ + def resolve_names(klass) for r in klass.relations target_name = if r.collection :target_plural_name else @@ -241,11 +262,10 @@ end # enchant. for r in klass.relations - # p "=== #{klass} : #{r.class} : #{r.name}" r.enchant() unless r.polymorphic_marker? end end @@ -326,7 +346,5 @@ end end end - -# * George Moschovitis <gm@navel.gr>