aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2014-08-30 07:59:40 -0400
committereileencodes <eileencodes@gmail.com>2014-09-01 21:42:43 -0400
commit8e9e424fa99769b86c1d3df958ef534868543316 (patch)
treef260d5c62a443b938d43e5f0cd69f94642ad4563
parent5c057f925516e87b2bcd6701fab42c1454652cc3 (diff)
downloadrails-8e9e424fa99769b86c1d3df958ef534868543316.tar.gz
rails-8e9e424fa99769b86c1d3df958ef534868543316.tar.bz2
rails-8e9e424fa99769b86c1d3df958ef534868543316.zip
Break conditional branches into separate methods
This breaks the two branches of the `if reflection.last` and `else` to clearer see where the two methods can be refactored. Eventually we hope to remove the need for these separated methods altogether. Move the first branch outside the loop This code doesn't need to be in the loop because it it always affects the last chain. `get_bind_values` and `add_constraints` must match in this context because `get_bind_values` is the caching of `add_constraints` Use each_cons to remove need for `chain[i + 1]` The `chain[i + 1]` is confusing because it's not immediately obvious what it's trying to achieve. The use of `each_cons` makes it clear we need to get the `next_reflection`.
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb87
1 files changed, 52 insertions, 35 deletions
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index 4c47af8cb0..26fed22b4c 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -45,20 +45,20 @@ module ActiveRecord
end
def self.get_bind_values(owner, chain)
- bvs = []
- chain.each_with_index do |reflection, i|
- if reflection == chain.last
- bvs << reflection.join_id_for(owner)
- if reflection.type
- bvs << owner.class.base_class.name
- end
- else
- if reflection.type
- bvs << chain[i + 1].klass.base_class.name
- end
+ binds = []
+ last_reflection = chain.last
+
+ binds << last_reflection.join_id_for(owner)
+ if last_reflection.type
+ binds << owner.class.base_class.name
+ end
+
+ chain.each_cons(2).each do |reflection, next_reflection|
+ if reflection.type
+ binds << next_reflection.klass.base_class.name
end
end
- bvs
+ binds
end
private
@@ -96,38 +96,55 @@ module ActiveRecord
bind_value scope, column, value, tracker
end
+ def last_chain_scope(scope, table, reflection, owner, tracker, assoc_klass)
+ join_keys = reflection.join_keys(assoc_klass)
+ key = join_keys.key
+ foreign_key = join_keys.foreign_key
+
+ bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
+ scope = scope.where(table[key].eq(bind_val))
+
+ if reflection.type
+ value = owner.class.base_class.name
+ bind_val = bind scope, table.table_name, reflection.type, value, tracker
+ scope = scope.where(table[reflection.type].eq(bind_val))
+ else
+ scope
+ end
+ end
+
+ def next_chain_scope(scope, table, reflection, chain, tracker, assoc_klass, foreign_table, next_reflection)
+ join_keys = reflection.join_keys(assoc_klass)
+ key = join_keys.key
+ foreign_key = join_keys.foreign_key
+
+ constraint = table[key].eq(foreign_table[foreign_key])
+
+ if reflection.type
+ value = next_reflection.klass.base_class.name
+ bind_val = bind scope, table.table_name, reflection.type, value, tracker
+ scope = scope.where(table[reflection.type].eq(bind_val))
+ end
+
+ scope = scope.joins(join(foreign_table, constraint))
+ end
+
def add_constraints(scope, owner, assoc_klass, refl, tracker)
chain = refl.chain
scope_chain = refl.scope_chain
tables = construct_tables(chain, assoc_klass, refl, tracker)
+ reflection = chain.last
+ table = tables.last
+ scope = last_chain_scope(scope, table, reflection, owner, tracker, assoc_klass)
+
chain.each_with_index do |reflection, i|
table, foreign_table = tables.shift, tables.first
- join_keys = reflection.join_keys(assoc_klass)
- key = join_keys.key
- foreign_key = join_keys.foreign_key
-
- if reflection == chain.last
- bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
- scope = scope.where(table[key].eq(bind_val))
-
- if reflection.type
- value = owner.class.base_class.name
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
- scope = scope.where(table[reflection.type].eq(bind_val))
- end
- else
- constraint = table[key].eq(foreign_table[foreign_key])
-
- if reflection.type
- value = chain[i + 1].klass.base_class.name
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
- scope = scope.where(table[reflection.type].eq(bind_val))
- end
-
- scope = scope.joins(join(foreign_table, constraint))
+ unless reflection == chain.last
+ next_reflection = chain[i + 1]
+ scope = next_chain_scope(scope, table, reflection, chain, tracker, assoc_klass, foreign_table, next_reflection)
end
is_first_chain = i == 0