Permalink
Browse files

Abstract common code from BelongsToAssociation and HasOneAssociation …

…into SingularAssociation
  • Loading branch information...
1 parent bf24fe8 commit ef79b917848f07b61e3243027f5e2ce4bc006d78 @jonleighton jonleighton committed with tenderlove Jan 16, 2011
@@ -119,6 +119,7 @@ module Associations # :nodoc:
# These classes will be loaded when associations are created.
# So there is no need to eager load them.
autoload :AssociationCollection, 'active_record/associations/association_collection'
+ autoload :SingularAssociation, 'active_record/associations/singular_association'
autoload :AssociationProxy, 'active_record/associations/association_proxy'
autoload :ThroughAssociation, 'active_record/associations/through_association'
autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
@@ -7,14 +7,15 @@ module Associations
# This is the root class of all association proxies ('+ Foo' signifies an included module Foo):
#
# AssociationProxy
- # BelongsToAssociation
- # BelongsToPolymorphicAssociation
+ # SingularAssociaton
+ # HasOneAssociation
+ # HasOneThroughAssociation + ThroughAssociation
+ # BelongsToAssociation
+ # BelongsToPolymorphicAssociation
# AssociationCollection
# HasAndBelongsToManyAssociation
# HasManyAssociation
# HasManyThroughAssociation + ThroughAssociation
- # HasOneAssociation
- # HasOneThroughAssociation + ThroughAssociation
#
# Association proxies in Active Record are middlemen between the object that
# holds the association, known as the <tt>@owner</tt>, and the actual associated
@@ -1,19 +1,7 @@
module ActiveRecord
# = Active Record Belongs To Associations
module Associations
- class BelongsToAssociation < AssociationProxy #:nodoc:
- def create(attributes = {})
- new_record(:create_association, attributes)
- end
-
- def create!(attributes = {})
- build(attributes).tap { |record| record.save! }
- end
-
- def build(attributes = {})
- new_record(:build_association, attributes)
- end
-
+ class BelongsToAssociation < SingularAssociation #:nodoc:
def replace(record)
record = record.target if AssociationProxy === record
raise_on_type_mismatch(record) if record
@@ -34,12 +22,6 @@ def updated?
end
private
- def new_record(method, attributes)
- record = scoped.scoping { @reflection.send(method, attributes) }
- replace(record)
- record
- end
-
def update_counters(record)
counter_cache_name = @reflection.counter_cache_column
@@ -1,19 +1,7 @@
module ActiveRecord
# = Active Record Belongs To Has One Association
module Associations
- class HasOneAssociation < AssociationProxy #:nodoc:
- def create(attributes = {})
- new_record(:create_association, attributes)
- end
-
- def create!(attributes = {})
- build(attributes).tap { |record| record.save! }
- end
-
- def build(attributes = {})
- new_record(:build_association, attributes)
- end
-
+ class HasOneAssociation < SingularAssociation #:nodoc:
def replace(record, save = true)
record = record.target if AssociationProxy === record
raise_on_type_mismatch(record) unless record.nil?
@@ -52,12 +40,11 @@ def association_scope
alias creation_attributes construct_owner_attributes
# The reason that the save param for replace is false, if for create (not just build),
- # is because the setting of the foreign keys is actually handled by the scoping, and
- # so they are set straight away and do not need to be updated within replace.
- def new_record(method, attributes)
- record = scoped.scoping { @reflection.send(method, attributes) }
+ # is because the setting of the foreign keys is actually handled by the scoping when
+ # the record is instantiated, and so they are set straight away and do not need to be
+ # updated within replace.
+ def set_new_record(record)
replace(record, false)
- record
end
def remove_target!(method)
@@ -0,0 +1,31 @@
+module ActiveRecord
+ module Associations
+ class SingularAssociation < AssociationProxy #:nodoc:
+ def create(attributes = {})
+ record = scoped.scoping { @reflection.create_association(attributes) }
+ set_new_record(record)
+ record
+ end
+
+ def create!(attributes = {})
+ build(attributes).tap { |record| record.save! }
+ end
+
+ def build(attributes = {})
+ record = scoped.scoping { @reflection.build_association(attributes) }
+ set_new_record(record)
+ record
+ end
+
+ private
+ # Implemented by subclasses
+ def replace(record)
+ raise NotImplementedError
+ end
+
+ def set_new_record(record)
+ replace(record)
+ end
+ end
+ end
+end

0 comments on commit ef79b91

Please sign in to comment.