Skip to content

Commit

Permalink
Make our builders more instance based vs class based.
Browse files Browse the repository at this point in the history
  • Loading branch information
metaskills committed Dec 5, 2011
1 parent 913a61b commit ab0c89f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 127 deletions.
92 changes: 3 additions & 89 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,99 +1,13 @@

* Rails 3.1 Implementation

/Users/kencollins/Repositories/rails/activerecord/lib/active_record/reflection.rb - [24, 159, 331]
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations.rb - [154, 1171]
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/builder/association.rb - []
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/builder/collection_association.rb - []
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/builder/has_many.rb -
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/has_many_association.rb -
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/collection_association.rb - [370]
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/association.rb - [97]
/Users/kencollins/Repositories/rails/activerecord/lib/active_record/associations/association_scope.rb - [48]

Notes:

>> User.reflections[:boxes]
=> #<ActiveRecord::Reflection::ThroughReflection:0x007faafdddd538 @macro=:has_many, @name=:boxes, @options={:through=>:columns, :readonly=>false, :order=>"columns.position, boxes.position", :extend=>[UserBoxesAssociationExtension]}, @active_record=User(14 columns), @plural_name="boxes", @collection=true>
>> User.reflections[:boxes].source_reflection
=> #<ActiveRecord::Reflection::AssociationReflection:0x007faafdbf1d00 @macro=:has_many, @name=:boxes, @options={:order=>"position", :extend=>[]}, @active_record=Column(3 columns), @plural_name="boxes", @collection=true>
>> User.reflections[:boxes].through_reflection
=> #<ActiveRecord::Reflection::AssociationReflection:0x007faafddf4df0 @macro=:has_many, @name=:columns, @options={:order=>"position", :extend=>[]}, @active_record=User(14 columns), @plural_name="columns", @collection=true, @class_name="Column", @klass=Column(3 columns)>
>> User.reflections[:boxes].source_reflection_names
=> [:box, :boxes]
>> User.reflections[:boxes].source_options
=> {:order=>"position", :extend=>[]}
>> User.reflections[:boxes].through_options
=> {:order=>"position", :extend=>[]}
>> User.reflections[:boxes].class_name
=> "Box"


>> User.reflections[:columns].primary_key_column
=> #<ActiveRecord::ConnectionAdapters::PostgreSQLColumn:0x007fdcd859b868 @name="id", @sql_type="integer", @null=false, @limit=nil, @precision=nil, @scale=nil, @type=:integer, @default=nil, @primary=true, @coder=nil>
>> User.reflections[:columns].association_foreign_key
=> "column_id"
>> User.reflections[:columns].association_primary_key
=> "id"
>> User.reflections[:columns].active_record_primary_key
=> "id"
>> User.reflections[:columns].active_record
=> User(14 columns)


equalities = wheres.grep(Arel::Nodes::Equality)

>> ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns)).scope.where_values
User Load (0.5ms) SELECT "users".* FROM "users" LIMIT 1
=> [#<Arel::Nodes::Equality:0x007ffa41eb9c70 @left=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x007ffa41eb9f40 @name="columns", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, name="user_id">, @right=8>]

>> ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns)).send(:construct_tables)
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
=> [#<Arel::Table:0x007ffa41fccbf8 @name="columns", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>]

>> ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns))
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
Column Load (0.7ms) SELECT "columns".* FROM "columns" WHERE "columns"."user_id" = 8 ORDER BY position
=> #<ActiveRecord::Associations::AssociationScope:0x007ffa458fe9d0 @association=#<ActiveRecord::Associations::HasManyAssociation:0x007ffa458fea70 @target=[], @reflection=#<ActiveRecord::Reflection::AssociationReflection:0x007ffa46855820 @macro=:has_many, @name=:columns, @options={:order=>"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, @table_name="columns", @association_foreign_key="column_id">, @owner=#<User id: 8, email: "[email protected]", verified: true, security_token: "1b8ed73c7e8600a82bd8824d2a5b243063665b9a", token_expiry: "2010-02-07 20:44:20", created_at: "2006-12-07 17:39:27", updated_at: "2011-09-24 16:28:41", logged_in_at: "2010-02-07 00:45:11", deleted: false, delete_after: nil, uuid: "b8281ad06871012903870016cba2a0b6", iphone_verified: false, tab_links: false, password_digest: "52eb36143a4c782e202a62d5b7d64f7ce4e6ec11">, @updated=false, @loaded=false, @association_scope=nil, @proxy=[#<Column id: 3635, user_id: 8, position: 1>, #<Column id: 10, user_id: 8, position: 2>], @stale_state=nil>, @alias_tracker=#<ActiveRecord::Associations::AliasTracker:0x007ffa458fe9a8 @aliases={}, @table_joins=[]>>

>> User.first.columns.unscoped { Column.where(:position => 99) }
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
Column Load (0.9ms) SELECT "columns".* FROM "columns" WHERE "columns"."position" = 99
=> []

>> User.first.columns.unscoped { Column.where(:user_id => [1,2,3]) }
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
Column Load (0.9ms) SELECT "columns".* FROM "columns" WHERE "columns"."user_id" IN (1, 2, 3)
=> [#<Column id: 1, user_id: 1, position: 5>, #<Column id: 2, user_id: 1, position: 1>, #<Column id: 8, user_id: 1, position: 6>, #<Column id: 9, user_id: 1, position: 4>, #<Column id: 809, user_id: 1, position: 2>, #<Column id: 3395, user_id: 1, position: 3>]

>> User.reflections[:columns].association_class
=> ActiveRecord::Associations::HasManyAssociation

>> User.reflections[:columns].association_foreign_key
=> "column_id"

>> User.reflect_on_all_associations(:has_many).detect { |a| a.name == :columns }
=> #<ActiveRecord::Reflection::AssociationReflection:0x007ffa46855820 @macro=:has_many, @name=:columns, @options={:order=>"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, @table_name="columns", @association_foreign_key="column_id">
* Kill &block stuff.

>> User.reflections[:columns]
=> #<ActiveRecord::Reflection::AssociationReflection:0x007ffa46855820 @macro=:has_many, @name=:columns, @options={:order=>"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>
* Make association conditions use pure SQL. Avoid 100s of IDs.

>> User.reflect_on_association(:columns)
=> #<ActiveRecord::Reflection::AssociationReflection:0x007ffa46855820 @macro=:has_many, @name=:columns, @options={:order=>"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>

>> User.first.association(:columns)
=> #<ActiveRecord::Associations::HasManyAssociation:0x007ffa464a7480 @target=[], @reflection=#<ActiveRecord::Reflection::AssociationReflection:0x007ffa46855820 @macro=:has_many, @name=:columns, @options={:order=>"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>, @owner=#<User id: 8, email: "[email protected]", verified: true, security_token: "1b8ed73c7e8600a82bd8824d2a5b243063665b9a", token_expiry: "2010-02-07 20:44:20", created_at: "2006-12-07 17:39:27", updated_at: "2011-09-24 16:28:41", logged_in_at: "2010-02-07 00:45:11", deleted: false, delete_after: nil, uuid: "b8281ad06871012903870016cba2a0b6", iphone_verified: false, tab_links: false, password_digest: "52eb36143a4c782e202a62d5b7d64f7ce4e6ec11">, @updated=false, @loaded=false, @association_scope=nil, @proxy=[#<Column id: 3635, user_id: 8, position: 1>, #<Column id: 10, user_id: 8, position: 2>], @stale_state=nil>


* Try out altering the #association_scope wheres after the fact vs a monkey patched version.

* Use appraisal for rails dep testing.
https://github.com/thoughtbot/appraisal

* Redo for rails 3.1 tests.

* Kill &block stuff.

* Make association conditions use pure SQL. Avoid 100's of IDs.



1 change: 1 addition & 0 deletions lib/grouped_scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

require 'grouped_scope/arish/reflection'
require 'grouped_scope/arish/associations/collection_association'
require 'grouped_scope/arish/associations/builder/grouped_association'
require 'grouped_scope/arish/associations/builder/grouped_collection_association'
require 'grouped_scope/arish/associations/association_scope'
require 'grouped_scope/arish/relation/predicate_builer'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module GroupedScope
module Arish
module Associations
module Builder
class GroupedAssociation

attr_reader :model, :ungrouped_name, :ungrouped_reflection, :grouped_name, :grouped_options

def self.build(model, *association_names)
association_names.each { |ungrouped_name| new(model, ungrouped_name).build }
end

def initialize(model, ungrouped_name)
@model = model
@ungrouped_name = ungrouped_name
@ungrouped_reflection = find_ungrouped_reflection
@grouped_name = :"grouped_scope_#{ungrouped_name}"
@grouped_options = copy_ungrouped_reflection_options
end

def build
model.send(ungrouped_reflection.macro, grouped_name, grouped_options).tap do |grouped_reflection|
grouped_reflection.grouped_scope = true
model.grouped_reflections = model.grouped_reflections.merge(ungrouped_name => grouped_reflection)
define_grouped_scope_reader(model)
end
end


private

def define_grouped_scope_reader(model)
model.send(:define_method, :group) do
@group ||= GroupedScope::SelfGroupping.new(self)
end
end

def find_ungrouped_reflection
model.reflections[ungrouped_name]
end

def copy_ungrouped_reflection_options
ungrouped_reflection.options.dup
end

end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,27 @@ module GroupedScope
module Arish
module Associations
module Builder
class GroupedCollectionAssociation
class GroupedCollectionAssociation < GroupedAssociation

class << self

def build(model, *association_names)
association_names.each do |name|
ungrouped_reflection = find_ungrouped_reflection(model, name)
options = ungrouped_reflection_options(ungrouped_reflection)
grouped_reflection = model.send ungrouped_reflection.macro, :"grouped_scope_#{name}", options
grouped_reflection.grouped_scope = true
model.grouped_reflections = model.grouped_reflections.merge(name => grouped_reflection)
end
define_grouped_scope_reader(model)
end

private

def define_grouped_scope_reader(model)
model.send(:define_method, :group) do
@group ||= GroupedScope::SelfGroupping.new(self)
end
end

def find_ungrouped_reflection(model, name)
reflection = model.reflections[name.to_sym]
if reflection.blank? || [:has_many, :has_and_belongs_to_many].exclude?(reflection.macro)
msg = "Cannot create a group scope for #{name.inspect}. Either the reflection is blank or not supported. " +
"Make sure to call grouped_scope after the association you are trying to extend has been defined."
raise ArgumentError, msg
end
reflection
private

def find_ungrouped_reflection
reflection = model.reflections[ungrouped_name]
if reflection.blank? || [:has_many, :has_and_belongs_to_many].exclude?(reflection.macro)
msg = "Cannot create a group scope for #{ungrouped_name.inspect}. Either the reflection is blank or not supported. " +
"Make sure to call grouped_scope after the association you are trying to extend has been defined."
raise ArgumentError, msg
end

def ungrouped_reflection_options(ungrouped_reflection)
ungrouped_reflection.options.dup.tap do |options|
options[:class_name] = ungrouped_reflection.class_name
if ungrouped_reflection.source_reflection && options[:source].blank?
options[:source] = ungrouped_reflection.source_reflection.name
end
reflection
end

def copy_ungrouped_reflection_options
ungrouped_reflection.options.dup.tap do |options|
options[:class_name] = ungrouped_reflection.class_name
if ungrouped_reflection.source_reflection && options[:source].blank?
options[:source] = ungrouped_reflection.source_reflection.name
end
end

end

end
Expand Down

0 comments on commit ab0c89f

Please sign in to comment.