<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -6,8 +6,8 @@ module MongoMapper
         self
       end
 
-      def many(association_id, options = {})
-        create_association(:many, association_id, options)
+      def many(association_id, options = {}, &amp;block)
+        create_association(:many, association_id, options, &amp;block)
         self
       end
 
@@ -18,13 +18,20 @@ module MongoMapper
       end
 
       private
-        def create_association(type, name, options)
+        def create_association(type, name, options, &amp;extension)
+          options[:extend] = modulized_extensions(extension, options[:extend])
           association = Associations::Base.new(type, name, options)
           associations[association.name] = association
           define_association_methods(association)
           define_dependent_callback(association)
           association
         end
+        
+        def modulized_extensions(*extensions)
+          extensions.flatten.compact.map do |extension|
+            Proc === extension ? Module.new(&amp;extension) : extension
+          end
+        end
 
         def define_association_methods(association)
           define_method(association.name) do</diff>
      <filename>lib/mongo_mapper/associations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,6 +6,7 @@ module MongoMapper
       def initialize(owner, association)
         @owner = owner
         @association = association
+        @association.options[:extend].each {|ext| proxy_extend(ext) }
         reset
       end
 </diff>
      <filename>lib/mongo_mapper/associations/proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 class BasicObject #:nodoc:
+  alias_method :proxy_extend, :extend
   instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|^methods$|instance_eval|proxy_|^object_id$)/ }
 end unless defined?(BasicObject)
 </diff>
      <filename>lib/mongo_mapper/support.rb</filename>
    </modified>
    <modified>
      <diff>@@ -129,4 +129,28 @@ class ManyEmbeddedPolymorphicProxyTest &lt; Test::Unit::TestCase
       from_db.transports[2].icu.should == true
     end
   end
-end
\ No newline at end of file
+
+  context &quot;extending the association&quot; do
+    should &quot;work using a block passed to many&quot; do
+      catalog = Catalog.new
+      medias = catalog.medias = [
+        Video.new(&quot;file&quot; =&gt; &quot;video.mpg&quot;, &quot;length&quot; =&gt; 3600, :visible =&gt; true),
+        Music.new(&quot;file&quot; =&gt; &quot;music.mp3&quot;, &quot;bitrate&quot; =&gt; &quot;128kbps&quot;, :visible =&gt; true),
+        Image.new(&quot;file&quot; =&gt; &quot;image.png&quot;, &quot;width&quot; =&gt; 800, &quot;height&quot; =&gt; 600, :visible =&gt; false)
+      ]
+      catalog.save
+      catalog.medias.visible.should == [medias[0], medias[1]]
+    end
+  
+    should &quot;work using many's :extend option&quot; do
+      fleet = TrModels::Fleet.new
+      transports = fleet.transports = [
+        TrModels::Car.new(&quot;license_plate&quot; =&gt; &quot;ABC1223&quot;, &quot;model&quot; =&gt; &quot;Honda Civic&quot;, &quot;year&quot; =&gt; 2003, :purchased_on =&gt; 2.years.ago.to_date),
+        TrModels::Bus.new(&quot;license_plate&quot; =&gt; &quot;XYZ9090&quot;, &quot;max_passengers&quot; =&gt; 51, :purchased_on =&gt; 3.years.ago.to_date),
+        TrModels::Ambulance.new(&quot;license_plate&quot; =&gt; &quot;HDD3030&quot;, &quot;icu&quot; =&gt; true, :purchased_on =&gt; 1.year.ago.to_date)
+      ]
+      fleet.save
+      fleet.transports.to_be_replaced.should == [transports[1]]
+    end
+  end
+end</diff>
      <filename>test/functional/associations/test_many_embedded_polymorphic_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -171,4 +171,29 @@ class ManyEmbeddedProxyTest &lt; Test::Unit::TestCase
     
     meg.pets.find(sparky.id).should == sparky
   end
+  
+  context &quot;extending the association&quot; do
+    should &quot;work using a block passed to many&quot; do
+      project = Project.new(:name =&gt; &quot;Some Project&quot;)
+      addr1 = Address.new(:address =&gt; &quot;Gate-3 Lankershim Blvd.&quot;, :city =&gt; &quot;Universal City&quot;, :state =&gt; &quot;CA&quot;, :zip =&gt; &quot;91608&quot;)
+      addr2 = Address.new(:address =&gt; &quot;3000 W. Alameda Ave.&quot;, :city =&gt; &quot;Burbank&quot;, :state =&gt; &quot;CA&quot;, :zip =&gt; &quot;91523&quot;)
+      addr3 = Address.new(:address =&gt; &quot;111 Some Ln&quot;, :city =&gt; &quot;Nashville&quot;, :state =&gt; &quot;TN&quot;, :zip =&gt; &quot;37211&quot;)
+      project.addresses = [addr1, addr2, addr3]
+      project.save
+      project.addresses.find_all_by_state(&quot;CA&quot;).should == [addr1, addr2]
+    end
+  
+    should &quot;work using many's :extend option&quot; do
+      project = Project.new(:name =&gt; &quot;Some Project&quot;)
+      person1 = Person.new(:name =&gt; &quot;Steve&quot;)
+      person2 = Person.new(:name =&gt; &quot;Betty&quot;)
+      person3 = Person.new(:name =&gt; &quot;Cynthia&quot;)
+
+      project.people &lt;&lt; person1
+      project.people &lt;&lt; person2
+      project.people &lt;&lt; person3
+      project.save
+      project.people.find_by_name(&quot;Steve&quot;).should == person1
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>test/functional/associations/test_many_embedded_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -294,4 +294,31 @@ class ManyPolymorphicProxyTest &lt; Test::Unit::TestCase
       end
     end
   end
+  
+  context &quot;extending the association&quot; do
+    should &quot;work using a block passed to many&quot; do
+      room = Room.new(:name =&gt; &quot;Amazing Room&quot;)
+      messages = room.messages = [
+        Enter.new(:body =&gt; 'John entered room',  :position =&gt; 3),
+        Chat.new(:body =&gt; 'Heyyyoooo!',          :position =&gt; 4),
+        Exit.new(:body =&gt; 'John exited room',    :position =&gt; 5),
+        Enter.new(:body =&gt; 'Steve entered room', :position =&gt; 6),
+        Chat.new(:body =&gt; 'Anyone there?',       :position =&gt; 7),
+        Exit.new(:body =&gt; 'Steve exited room',   :position =&gt; 8)
+      ]
+      room.save
+      room.messages.older.should == messages[3..5]
+    end
+  
+    should &quot;work using many's :extend option&quot; do
+      room = Room.new(:name =&gt; &quot;Amazing Room&quot;)
+      accounts = room.accounts = [
+        Bot.new(:last_logged_in =&gt; 3.weeks.ago),
+        User.new(:last_logged_in =&gt; nil),
+        Bot.new(:last_logged_in =&gt; 1.week.ago)
+      ]
+      room.save
+      room.accounts.inactive.should == [accounts[1]]
+    end
+  end
 end</diff>
      <filename>test/functional/associations/test_many_polymorphic_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -328,4 +328,25 @@ class ManyProxyTest &lt; Test::Unit::TestCase
       end
     end
   end
+
+  context &quot;extending the association&quot; do
+    should &quot;work using a block passed to many&quot; do
+      project = Project.new(:name =&gt; &quot;Some Project&quot;)
+      status1 = Status.new(:name =&gt; &quot;New&quot;)
+      status2 = Status.new(:name =&gt; &quot;Assigned&quot;)
+      status3 = Status.new(:name =&gt; &quot;Closed&quot;)
+      project.statuses = [status1, status2, status3]
+      project.save
+      project.statuses.open.should == [status1, status2]
+    end
+  
+    should &quot;work using many's :extend option&quot; do
+      project = Project.new(:name =&gt; &quot;Some Project&quot;)
+      collaborator1 = Collaborator.new(:name =&gt; &quot;zing&quot;)
+      collaborator2 = Collaborator.new(:name =&gt; &quot;zang&quot;)
+      project.collaborators = [collaborator1, collaborator2]
+      project.save
+      project.collaborators.top.should == collaborator1
+    end
+  end
 end</diff>
      <filename>test/functional/associations/test_many_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -78,19 +78,77 @@ class Enter &lt; Message; end
 class Exit &lt; Message;  end
 class Chat &lt; Message;  end
 
+module AccountsExtensions
+  def inactive
+    find(:all, :conditions =&gt; { :last_logged_in =&gt; nil })
+  end
+end
+
+class Account
+  include MongoMapper::Document
+  
+  key :_type, String
+  key :room_id, String
+  key :last_logged_in, Time
+  
+  belongs_to :room
+end
+class User &lt; Account; end
+class Bot &lt; Account; end
+
+
 class Room
   include MongoMapper::Document
 
   key :name, String
-  many :messages, :polymorphic =&gt; true
+  many :messages, :polymorphic =&gt; true do
+    def older
+      find(:all, :conditions =&gt; { :position =&gt; {&quot;$gt&quot; =&gt; 5} })
+    end
+  end
+  
+  many :accounts, :polymorphic =&gt; true, :extend =&gt; AccountsExtensions
 end
 
 class Project
   include MongoMapper::Document
 
   key :name, String
-  many :statuses
-  many :addresses
+  
+  module PeopleExtensions
+    def find_by_name(name)
+      detect {|p| p.name == name }
+    end
+  end
+  many :people, :extend =&gt; PeopleExtensions
+  
+  module CollaboratorsExtensions
+    def top
+      find(:first)
+    end
+  end
+  many :collaborators, :extend =&gt; CollaboratorsExtensions
+  
+  many :statuses do
+    def open
+      find(:all, :conditions =&gt; { :name =&gt; %w(New Assigned) })
+    end
+  end
+  
+  many :addresses do
+    def find_all_by_state(state)
+      # can't use select here for some reason
+      find_all {|a| a.state == state }
+    end
+  end
+  
+end
+
+class Collaborator
+  include MongoMapper::Document
+  key :project_id, String
+  key :name, String
+  belongs_to :project
 end
 
 class Status
@@ -109,9 +167,13 @@ end
 class RealPerson
   include MongoMapper::Document
 
-  many :pets
+  key :room_id, String
   key :name, String
-
+  
+  belongs_to :room
+  
+  many :pets
+  
   def realname=(n)
     self.name = n
   end
@@ -138,6 +200,8 @@ class Media
 
   key :_type, String
   key :file, String
+  
+  key :visible, Boolean
 end
 
 class Video &lt; Media
@@ -155,8 +219,13 @@ end
 
 class Catalog
   include MongoMapper::Document
-
-  many :medias, :polymorphic =&gt; true
+  
+  many :medias, :polymorphic =&gt; true do
+    def visible
+      # for some reason we can't use select here
+      find_all {|m| m.visible? }
+    end
+  end
 end
 
 module TrModels
@@ -165,6 +234,7 @@ module TrModels
 
     key :_type, String
     key :license_plate, String
+    key :purchased_on, Date
   end
 
   class Car &lt; TrModels::Transport
@@ -189,7 +259,14 @@ module TrModels
   class Fleet
     include MongoMapper::Document
 
-    many :transports, :polymorphic =&gt; true, :class_name =&gt; &quot;TrModels::Transport&quot;
+    module TransportsExtension
+      def to_be_replaced
+        # for some reason we can't use select
+        find_all {|t| t.purchased_on &lt; 2.years.ago.to_date }
+      end
+    end
+    
+    many :transports, :polymorphic =&gt; true, :class_name =&gt; &quot;TrModels::Transport&quot;, :extend =&gt; TransportsExtension
     key :name, String
   end
 end</diff>
      <filename>test/models.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>66424ec633bcc81076c40788828529ef44212192</id>
    </parent>
  </parents>
  <author>
    <name>Rune Botten</name>
    <email>rbotten@gmail.com</email>
  </author>
  <url>http://github.com/collectiveidea/mongomapper/commit/78a20494e0c6bea89638b1348afca732a647007e</url>
  <id>78a20494e0c6bea89638b1348afca732a647007e</id>
  <committed-date>2009-10-16T17:50:54-07:00</committed-date>
  <authored-date>2009-10-16T16:49:59-07:00</authored-date>
  <message>Add a way to extend a has_many association using either a block or the :extend option

Rebased to jnunemakers master from mcmires fork

All code by mcmire</message>
  <tree>47169ab01bdcc9d87d46cbc7435e9cf391be54a0</tree>
  <committer>
    <name>Rune Botten</name>
    <email>rbotten@gmail.com</email>
  </committer>
</commit>
