Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Find with a list of ids supports limit/offset. Closes #8437.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6845 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 109926c5a3472dd08b921b7729c0457ad23dcbf8 1 parent ad4f1fd
@jeremy jeremy authored
View
2  activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Find with a list of ids supports limit/offset. #8437 [hrudududu]
+
* Optimistic locking: revert the lock version when an update fails. #7840 [plang]
* Migrations: add_column supports custom column types. #7742 [jsgarvin, Theory]
View
15 activerecord/lib/active_record/base.rb
@@ -1117,10 +1117,21 @@ def find_some(ids, options)
result = find_every(options)
- if result.size == ids.size
+ # If the user passes in a limit to find(), we need to check
+ # to see if the result is limited before just checking the
+ # size of the results.
+ expected_size =
+ if options[:limit] && ids.size > options[:limit]
+ options[:limit]
+ else
+ ids.size
+ end
+ expected_size -= options[:offset] if options[:offset]
+
+ if result.size == expected_size
result
else
- raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions}"
+ raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
end
end
View
95 activerecord/test/finder_test.rb
@@ -12,13 +12,13 @@ class FinderTest < Test::Unit::TestCase
def test_find
assert_equal(topics(:first).title, Topic.find(1).title)
end
-
+
# find should handle strings that come from URLs
# (example: Category.find(params[:id]))
def test_find_with_string
assert_equal(Topic.find(1).title,Topic.find("1").title)
end
-
+
def test_exists
assert Topic.exists?(1)
assert Topic.exists?("1")
@@ -29,15 +29,20 @@ def test_exists
assert !Topic.exists?("foo")
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
end
-
+
def test_find_by_array_of_one_id
assert_kind_of(Array, Topic.find([ 1 ]))
assert_equal(1, Topic.find([ 1 ]).length)
end
-
+
def test_find_by_ids
- assert_equal(2, Topic.find(1, 2).length)
- assert_equal(topics(:second).title, Topic.find([ 2 ]).first.title)
+ assert_equal 2, Topic.find(1, 2).size
+ assert_equal topics(:second).title, Topic.find([2]).first.title
+ end
+
+ def test_find_by_ids_with_limit_and_offset
+ assert_equal 2, Entrant.find([1,3,2], :limit => 2)
+ assert_equal 1, Entrant.find([1,3,2], :limit => 3, :offset => 2).size
end
def test_find_an_empty_array
@@ -45,14 +50,12 @@ def test_find_an_empty_array
end
def test_find_by_ids_missing_one
- assert_raises(ActiveRecord::RecordNotFound) {
- Topic.find(1, 2, 45)
- }
+ assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, 2, 45) }
end
-
+
def test_find_all_with_limit
entrants = Entrant.find(:all, :order => "id ASC", :limit => 2)
-
+
assert_equal(2, entrants.size)
assert_equal(entrants(:first).name, entrants.first.name)
end
@@ -67,12 +70,12 @@ def test_find_all_with_prepared_limit_and_offset
assert_equal(1, entrants.size)
assert_equal(entrants(:third).name, entrants.first.name)
end
-
+
def test_find_all_with_limit_and_offset_and_multiple_orderings
developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1)
assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name}
end
-
+
def test_find_with_limit_and_condition
developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7)
assert_equal(1, developers.size)
@@ -81,28 +84,28 @@ def test_find_with_limit_and_condition
def test_find_with_entire_select_statement
topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
-
+
assert_equal(1, topics.size)
assert_equal(topics(:second).title, topics.first.title)
end
-
+
def test_find_with_prepared_select_statement
topics = Topic.find_by_sql ["SELECT * FROM topics WHERE author_name = ?", "Mary"]
-
+
assert_equal(1, topics.size)
assert_equal(topics(:second).title, topics.first.title)
end
-
+
def test_find_by_sql_with_sti_on_joined_table
accounts = Account.find_by_sql("SELECT * FROM accounts INNER JOIN companies ON companies.id = accounts.firm_id")
assert_equal [Account], accounts.collect(&:class).uniq
end
-
+
def test_find_first
first = Topic.find(:first, :conditions => "title = 'The First Topic'")
assert_equal(topics(:first).title, first.title)
end
-
+
def test_find_first_failing
first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
assert_nil(first)
@@ -112,10 +115,10 @@ def test_unexisting_record_exception_handling
assert_raises(ActiveRecord::RecordNotFound) {
Topic.find(1).parent
}
-
+
Topic.find(2).topic
end
-
+
def test_find_only_some_columns
topic = Topic.find(1, :select => "author_name")
assert_raises(NoMethodError) { topic.title }
@@ -130,42 +133,42 @@ def test_find_on_array_conditions
assert Topic.find(1, :conditions => ["approved = ?", false])
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => ["approved = ?", true]) }
end
-
+
def test_find_on_hash_conditions
assert Topic.find(1, :conditions => { :approved => false })
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :approved => true }) }
end
-
+
def test_find_on_hash_conditions_with_range
assert_equal [1,2], Topic.find(:all, :conditions => { :id => 1..2 }).map(&:id).sort
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
end
-
+
def test_find_on_hash_conditions_with_multiple_ranges
assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
end
-
+
def test_find_on_multiple_hash_conditions
assert Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => false })
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "HHC", :replies_count => 1, :approved => false }) }
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
end
-
+
def test_condition_array_interpolation
assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"])
assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on
end
-
+
def test_condition_hash_interpolation
assert_kind_of Firm, Company.find(:first, :conditions => { :name => "37signals"})
assert_nil Company.find(:first, :conditions => { :name => "37signals!"})
assert_kind_of Time, Topic.find(:first, :conditions => {:id => 1}).written_on
end
-
+
def test_hash_condition_find_malformed
assert_raises(ActiveRecord::StatementInvalid) {
Company.find(:first, :conditions => { :id => 2, :dhh => true })
@@ -201,7 +204,7 @@ def test_bind_variables
Company.find(:first, :conditions => ["id=?", 2, 3, 4])
}
end
-
+
def test_bind_variables_with_quotes
Company.create("name" => "37signals' go'es agains")
assert Company.find(:first, :conditions => ["name = ?", "37signals' go'es agains"])
@@ -215,16 +218,16 @@ def test_named_bind_variables_with_quotes
def test_bind_arity
assert_nothing_raised { bind '' }
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '', 1 }
-
+
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?' }
assert_nothing_raised { bind '?', 1 }
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?', 1, 1 }
end
-
+
def test_named_bind_variables
assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
-
+
assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }])
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }])
@@ -299,11 +302,11 @@ def test_find_by_one_attribute_with_conditions
def test_find_by_one_attribute_with_several_options
assert_equal accounts(:unknown), Account.find_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
end
-
+
def test_find_by_one_missing_attribute
assert_raises(NoMethodError) { Topic.find_by_undertitle("The First Topic!") }
end
-
+
def test_find_by_invalid_method_syntax
assert_raises(NoMethodError) { Topic.fail_to_find_by_title("The First Topic") }
assert_raises(NoMethodError) { Topic.find_by_title?("The First Topic") }
@@ -323,7 +326,7 @@ def test_find_all_by_one_attribute
assert_equal [], Topic.find_all_by_title("The First Topic!!")
end
-
+
def test_find_all_by_one_attribute_with_options
topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC")
assert topics(:first), topics.last
@@ -345,19 +348,19 @@ def test_find_all_by_boolean_attribute
assert_equal 1, topics.size
assert topics.include?(topics(:second))
end
-
+
def test_find_by_nil_attribute
topic = Topic.find_by_last_read nil
assert_not_nil topic
assert_nil topic.last_read
end
-
+
def test_find_all_by_nil_attribute
topics = Topic.find_all_by_last_read nil
assert_equal 1, topics.size
assert_nil topics[0].last_read
end
-
+
def test_find_by_nil_and_not_nil_attributes
topic = Topic.find_by_last_read_and_author_name nil, "Mary"
assert_equal "Mary", topic.author_name
@@ -384,7 +387,7 @@ def test_find_or_create_from_two_attributes
assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John")
assert !another.new_record?
end
-
+
def test_find_or_create_from_one_attribute_and_hash
number_of_companies = Company.count
sig38 = Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
@@ -401,14 +404,14 @@ def test_find_or_initialize_from_one_attribute
assert_equal "38signals", sig38.name
assert sig38.new_record?
end
-
+
def test_find_or_initialize_from_two_attributes
another = Topic.find_or_initialize_by_title_and_author_name("Another topic","John")
assert_equal "Another topic", another.title
assert_equal "John", another.author_name
assert another.new_record?
end
-
+
def test_find_or_initialize_from_one_attribute_and_hash
sig38 = Company.find_or_initialize_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
assert_equal "38signals", sig38.name
@@ -431,7 +434,7 @@ def test_find_all_with_limit
assert_equal 5, first_five_developers.length
assert_equal 'David', first_five_developers.first.name
assert_equal 'fixture_5', first_five_developers.last.name
-
+
no_developers = Developer.find :all, :order => 'id ASC', :limit => 0
assert_equal 0, no_developers.length
end
@@ -440,11 +443,11 @@ def test_find_all_with_limit_and_offset
first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0
second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3
last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 8
-
+
assert_equal 3, first_three_developers.length
assert_equal 3, second_three_developers.length
assert_equal 2, last_two_developers.length
-
+
assert_equal 'David', first_three_developers.first.name
assert_equal 'fixture_4', second_three_developers.first.name
assert_equal 'fixture_9', last_two_developers.first.name
@@ -462,8 +465,8 @@ def test_find_all_with_limit_and_offset_and_multiple_order_clauses
def test_find_all_with_join
developers_on_project_one = Developer.find(
- :all,
- :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id',
+ :all,
+ :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id',
:conditions => 'project_id=1'
)
assert_equal 3, developers_on_project_one.length
Please sign in to comment.
Something went wrong with that request. Please try again.