lib/active_data/model/associations.rb in active_data-0.3.0 vs lib/active_data/model/associations.rb in active_data-1.0.0
- old
+ new
@@ -1,46 +1,115 @@
-require 'active_data/model/associations/association'
-require 'active_data/model/associations/embeds_many'
+require 'active_data/model/associations/collection/proxy'
+require 'active_data/model/associations/collection/embedded'
+require 'active_data/model/associations/collection/referenced'
+
+require 'active_data/model/associations/reflections/base'
+require 'active_data/model/associations/reflections/embeds_one'
+require 'active_data/model/associations/reflections/embeds_many'
+require 'active_data/model/associations/reflections/reference_reflection'
+require 'active_data/model/associations/reflections/references_one'
+require 'active_data/model/associations/reflections/references_many'
+
+require 'active_data/model/associations/base'
require 'active_data/model/associations/embeds_one'
+require 'active_data/model/associations/embeds_many'
+require 'active_data/model/associations/references_one'
+require 'active_data/model/associations/references_many'
+require 'active_data/model/associations/nested_attributes'
+require 'active_data/model/associations/validations'
+
module ActiveData
module Model
module Associations
extend ActiveSupport::Concern
included do
- class_attribute :_associations, instance_reader: false, instance_writer: false
+ include NestedAttributes
+ include Validations
+
+ class_attribute :_associations, :_association_aliases, instance_reader: false, instance_writer: false
self._associations = {}
+ self._association_aliases = {}
- { embeds_many: EmbedsMany, embeds_one: EmbedsOne }.each do |(name, association_class)|
- define_singleton_method name do |*args|
- association = association_class.new *args
- association.define_accessor self
- self._associations = _associations.merge(association.name => association)
+ delegate :association_names, to: 'self.class'
+
+ {
+ embeds_many: Reflections::EmbedsMany,
+ embeds_one: Reflections::EmbedsOne,
+ references_one: Reflections::ReferencesOne,
+ references_many: Reflections::ReferencesMany
+ }.each do |(name, reflection_class)|
+ define_singleton_method name do |*args, &block|
+ reflection = reflection_class.build self, generated_associations_methods, *args, &block
+ self._associations = _associations.merge(reflection.name => reflection)
+ reflection
end
end
end
module ClassMethods
+ def reflections
+ _associations
+ end
- def reflect_on_association name
- _associations[name.to_s]
+ def alias_association(alias_name, association_name)
+ reflection = reflect_on_association(association_name)
+ raise ArgumentError.new("Can't alias undefined association `#{attribute_name}` on #{self}") unless reflection
+ reflection.class.generate_methods alias_name, generated_associations_methods
+ self._association_aliases = _association_aliases.merge(alias_name.to_sym => reflection.name)
+ reflection
end
- def associations
- _associations
+ def reflect_on_association name
+ name = name.to_sym
+ _associations[_association_aliases[name] || name]
end
def association_names
_associations.keys
end
+
+ private
+
+ def attributes_for_inspect
+ (_associations.map do |name, reflection|
+ "#{name}: #{reflection.inspect}"
+ end + [super]).join(', ')
+ end
+
+ def generated_associations_methods
+ @generated_associations_methods ||= const_set(:GeneratedAssociationsMethods, Module.new)
+ .tap { |proxy| include proxy }
+ end
end
def == other
- super(other) && self.class.association_names.all? do |association|
- send(association) == other.send(association)
+ super && association_names.all? do |association|
+ public_send(association) == other.public_send(association)
end
end
+ alias_method :eql?, :==
+ def association name
+ if reflection = self.class.reflect_on_association(name)
+ (@_associations ||= {})[reflection.name] ||= reflection.build_association(self)
+ end
+ end
+
+ def apply_association_changes!
+ association_names.all? do |name|
+ association(name).apply_changes!
+ end
+ end
+
+ private
+
+ def attributes_for_inspect
+ (association_names.map do |name|
+ association = association(name)
+ "#{name}: #{association.inspect}"
+ end + [super]).join(', ')
+ end
end
end
-end
\ No newline at end of file
+end