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>