From dba62c0c95bb299c3c0023b570a7983c3c2c0d16 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Mon, 5 Dec 2011 14:47:09 -0500 Subject: [PATCH] Final Rails 3.1 notes. --- README.md | 5 +- .../arish/associations/association_scope.rb | 102 +++++------------- 2 files changed, 26 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d3df717..1f23ea4 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,8 @@ defined on the original has_many. For instance: ## Todo List -* Add polymorphic support. -* Add :through support. -* Raise errors and/or support :finder_sql/:counter_sql. +* Make group association conditions use pure SQL. Avoid many ids. +* Raise errors for :finder_sql/:counter_sql. * Add a user definable group_id schema. diff --git a/lib/grouped_scope/arish/associations/association_scope.rb b/lib/grouped_scope/arish/associations/association_scope.rb index 67feeac..7c1a047 100644 --- a/lib/grouped_scope/arish/associations/association_scope.rb +++ b/lib/grouped_scope/arish/associations/association_scope.rb @@ -2,74 +2,81 @@ module GroupedScope module Arish module Associations class AssociationScope < ActiveRecord::Associations::AssociationScope - + + private - + + # A direct copy of of ActiveRecord's AssociationScope#add_constraints. If this was + # in chunks, it would be easier to hook into. This more elegant version which supers + # up will only work for the has_many. https://gist.github.com/1434980 + # + # We will just have to monitor rails everynow and then and update this. Thankfully this + # copy is only used in a group scope. FYI, our one line change is below. def add_constraints(scope) tables = construct_tables - + chain.each_with_index do |reflection, i| table, foreign_table = tables.shift, tables.first - + if reflection.source_macro == :has_and_belongs_to_many join_table = tables.shift - + scope = scope.joins(join( join_table, table[reflection.association_primary_key]. in(join_table[reflection.association_foreign_key]) )) - + table, foreign_table = join_table, tables.first end - + if reflection.source_macro == :belongs_to if reflection.options[:polymorphic] key = reflection.association_primary_key(klass) else key = reflection.association_primary_key end - + foreign_key = reflection.foreign_key else key = reflection.foreign_key foreign_key = reflection.active_record_primary_key end - + conditions = self.conditions[i] - + if reflection == chain.last # GroupedScope changed this line. # scope = scope.where(table[key].eq(owner[foreign_key])) scope = scope.where(table[key].in(owner.group.ids)) - + if reflection.type scope = scope.where(table[reflection.type].eq(owner.class.base_class.name)) end - + conditions.each do |condition| if options[:through] && condition.is_a?(Hash) condition = { table.name => condition } end - + scope = scope.where(interpolate(condition)) end else constraint = table[key].eq(foreign_table[foreign_key]) - + if reflection.type type = chain[i + 1].klass.base_class.name constraint = constraint.and(table[reflection.type].eq(type)) end - + scope = scope.joins(join(foreign_table, constraint)) - + unless conditions.empty? scope = scope.where(sanitize(conditions, table)) end end end - + scope end @@ -77,64 +84,3 @@ def add_constraints(scope) end end end - -=begin - -# Initial #add_constraints Idea -# ----------------------------- - -super(scope).tap do |s| - case reflection.macro - when :has_many - ... - end if reflection.grouped_scope? -end - - -# Simple AssociationScope Methods -# ------------------------------- - -as = ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns)) ; as.object_id -as.klass # => Column(3 columns) -as.owner # => # -as.active_record # => User(14 columns) - - -# Reflection Stuff For Join Through -# --------------------------------- - -as.reflection -# => #"position", :extend=>[]}, @active_record=User(14 columns), @plural_name="columns", @collection=true, @class_name="Column", @klass=Column(3 columns), @foreign_key="user_id", @active_record_primary_key="id", @type=nil> - -as.reflection.association_primary_key # => "id" -as.reflection.association_foreign_key # => "column_id" - - -# How Tables Work In #add_constraints -# ----------------------------------- - -tables = as.send(:construct_tables) -table = tables.first - -key = as.reflection.foreign_key # => "user_id" -foreign_key = as.reflection.active_record_primary_key # => "id" - -table[key].eq(as.owner[foreign_key]).to_sql # => "columns"."user_id" = 8 -table[key].in([1,2,3]).to_sql # => "columns"."user_id" IN (1, 2, 3) -table[key].in(as.owner.group.ids).to_sql # => - - - - - -s = as.scope ; s.object_id -equalities = s.where_values.grep(Arel::Nodes::Equality) - -e = equalities.first -# => #, name="user_id">, @right=8> - - - - - -=end