aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/finder_methods.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2015-12-18 15:54:04 +1030
committerMatthew Draper <matthew@trebex.net>2015-12-18 15:54:04 +1030
commit04309aee82468fa4c4b3d92a533e84a96533f236 (patch)
tree4381dd87ac4d9b465d6fc18d812176889c2aceb4 /activerecord/lib/active_record/relation/finder_methods.rb
parenteaefe87c5ed33b9581906a4848163a6c32a1ee24 (diff)
downloadrails-04309aee82468fa4c4b3d92a533e84a96533f236.tar.gz
rails-04309aee82468fa4c4b3d92a533e84a96533f236.tar.bz2
rails-04309aee82468fa4c4b3d92a533e84a96533f236.zip
Implement limit & offset for ourselves
We know the query will return exactly one row for each entry in the `ids` array, so we can do all the limit/offset calculations on that array, in advance. I also split our new ordered-ids behaviour out of the existing `find_some` method: especially with this change, the conditionals were overwhelming the actual logic.
Diffstat (limited to 'activerecord/lib/active_record/relation/finder_methods.rb')
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb25
1 files changed, 19 insertions, 6 deletions
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 3aa38dcf78..fc4e891b02 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -444,6 +444,10 @@ module ActiveRecord
end
def find_some(ids)
+ return find_some_ordered(ids) unless order_values.present?
+
+ result = where(primary_key => ids).to_a
+
expected_size =
if limit_value && ids.size > limit_value
limit_value
@@ -454,18 +458,27 @@ module ActiveRecord
# 11 ids with limit 3, offset 9 should give 2 results.
if offset_value && (ids.size - offset_value < expected_size)
expected_size = ids.size - offset_value
+ end
+
+ if result.size == expected_size
+ result
else
- ids = ids.first(expected_size) if order_values.empty?
+ raise_record_not_found_exception!(ids, result.size, expected_size)
end
+ end
- result = where(primary_key => ids).to_a
+ def find_some_ordered(ids)
+ ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
+
+ result = except(:limit, :offset).where(primary_key => ids).to_a
+
+ if result.size == ids.size
+ pk_type = @klass.type_for_attribute(primary_key)
- if result.size == expected_size
- return result if order_values.present?
records_by_id = result.index_by(&:id)
- ids.collect { |id| records_by_id[id.to_i] }.compact
+ ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
else
- raise_record_not_found_exception!(ids, result.size, expected_size)
+ raise_record_not_found_exception!(ids, result.size, ids.size)
end
end