Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added specs for NestedThrough::Reflection
Separated db into own file in spec setup
- Loading branch information
Showing
10 changed files
with
347 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,8 @@ | ||
require 'nested_has_many_through' | ||
#require 'nested_through' | ||
|
||
ActiveRecord::Associations::HasManyThroughAssociation.send :include, NestedHasManyThrough::Association | ||
require 'nested_through/reflection' | ||
ActiveRecord::Reflection::AssociationReflection.send :include, NestedThrough::Reflection | ||
ActiveRecord::Reflection::ThroughReflection.send :include, NestedThrough::Reflection | ||
|
||
# BC | ||
if defined?(ActiveRecord::Reflection::ThroughReflection) | ||
ActiveRecord::Reflection::ThroughReflection.send :include, NestedHasManyThrough::Reflection | ||
else | ||
ActiveRecord::Reflection::AssociationReflection.send :include, NestedHasManyThrough::Reflection | ||
end | ||
# | ||
#ActiveRecord::Associations::HasManyThroughAssociation.send :include, NestedHasManyThrough::Association |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
module NestedThrough | ||
# module Associations | ||
# def has_many(association_id, options = {}, &extension) | ||
# if through_association?(options[:through]) | ||
# reflection = create_has_many_reflection(association_id, options, &extension) | ||
# configure_dependency_for_has_many(reflection) | ||
# add_association_callbacks(reflection.name, reflection.options) | ||
# collection_accessor_methods(reflection, NestedThrough::NestedHasManyThroughAssociation) | ||
# else | ||
# super | ||
# end | ||
# end | ||
# | ||
# def has_one(association_id, options = {}) | ||
# if through_association?(options[:through]) | ||
# reflection = create_has_one_through_reflection(association_id, options) | ||
# association_accessor_methods(reflection, NestedThrough::NestedHasOneThroughAssociation) | ||
# else | ||
# super | ||
# end | ||
# end | ||
# | ||
# private | ||
# def through_association?(assoc_name) | ||
# reflection = reflect_on_association(assoc_name) | ||
# reflection && reflection.through_association | ||
# end | ||
# end | ||
#end | ||
## module Association | ||
## def self.included(base) | ||
## base.class_eval do | ||
## def construct_conditions | ||
## @nested_join_attributes ||= construct_nested_join_attributes | ||
## "#{@nested_join_attributes[:remote_key]} = #{@owner.quoted_id} #{@nested_join_attributes[:conditions]}" | ||
## end | ||
## | ||
## def construct_joins(custom_joins = nil) | ||
## @nested_join_attributes ||= construct_nested_join_attributes | ||
## "#{@nested_join_attributes[:joins]} #{custom_joins}" | ||
## end | ||
## end | ||
## end | ||
## | ||
## protected | ||
## # Given any belongs_to or has_many (including has_many :through) association, | ||
## # return the essential components of a join corresponding to that association, namely: | ||
## # | ||
## # * <tt>:joins</tt>: any additional joins required to get from the association's table | ||
## # (reflection.table_name) to the table that's actually joining to the active record's table | ||
## # * <tt>:remote_key</tt>: the name of the key in the join table (qualified by table name) which will join | ||
## # to a field of the active record's table | ||
## # * <tt>:local_key</tt>: the name of the key in the local table (not qualified by table name) which will | ||
## # take part in the join | ||
## # * <tt>:conditions</tt>: any additional conditions (e.g. filtering by type for a polymorphic association, | ||
## # or a :conditions clause explicitly given in the association), including a leading AND | ||
## def construct_nested_join_attributes( reflection = @reflection, | ||
## association_class = reflection.klass, | ||
## table_ids = {association_class.table_name => 1}) | ||
## if reflection.macro == :has_many && reflection.through_reflection | ||
## construct_has_many_through_attributes(reflection, table_ids) | ||
## else | ||
## construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids) | ||
## end | ||
## end | ||
## | ||
## def construct_has_many_through_attributes(reflection, table_ids) | ||
## # Construct the join components of the source association, so that we have a path from | ||
## # the eventual target table of the association up to the table named in :through, and | ||
## # all tables involved are allocated table IDs. | ||
## source_attrs = construct_nested_join_attributes(reflection.source_reflection, reflection.klass, table_ids) | ||
## | ||
## # Determine the alias of the :through table; this will be the last table assigned | ||
## # when constructing the source join components above. | ||
## through_table_alias = through_table_name = reflection.through_reflection.table_name | ||
## through_table_alias += "_#{table_ids[through_table_name]}" unless table_ids[through_table_name] == 1 | ||
## | ||
## # Construct the join components of the through association, so that we have a path to | ||
## # the active record's table. | ||
## through_attrs = construct_nested_join_attributes(reflection.through_reflection, reflection.through_reflection.klass, table_ids) | ||
## | ||
## # Any subsequent joins / filters on owner attributes will act on the through association, | ||
## # so that's what we return for the conditions/keys of the overall association. | ||
## conditions = through_attrs[:conditions] | ||
## conditions += " AND #{interpolate_sql(reflection.klass.send(:sanitize_sql, reflection.options[:conditions]))}" if reflection.options[:conditions] | ||
## | ||
## { | ||
## :joins => "%s INNER JOIN %s ON ( %s = %s.%s %s) %s %s" % [ | ||
## source_attrs[:joins], | ||
## through_table_name == through_table_alias ? through_table_name : "#{through_table_name} #{through_table_alias}", | ||
## source_attrs[:remote_key], | ||
## through_table_alias, source_attrs[:local_key], | ||
## source_attrs[:conditions], | ||
## through_attrs[:joins], | ||
## reflection.options[:joins] | ||
## ], | ||
## :remote_key => through_attrs[:remote_key], | ||
## :local_key => through_attrs[:local_key], | ||
## :conditions => conditions | ||
## } | ||
## end | ||
## | ||
## | ||
## # reflection is not has_many :through; it's a standard has_many / belongs_to instead | ||
## # TODO: see if we can defer to rails code here a bit more | ||
## def construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids) | ||
## # Determine the alias used for remote_table_name, if any. In all cases this will already | ||
## # have been assigned an ID in table_ids (either through being involved in a previous join, | ||
## # or - if it's the first table in the query - as the default value of table_ids) | ||
## remote_table_alias = remote_table_name = association_class.table_name | ||
## remote_table_alias += "_#{table_ids[remote_table_name]}" unless table_ids[remote_table_name] == 1 | ||
## | ||
## # Assign a new alias for the local table. | ||
## local_table_alias = local_table_name = reflection.active_record.table_name | ||
## if table_ids[local_table_name] | ||
## table_id = table_ids[local_table_name] += 1 | ||
## local_table_alias += "_#{table_id}" | ||
## else | ||
## table_ids[local_table_name] = 1 | ||
## end | ||
## | ||
## conditions = '' | ||
## # Add type_condition, if applicable | ||
## conditions += " AND #{association_class.send(:type_condition, remote_table_alias)}" unless association_class.descends_from_active_record? | ||
## # Add custom conditions | ||
## conditions += " AND (#{interpolate_sql(association_class.send(:sanitize_sql, reflection.options[:conditions]))})" if reflection.options[:conditions] | ||
## | ||
## if reflection.macro == :belongs_to | ||
## if reflection.options[:polymorphic] | ||
## conditions += " AND #{local_table_alias}.#{reflection.options[:foreign_type]} = #{reflection.active_record.quote_value(association_class.base_class.name.to_s)}" | ||
## end | ||
## { | ||
## :joins => reflection.options[:joins], | ||
## :remote_key => "#{remote_table_alias}.#{association_class.primary_key}", | ||
## :local_key => reflection.primary_key_name, | ||
## :conditions => conditions | ||
## } | ||
## else | ||
## # Association is has_many (without :through) | ||
## if reflection.options[:as] | ||
## conditions += " AND #{remote_table_alias}.#{reflection.options[:as]}_type = #{reflection.active_record.quote_value(reflection.active_record.base_class.name.to_s)}" | ||
## end | ||
## { | ||
## :joins => "#{reflection.options[:joins]}", | ||
## :remote_key => "#{remote_table_alias}.#{reflection.primary_key_name}", | ||
## :local_key => reflection.klass.primary_key, | ||
## :conditions => conditions | ||
## } | ||
## end | ||
## end | ||
## end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module NestedThrough | ||
# extension for ActiveRecord::Base which created NestedThrough associations | ||
module Associations | ||
def has_many(association_id, options = {}, &extension) | ||
if through_association?(options[:through]) | ||
reflection = create_has_many_reflection(association_id, options, &extension) | ||
configure_dependency_for_has_many(reflection) | ||
add_association_callbacks(reflection.name, reflection.options) | ||
collection_accessor_methods(reflection, NestedThrough::Associations::NestedHasManyThroughAssociation) | ||
else | ||
super | ||
end | ||
end | ||
|
||
def has_one(association_id, options = {}) | ||
if through_association?(options[:through]) | ||
reflection = create_has_one_through_reflection(association_id, options) | ||
association_accessor_methods(reflection, NestedThrough::Associations::NestedHasOneThroughAssociation) | ||
else | ||
super | ||
end | ||
end | ||
|
||
private | ||
def through_association?(assoc_name) | ||
reflection = reflect_on_association(assoc_name) | ||
reflection && reflection.through_association | ||
end | ||
end | ||
end |
6 changes: 6 additions & 0 deletions
6
lib/nested_through/associations/nested_has_many_through_association.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module NestedThrough | ||
module Associations | ||
class NestedHasManyThroughAssociation < ActiveRecord::Associations::HasManyThroughAssociation | ||
end | ||
end | ||
end |
6 changes: 6 additions & 0 deletions
6
lib/nested_through/associations/nested_has_one_through_association.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module NestedThrough | ||
module Associations | ||
class NestedHasOneThroughAssociation < ActiveRecord::Associations::HasOneThroughAssociation | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module NestedThrough | ||
# mixin for ActiveRecord::Reflection::AssociationReflection & ActiveRecord::Reflection::ThroughReflection | ||
module Reflection | ||
def self.included(reflection_class) | ||
reflection_class.alias_method_chain :check_validity!, :nested_through | ||
end | ||
|
||
# NestedThrough allows through source reflections | ||
def check_validity_with_nested_through! | ||
check_validity_without_nested_through! | ||
rescue ActiveRecord::HasManyThroughSourceAssociationMacroError => e | ||
raise e unless source_through? | ||
end | ||
|
||
# is this association a nested_through association? | ||
def nested_through? | ||
through_reflection && through_reflection.through_reflection | ||
end | ||
|
||
# does this association have a through source? | ||
def source_through? | ||
source_reflection && source_reflection.through_reflection | ||
end | ||
end | ||
end |
Oops, something went wrong.