Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 9084

Show
Ignore:
Timestamp:
03/24/08 02:50:02 (2 years ago)
Author:
rick
Message:

Merge the has_finder gem, renamed as 'named_scope'. Closes #11404 [nkallen]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r9067 r9084  
    11*SVN* 
     2 
     3* Merge the has_finder gem, renamed as 'named_scope'.  #11404 [nkallen] 
     4 
     5  class Article < ActiveRecord::Base 
     6    has_finder :published, :conditions => {:published => true} 
     7    has_finder :popular, :conditions => ... 
     8  end 
     9 
     10  Article.published.paginate(:page => 1) 
     11  Article.published.popular.count 
     12  Article.popular.find(:first) 
     13  Article.popular.find(:all, :conditions => {...}) 
     14 
     15  See http://pivots.pivotallabs.com/users/nick/blog/articles/284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries 
    216 
    317* Add has_one :through support.  #4756 [thechrisoshow] 
  • trunk/activerecord/lib/active_record.rb

    r8672 r9084  
    3838 
    3939require 'active_record/base' 
     40require 'active_record/named_scope' 
    4041require 'active_record/observer' 
    4142require 'active_record/query_cache' 
     
    6566  include ActiveRecord::Timestamp 
    6667  include ActiveRecord::Associations 
     68  include ActiveRecord::NamedScope 
    6769  include ActiveRecord::AssociationPreload 
    6870  include ActiveRecord::Aggregations 
  • trunk/activerecord/lib/active_record/associations.rb

    r9075 r9084  
    11341134          end 
    11351135        end 
    1136  
     1136         
    11371137        def add_multiple_associated_save_callbacks(association_name) 
    11381138          method_name = "validate_associated_records_for_#{association_name}".to_sym 
  • trunk/activerecord/lib/active_record/associations/association_collection.rb

    r9068 r9084  
    4242        reset_target! 
    4343      end 
    44  
     44       
    4545      # Calculate sum using SQL, not Enumerable 
    4646      def sum(*args) 
     
    169169              super 
    170170            end 
    171           else 
    172             @reflection.klass.send(:with_scope, construct_scope) do 
     171          elsif @reflection.klass.scopes.include?(method) 
     172            @reflection.klass.scopes[method].call(self, *args) 
     173          else           
     174            with_scope(construct_scope) do 
    173175              if block_given? 
    174176                @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) } 
  • trunk/activerecord/lib/active_record/associations/association_proxy.rb

    r8957 r9084  
    120120        end 
    121121 
     122        def with_scope(*args, &block) 
     123          @reflection.klass.send :with_scope, *args, &block 
     124        end 
     125           
    122126      private 
    123127        def method_missing(method, *args) 
  • trunk/activerecord/lib/active_record/associations/has_many_association.rb

    r8571 r9084  
    168168          create_scoping = {} 
    169169          set_belongs_to_association_for(create_scoping) 
    170           { :find => { :conditions => @finder_sql, :readonly => false, :order => @reflection.options[:order], :limit => @reflection.options[:limit] }, :create => create_scoping } 
     170          { 
     171            :find => { :conditions => @finder_sql, :readonly => false, :order => @reflection.options[:order], :limit => @reflection.options[:limit] }, 
     172            :create => create_scoping 
     173          } 
    171174        end 
    172175    end 
  • trunk/activerecord/lib/active_record/associations/has_many_through_association.rb

    r8989 r9084  
    140140              super 
    141141            end 
    142           else 
    143             @reflection.klass.send(:with_scope, construct_scope) do 
     142          elsif @reflection.klass.scopes.include?(method) 
     143            @reflection.klass.scopes[method].call(self, *args) 
     144          else 
     145            with_scope construct_scope do 
    144146              if block_given? 
    145147                @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) } 
  • trunk/activerecord/test/cases/associations/cascaded_eager_loading_test.rb

    r8681 r9084  
    6262  def test_eager_association_loading_with_has_many_sti 
    6363    topics = Topic.find(:all, :include => :replies, :order => 'topics.id') 
    64     assert_equal topics(:first, :second), topics 
     64    first, second, = topics(:first).replies.size, topics(:second).replies.size 
    6565    assert_no_queries do 
    66       assert_equal 1, topics[0].replies.size 
    67       assert_equal 0, topics[1].replies.size 
     66      assert_equal first, topics[0].replies.size 
     67      assert_equal second, topics[1].replies.size 
    6868    end 
    6969  end 
     
    7171  def test_eager_association_loading_with_belongs_to_sti 
    7272    replies = Reply.find(:all, :include => :topic, :order => 'topics.id') 
    73     assert_equal [topics(:second)], replies 
     73    assert replies.include?(topics(:second)) 
     74    assert !replies.include?(topics(:first)) 
    7475    assert_equal topics(:first), assert_no_queries { replies.first.topic } 
    7576  end 
  • trunk/activerecord/test/cases/base_test.rb

    r9012 r9084  
    478478  def test_load 
    479479    topics = Topic.find(:all, :order => 'id') 
    480     assert_equal(2, topics.size) 
     480    assert_equal(4, topics.size) 
    481481    assert_equal(topics(:first).title, topics.first.title) 
    482482  end 
     
    550550 
    551551  def test_destroy_all 
    552     assert_equal 2, Topic.count 
    553  
    554     Topic.destroy_all "author_name = 'Mary'" 
    555     assert_equal 1, Topic.count 
     552    original_count = Topic.count 
     553    topics_by_mary = Topic.count(:conditions => mary = "author_name = 'Mary'") 
     554     
     555    Topic.destroy_all mary 
     556    assert_equal original_count - topics_by_mary, Topic.count 
    556557  end 
    557558 
     
    563564 
    564565  def test_delete_many 
    565     Topic.delete([1, 2]) 
    566     assert_equal 0, Topic.count 
     566    original_count = Topic.count 
     567    Topic.delete(deleting = [1, 2]) 
     568    assert_equal original_count - deleting.size, Topic.count 
    567569  end 
    568570 
     
    589591 
    590592  def test_update_all 
    591     assert_equal 2, Topic.update_all("content = 'bulk updated!'") 
     593    assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'") 
    592594    assert_equal "bulk updated!", Topic.find(1).content 
    593595    assert_equal "bulk updated!", Topic.find(2).content 
    594596 
    595     assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!']) 
     597    assert_equal Topic.count, Topic.update_all(['content = ?', 'bulk updated again!']) 
    596598    assert_equal "bulk updated again!", Topic.find(1).content 
    597599    assert_equal "bulk updated again!", Topic.find(2).content 
    598600 
    599     assert_equal 2, Topic.update_all(['content = ?', nil]) 
     601    assert_equal Topic.count, Topic.update_all(['content = ?', nil]) 
    600602    assert_nil Topic.find(1).content 
    601603  end 
     
    603605  def test_update_all_with_hash 
    604606    assert_not_nil Topic.find(1).last_read 
    605     assert_equal 2, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil) 
     607    assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil) 
    606608    assert_equal "bulk updated with hash!", Topic.find(1).content 
    607609    assert_equal "bulk updated with hash!", Topic.find(2).content 
     
    638640 
    639641  def test_delete_all 
    640     assert_equal 2, Topic.delete_all 
     642    assert Topic.count > 0 
     643     
     644    assert_equal Topic.count, Topic.delete_all 
    641645  end 
    642646 
     
    805809  def test_update_attributes! 
    806810    reply = Reply.find(2) 
    807     assert_equal "The Second Topic's of the day", reply.title 
     811    assert_equal "The Second Topic of the day", reply.title 
    808812    assert_equal "Have a nice day", reply.content 
    809813 
    810     reply.update_attributes!("title" => "The Second Topic's of the day updated", "content" => "Have a nice evening") 
     814    reply.update_attributes!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening") 
    811815    reply.reload 
    812     assert_equal "The Second Topic's of the day updated", reply.title 
     816    assert_equal "The Second Topic of the day updated", reply.title 
    813817    assert_equal "Have a nice evening", reply.content 
    814818 
    815     reply.update_attributes!(:title => "The Second Topic's of the day", :content => "Have a nice day") 
     819    reply.update_attributes!(:title => "The Second Topic of the day", :content => "Have a nice day") 
    816820    reply.reload 
    817     assert_equal "The Second Topic's of the day", reply.title 
     821    assert_equal "The Second Topic of the day", reply.title 
    818822    assert_equal "Have a nice day", reply.content 
    819823 
     
    17711775    assert_equal "<topic>", xml.first(7) 
    17721776    assert xml.include?(%(<replies type="array"><reply>)) 
    1773     assert xml.include?(%(<title>The Second Topic's of the day</title>)) 
     1777    assert xml.include?(%(<title>The Second Topic of the day</title>)) 
    17741778  end 
    17751779 
  • trunk/activerecord/test/cases/finder_test.rb

    r8936 r9084  
    543543 
    544544  def test_find_all_by_array_attribute 
    545     assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic's of the day"]).size 
     545    assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic of the day"]).size 
    546546  end 
    547547 
     
    552552 
    553553    topics = Topic.find_all_by_approved(true) 
    554     assert_equal 1, topics.size 
     554    assert_equal 3, topics.size 
    555555    assert topics.include?(topics(:second)) 
    556556  end 
     
    564564  def test_find_all_by_nil_attribute 
    565565    topics = Topic.find_all_by_last_read nil 
    566     assert_equal 1, topics.size 
    567     assert_nil topics[0].last_read 
     566    assert_equal 3, topics.size 
     567    assert topics.collect(&:last_read).all?(&:nil?) 
    568568  end 
    569569 
  • trunk/activerecord/test/cases/fixtures_test.rb

    r9050 r9084  
    124124 
    125125  def test_complete_instantiation 
    126     assert_equal 2, @topics.size 
     126    assert_equal 4, @topics.size 
    127127    assert_equal "The First Topic", @first.title 
    128128  end 
  • trunk/activerecord/test/cases/lifecycle_test.rb

    r8889 r9084  
    6969 
    7070  def test_before_destroy 
    71     assert_equal 2, Topic.count 
    72     Topic.find(1).destroy 
    73     assert_equal 0, Topic.count 
     71    original_count = Topic.count 
     72    (topic_to_be_destroyed = Topic.find(1)).destroy 
     73    assert_equal original_count - (1 + topic_to_be_destroyed.replies.size), Topic.count 
    7474  end 
    7575 
  • trunk/activerecord/test/cases/validations_test.rb

    r8941 r9084  
    429429    assert t2.errors.on(:parent_id) 
    430430 
    431     t2.parent_id = 3 
     431    t2.parent_id = 4 
    432432    assert t2.save, "Should now save t2 as unique" 
    433433 
  • trunk/activerecord/test/fixtures/topics.yml

    r4579 r9084  
    1313second: 
    1414  id: 2 
    15   title: The Second Topic's of the day 
     15  title: The Second Topic of the day 
    1616  author_name: Mary 
    17   written_on: 2003-07-15t15:28:00.0099+01:00 
     17  written_on: 2004-07-15t15:28:00.0099+01:00 
    1818  content: Have a nice day 
    1919  approved: true 
     
    2121  parent_id: 1 
    2222  type: Reply 
     23 
     24third: 
     25  id: 3 
     26  title: The Third Topic of the day 
     27  author_name: Nick 
     28  written_on: 2005-07-15t15:28:00.0099+01:00 
     29  content: I'm a troll 
     30  approved: true 
     31  replies_count: 1 
     32 
     33fourth: 
     34  id: 4 
     35  title: The Fourth Topic of the day 
     36  author_name: Carl 
     37  written_on: 2006-07-15t15:28:00.0099+01:00 
     38  content: Why not? 
     39  approved: true 
     40  type: Reply 
     41  parent_id: 3 
     42 
  • trunk/activerecord/test/models/author.rb

    r8989 r9084  
    44  has_many :posts_with_categories, :include => :categories, :class_name => "Post" 
    55  has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post" 
     6  has_many :posts_containing_the_letter_a, :class_name => "Post" 
    67  has_many :posts_with_extension, :class_name => "Post" do #, :extend => ProxyTestExtension 
    78    def testing_proxy_owner 
     
    1617  end 
    1718  has_many :comments, :through => :posts 
     19  has_many :comments_containing_the_letter_e, :through => :posts, :source => :comments 
    1820  has_many :comments_desc, :through => :posts, :source => :comments, :order => 'comments.id DESC' 
    1921  has_many :limited_comments, :through => :posts, :source => :comments, :limit => 1 
  • trunk/activerecord/test/models/comment.rb

    r8735 r9084  
    11class Comment < ActiveRecord::Base 
     2  named_scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'" 
     3   
    24  belongs_to :post, :counter_cache => true 
    35 
  • trunk/activerecord/test/models/post.rb

    r8890 r9084  
    11class Post < ActiveRecord::Base 
     2  named_scope :containing_the_letter_a, :conditions => "body LIKE '%a%'" 
     3   
    24  belongs_to :author do 
    35    def greeting 
  • trunk/activerecord/test/models/topic.rb

    r8657 r9084  
    11class Topic < ActiveRecord::Base 
     2  named_scope :written_before, lambda { |time| 
     3    { :conditions => ['written_on < ?', time] } 
     4  } 
     5  named_scope :approved, :conditions => {:approved => true} 
     6  named_scope :replied, :conditions => ['replies_count > 0'] 
     7  named_scope :anonymous_extension do 
     8    def one 
     9      1 
     10    end 
     11  end 
     12  module NamedExtension 
     13    def two 
     14      2 
     15    end 
     16  end 
     17  module MultipleExtensionOne 
     18    def extension_one 
     19      1 
     20    end 
     21  end 
     22  module MultipleExtensionTwo 
     23    def extension_two 
     24      2 
     25    end 
     26  end 
     27  named_scope :named_extension, :extend => NamedExtension 
     28  named_scope :multiple_extensions, :extend => [MultipleExtensionTwo, MultipleExtensionOne] 
     29   
    230  has_many :replies, :dependent => :destroy, :foreign_key => "parent_id" 
    331  serialize :content