lib/og/relation.rb in og-0.20.0 vs lib/og/relation.rb in og-0.21.0

- old
+ new

@@ -7,228 +7,252 @@ # A relation between Entities. class Relation - attr_accessor :options - - attr_accessor :is_polymorphic - - # A generalized initialize method for all relations. - # Contains common setup code. - - def initialize(args, options = {}) - @options = options - @options.update(args.pop) if args.last.is_a?(Hash) + attr_accessor :options + + attr_accessor :is_polymorphic + + # A generalized initialize method for all relations. + # Contains common setup code. + + def initialize(args, options = {}) + @options = options + @options.update(args.pop) if args.last.is_a?(Hash) - if args.empty? or (not (args.last.is_a?(Class) or args.last.is_a?(Symbol))) - raise 'Class of target not defined' - end + if args.empty? or (not (args.last.is_a?(Class) or args.last.is_a?(Symbol))) + raise 'Class of target not defined' + end - @options[:target_class] = args.pop + @options[:target_class] = args.pop - if target_class == Object - # If the target class is just an Object mark that class - # as a polymorphic parent class. - # This class acts as template - # to generate customized versions of this class. + if target_class == Object + # If the target class is just an Object mark that class + # as a polymorphic parent class. + # This class acts as template + # to generate customized versions of this class. - owner_class.meta(:polymorphic, owner_class) - elsif target_class.respond_to?(:metadata) and target_class.metadata.polymorphic - # If the target class is polymorphic, create a specialized - # version of the class enclosed in the owner namespace. - - target_dm = target_class.to_s.demodulize - owner_class.module_eval %{ - class #{owner_class}::#{target_dm} < #{target_class} - end - } - eval %{ - @options[:target_class] = #{owner_class}::#{target_dm} - } - end - - target_name = if collection - :target_plural_name - else - :target_singular_name - end - - # Inflect the relation name. - - unless args.empty? - @options[target_name] = args.first - else - @options[target_name] = if collection - target_class.to_s.demodulize.underscore.downcase.plural.intern - else - target_class.to_s.demodulize.underscore.downcase.intern - end - end - - @options[:name] = options[target_name] - end + owner_class.meta(:polymorphic, owner_class) + elsif target_class.respond_to?(:metadata) and target_class.metadata.polymorphic + # If the target class is polymorphic, create a specialized + # version of the class enclosed in the owner namespace. + + target_dm = target_class.to_s.demodulize + owner_class.module_eval %{ + class #{owner_class}::#{target_dm} < #{target_class} + end + } + eval %{ + @options[:target_class] = #{owner_class}::#{target_dm} + } + end + + target_name = if collection + :target_plural_name + else + :target_singular_name + end + + # Inflect the relation name. + + unless args.empty? + @options[target_name] = args.first + else + @options[target_name] = if collection + target_class.to_s.demodulize.underscore.downcase.plural.intern + else + target_class.to_s.demodulize.underscore.downcase.intern + end + end + + @options[:name] = options[target_name] + end - def [](key) - @options[key] - end + def [](key) + @options[key] + end - def []=(key, val) - @options[key] = val - end + def []=(key, val) + @options[key] = val + end - # Is the relation polymorphic? - - def polymorphic? - target_class == Object - end + # Is the relation polymorphic? + + def polymorphic? + target_class == Object + end - #-- - # gmosx, TODO: remove, this is not really needed. - #++ - - def resolve_options - @options[:owner_pk], @options[:owner_pkclass] = owner_class.primary_key - if target_class.respond_to?(:primary_key) - @options[:target_pk], @options[:target_pkclass] = target_class.primary_key - end - end + #-- + # gmosx, TODO: remove, this is not really needed. + #++ + + def resolve_options + @options[:owner_pk], @options[:owner_pkclass] = owner_class.primary_key + if target_class.respond_to?(:primary_key) + @options[:target_pk], @options[:target_pkclass] = target_class.primary_key + end + end - # 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. - #-- - # FIXME: do something more elegant here. - #++ + # 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. + #-- + # FIXME: do something more elegant here. + #++ - def resolve_target - if target_class.is_a?(Symbol) - c = owner_class.name.dup - c = "::" + c unless c =~ /::/ - c.gsub!(/::.*$/, '::') - c << target_class.to_s - begin - klass = constant(c) - rescue - unless c == target_class - c = target_class - retry - end - end - @options[:target_class] = klass - end - end + def resolve_symbol(sym, owner_class) + c = owner_class.name.dup + c = "::" + c unless c =~ /::/ + c.gsub!(/::.*$/, '::') + c << sym.to_s + begin + return constant(c) + rescue + unless c == sym + c = sym + retry + end + end + end - # Resolve a polymorphic target class. - # Overrided in subclasses. - - def resolve_polymorphic - end - - # This method is implemented in subclasses. - - def enchant - end + def resolve_target + if target_class.is_a?(Symbol) + klass = resolve_symbol(target_class, owner_class) + @options[:target_class] = klass + end + end + +=begin + def resolve_target + if target_class.is_a?(Symbol) + c = owner_class.name.dup + c = "::" + c unless c =~ /::/ + c.gsub!(/::.*$/, '::') + c << target_class.to_s + begin + klass = constant(c) + rescue + unless c == target_class + c = target_class + retry + end + end + @options[:target_class] = klass + end + end +=end - # Access the hash values as methods. + # Resolve a polymorphic target class. + # Overrided in subclasses. + + def resolve_polymorphic + end + + # This method is implemented in subclasses. + + def enchant + end - def method_missing(sym, *args) - return @options[sym] - end + # Access the hash values as methods. - class << self + def method_missing(sym, *args) + return @options[sym] + end - def resolve(klass, action) - if klass.__meta[:relations] - for relation in klass.__meta[:relations] - relation.send(action) - end - end - end - - def enchant(klass) - if klass.__meta[:relations] - for relation in klass.__meta[:relations] - relation.enchant unless relation.target_class == Object - end - end - end + class << self - end + def resolve(klass, action) + if klass.__meta[:relations] + for relation in klass.__meta[:relations] + relation.send(action) + end + end + end + + def enchant(klass) + if klass.__meta[:relations] + for relation in klass.__meta[:relations] + relation.enchant unless relation.target_class == Object + end + end + end + end + end # Relation macros. These macros are used to define Entity # relations. module RelationMacros - def self.append_features(base) - super - base.extend(ClassMethods) - end + def self.append_features(base) + super + base.extend(ClassMethods) + end - module ClassMethods + module ClassMethods - # === Examples - # - # belongs_to Article - # belongs_to :article, Article - # belongs_to :article, Article, :view => 'lala' - - def belongs_to(*args) - require 'og/relation/belongs_to' - meta :relations, Og::BelongsTo.new(args, :owner_class => self) - end + # === Examples + # + # belongs_to Article + # belongs_to :article, Article + # belongs_to :article, Article, :view => 'lala' + + def belongs_to(*args) + require 'og/relation/belongs_to' + meta :relations, Og::BelongsTo.new(args, :owner_class => self) + end - # === Examples - # - # refers_to Topic - - def refers_to(*args) - require 'og/relation/refers_to' - meta :relations, Og::RefersTo.new(args, :owner_class => self) - end + # === Examples + # + # refers_to Topic + + def refers_to(*args) + require 'og/relation/refers_to' + meta :relations, Og::RefersTo.new(args, :owner_class => self) + end - # === Examples - # - # has_one User - - def has_one(*args) - require 'og/relation/has_one' - meta :relations, Og::HasOne.new(args, :owner_class => self) - end - - # === Examples - # - # has_many Comment - # has_many :comments, Comment - - def has_many(*args) - require 'og/relation/has_many' - meta :relations, Og::HasMany.new(args, :owner_class => self, :collection => true) - end + # === Examples + # + # has_one User + + def has_one(*args) + require 'og/relation/has_one' + meta :relations, Og::HasOne.new(args, :owner_class => self) + end + + # === Examples + # + # has_many Comment + # has_many :comments, Comment + + def has_many(*args) + require 'og/relation/has_many' + meta :relations, Og::HasMany.new(args, :owner_class => self, :collection => true) + end - def joins_many(*args) - require 'og/relation/joins_many' - meta :relations, Og::JoinsMany.new(args, :owner_class => self, :collection => true) - end - - def many_to_many(*args) - require 'og/relation/many_to_many' - meta :relations, Og::ManyToMany.new(args, :owner_class => self, :collection => true) - end + def joins_many(*args) + require 'og/relation/joins_many' + meta :relations, Og::JoinsMany.new(args, :owner_class => self, :collection => true) + end + + def many_to_many(*args) + require 'og/relation/many_to_many' + meta :relations, Og::ManyToMany.new(args, :owner_class => self, :collection => true) + end - def inspect_relations - __meta[:relations] - end - alias_method :relations, :inspect_relations + def inspect_relations + __meta[:relations] + end + alias_method :relations, :inspect_relations - def inspect_relation(name) - __meta[:relations].find { |r| r[:name] == name } - end - alias_method :relation, :inspect_relation - - end + def inspect_relation(name) + __meta[:relations].find { |r| r[:name] == name } + end + alias_method :relation, :inspect_relation + + end end end