mirror of https://github.com/rails/rails
Add a HasAssociation module for common code for has_* associations
This commit is contained in:
parent
0c272471fe
commit
b0498372a1
|
@ -120,6 +120,8 @@ module ActiveRecord
|
|||
# So there is no need to eager load them.
|
||||
autoload :AssociationCollection, 'active_record/associations/association_collection'
|
||||
autoload :AssociationProxy, 'active_record/associations/association_proxy'
|
||||
autoload :HasAssociation, 'active_record/associations/has_association'
|
||||
autoload :ThroughAssociation, 'active_record/associations/through_association'
|
||||
autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
|
||||
autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
|
||||
autoload :HasAndBelongsToManyAssociation, 'active_record/associations/has_and_belongs_to_many_association'
|
||||
|
|
|
@ -18,6 +18,8 @@ module ActiveRecord
|
|||
# If you need to work on all current children, new and existing records,
|
||||
# +load_target+ and the +loaded+ flag are your friends.
|
||||
class AssociationCollection < AssociationProxy #:nodoc:
|
||||
include HasAssociation
|
||||
|
||||
delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped
|
||||
|
||||
def select(select = nil)
|
||||
|
|
|
@ -4,17 +4,17 @@ module ActiveRecord
|
|||
module Associations
|
||||
# = Active Record Associations
|
||||
#
|
||||
# This is the root class of all association proxies:
|
||||
# This is the root class of all association proxies ('+ Foo' signifies an included module Foo):
|
||||
#
|
||||
# AssociationProxy
|
||||
# BelongsToAssociation
|
||||
# HasOneAssociation
|
||||
# BelongsToPolymorphicAssociation
|
||||
# AssociationCollection
|
||||
# AssociationCollection + HasAssociation
|
||||
# HasAndBelongsToManyAssociation
|
||||
# HasManyAssociation
|
||||
# HasManyThroughAssociation
|
||||
# HasOneThroughAssociation
|
||||
# HasManyThroughAssociation + ThroughAssociation
|
||||
# HasOneAssociation + HasAssociation
|
||||
# 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
|
||||
|
@ -176,43 +176,6 @@ module ActiveRecord
|
|||
@reflection.klass.send(:sanitize_sql, sql, table_name)
|
||||
end
|
||||
|
||||
# Sets the owner attributes on the given record
|
||||
# Note: does not really make sense for belongs_to associations, but this method is not
|
||||
# used by belongs_to
|
||||
def set_owner_attributes(record)
|
||||
if @owner.persisted?
|
||||
construct_owner_attributes.each { |key, value| record[key] = value }
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a has linking the owner to the association represented by the reflection
|
||||
def construct_owner_attributes(reflection = @reflection)
|
||||
attributes = {}
|
||||
if reflection.macro == :belongs_to
|
||||
attributes[reflection.association_primary_key] = @owner.send(reflection.primary_key_name)
|
||||
else
|
||||
attributes[reflection.primary_key_name] = @owner.send(reflection.active_record_primary_key)
|
||||
|
||||
if reflection.options[:as]
|
||||
attributes["#{reflection.options[:as]}_type"] = @owner.class.base_class.name
|
||||
end
|
||||
end
|
||||
attributes
|
||||
end
|
||||
|
||||
# Builds an array of arel nodes from the owner attributes hash
|
||||
def construct_owner_conditions(table = aliased_table, reflection = @reflection)
|
||||
construct_owner_attributes(reflection).map do |attr, value|
|
||||
table[attr].eq(value)
|
||||
end
|
||||
end
|
||||
|
||||
def construct_conditions
|
||||
conditions = construct_owner_conditions
|
||||
conditions << Arel.sql(sql_conditions) if sql_conditions
|
||||
aliased_table.create_and(conditions)
|
||||
end
|
||||
|
||||
# Merges into +options+ the ones coming from the reflection.
|
||||
def merge_options_from_reflection!(options)
|
||||
options.reverse_merge!(
|
||||
|
@ -312,18 +275,6 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9.2'
|
||||
# Array#flatten has problems with recursive arrays before Ruby 1.9.2.
|
||||
# Going one level deeper solves the majority of the problems.
|
||||
def flatten_deeper(array)
|
||||
array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
|
||||
end
|
||||
else
|
||||
def flatten_deeper(array)
|
||||
array.flatten
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the ID of the owner, quoted if needed.
|
||||
def owner_quoted_id
|
||||
@owner.quoted_id
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
module ActiveRecord
|
||||
module Associations
|
||||
# Included in all has_* associations (i.e. everything except belongs_to)
|
||||
module HasAssociation #:nodoc:
|
||||
protected
|
||||
# Sets the owner attributes on the given record
|
||||
def set_owner_attributes(record)
|
||||
if @owner.persisted?
|
||||
construct_owner_attributes.each { |key, value| record[key] = value }
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a hash linking the owner to the association represented by the reflection
|
||||
def construct_owner_attributes(reflection = @reflection)
|
||||
attributes = {}
|
||||
if reflection.macro == :belongs_to
|
||||
attributes[reflection.association_primary_key] = @owner.send(reflection.primary_key_name)
|
||||
else
|
||||
attributes[reflection.primary_key_name] = @owner.send(reflection.active_record_primary_key)
|
||||
|
||||
if reflection.options[:as]
|
||||
attributes["#{reflection.options[:as]}_type"] = @owner.class.base_class.name
|
||||
end
|
||||
end
|
||||
attributes
|
||||
end
|
||||
|
||||
# Builds an array of arel nodes from the owner attributes hash
|
||||
def construct_owner_conditions(table = aliased_table, reflection = @reflection)
|
||||
construct_owner_attributes(reflection).map do |attr, value|
|
||||
table[attr].eq(value)
|
||||
end
|
||||
end
|
||||
|
||||
def construct_conditions
|
||||
conditions = construct_owner_conditions
|
||||
conditions << Arel.sql(sql_conditions) if sql_conditions
|
||||
aliased_table.create_and(conditions)
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9.2'
|
||||
# Array#flatten has problems with recursive arrays before Ruby 1.9.2.
|
||||
# Going one level deeper solves the majority of the problems.
|
||||
def flatten_deeper(array)
|
||||
array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
|
||||
end
|
||||
else
|
||||
def flatten_deeper(array)
|
||||
array.flatten
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +1,10 @@
|
|||
require "active_record/associations/through_association_scope"
|
||||
require 'active_support/core_ext/object/blank'
|
||||
|
||||
module ActiveRecord
|
||||
# = Active Record Has Many Through Association
|
||||
module Associations
|
||||
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
|
||||
include ThroughAssociationScope
|
||||
include ThroughAssociation
|
||||
|
||||
alias_method :new, :build
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ module ActiveRecord
|
|||
# = Active Record Belongs To Has One Association
|
||||
module Associations
|
||||
class HasOneAssociation < AssociationProxy #:nodoc:
|
||||
include HasAssociation
|
||||
|
||||
def create(attrs = {}, replace_existing = true)
|
||||
new_record(replace_existing) do |reflection|
|
||||
attrs = merge_with_conditions(attrs)
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
require "active_record/associations/through_association_scope"
|
||||
|
||||
module ActiveRecord
|
||||
# = Active Record Has One Through Association
|
||||
module Associations
|
||||
class HasOneThroughAssociation < HasOneAssociation
|
||||
include ThroughAssociationScope
|
||||
include ThroughAssociation
|
||||
|
||||
def replace(new_value)
|
||||
create_through_record(new_value)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module ActiveRecord
|
||||
# = Active Record Through Association Scope
|
||||
# = Active Record Through Association
|
||||
module Associations
|
||||
module ThroughAssociationScope
|
||||
module ThroughAssociation
|
||||
|
||||
def scoped
|
||||
with_scope(@scope) do
|
Loading…
Reference in New Issue