lib/hobo/scopes/automatic_scopes.rb in hobo-1.1.0.pre2 vs lib/hobo/scopes/automatic_scopes.rb in hobo-1.1.0.pre3

- old
+ new

@@ -265,11 +265,34 @@ klass = @klass def_scope do |*args| field, asc = args type = klass.attr_type(field) if type.nil? #a virtual attribute from an SQL alias, e.g., 'total' from 'COUNT(*) AS total' - colspec = "#{field}" # don't prepend the table name + # can also be has_many association, let's check it out + _, assoc, count = *field._?.match(/^([a-z_]+)(?:\.([a-z_]+))?/) + refl = klass.attr_type(assoc) + + if refl.respond_to?(:primary_key_name) && refl.macro == :has_many && count._?.upcase == 'COUNT' + owner_primary_key = "#{klass.quoted_table_name}.#{klass.primary_key}" + # now we have :has_many association in refl, is this a through association? + if (through = refl.through_reflection) && (source = refl.source_reflection) + # has_many through association was found and now we have a few variants: + # 1) owner.has_many -> through.belongs_to <- source.has_many (many to many, source.macro == :belongs_to ) + # 2) owner.has_many -> through.has_many -> source.belongs_to (many to one through table, source.macro == :has_many) + colspec = "(SELECT COUNT(*) AS count_all FROM #{refl.quoted_table_name} INNER JOIN #{through.quoted_table_name}" + + " ON #{source.quoted_table_name}.#{source.macro == :belongs_to ? source.klass.primary_key : through.association_foreign_key}" + + " = #{through.quoted_table_name}.#{source.macro == :belongs_to ? source.association_foreign_key : through.klass.primary_key}" + + " WHERE #{through.quoted_table_name}.#{through.primary_key_name} = #{owner_primary_key} )" + else + # simple many to one (has_many -> belongs_to) association + colspec = "(SELECT COUNT(*) as count_all FROM #{refl.quoted_table_name}" + + " WHERE #{refl.quoted_table_name}.#{refl.primary_key_name} = #{owner_primary_key})" + end + + else + colspec = "#{field}" # don't prepend the table name + end elsif type.respond_to?(:name_attribute) && (name = type.name_attribute) include = field colspec = "#{type.table_name}.#{name}" else colspec = "#{klass.table_name}.#{field}" @@ -277,9 +300,14 @@ { :order => "#{colspec} #{asc._?.upcase}", :include => include } end when "include" + def_scope do |inclusions| + { :include => inclusions } + end + + when "includes" def_scope do |inclusions| { :include => inclusions } end when "search"