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