From dcee87c9fc2f16e240a90c564a82d23e9f9e9181 Mon Sep 17 00:00:00 2001 From: Miguel Grazziotin Date: Fri, 29 May 2015 17:42:54 -0300 Subject: [#20338] WIP: first basic implementation and specs --- activerecord/lib/active_record/relation/finder_methods.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 6020aa238f..e75ff6fd69 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -459,7 +459,11 @@ module ActiveRecord end if result.size == expected_size - result + # result + records_by_id = result.each_with_object(Hash.new) do |record, by_id| + by_id[record.id] = record + end + ids.first(expected_size).collect { |id| records_by_id[id] } else raise_record_not_found_exception!(ids, result.size, expected_size) end -- cgit v1.2.3 From 24389135b2eac027f3079476e776587c5f74b350 Mon Sep 17 00:00:00 2001 From: Miguel Grazziotin Date: Wed, 3 Jun 2015 20:42:52 -0300 Subject: [#20338] improving implementation, fixing and adding some more specs --- activerecord/lib/active_record/relation/finder_methods.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index e75ff6fd69..48a7d15ea8 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -459,11 +459,8 @@ module ActiveRecord end if result.size == expected_size - # result - records_by_id = result.each_with_object(Hash.new) do |record, by_id| - by_id[record.id] = record - end - ids.first(expected_size).collect { |id| records_by_id[id] } + records_by_id = result.index_by(&:id) + ids.first(expected_size).collect { |id| records_by_id[id.to_i] } else raise_record_not_found_exception!(ids, result.size, expected_size) end -- cgit v1.2.3 From 2eb6b9dd0ba5049ee3a94f2f7ec7aa2fadd69dfc Mon Sep 17 00:00:00 2001 From: Miguel Grazziotin Date: Fri, 5 Jun 2015 17:18:03 -0300 Subject: do not change the order of the result if the object was already ordered by the user via :order clause --- activerecord/lib/active_record/relation/finder_methods.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 48a7d15ea8..a0e1420055 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -459,6 +459,7 @@ module ActiveRecord end if result.size == expected_size + return result if self.values[:order] records_by_id = result.index_by(&:id) ids.first(expected_size).collect { |id| records_by_id[id.to_i] } else -- cgit v1.2.3 From 07cdbb12b35e82c17e2103d38e90b26879e792af Mon Sep 17 00:00:00 2001 From: Miguel Grazziotin Date: Fri, 19 Jun 2015 16:30:16 -0300 Subject: WIP: fixing the limit bug and introducing new tests (failing for now) on .find(array) with offset --- activerecord/lib/active_record/relation/finder_methods.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index a0e1420055..18324cf3c6 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -444,8 +444,6 @@ module ActiveRecord end def find_some(ids) - result = where(primary_key => ids).to_a - expected_size = if limit_value && ids.size > limit_value limit_value @@ -456,12 +454,16 @@ 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 + else + ids = ids.first(expected_size) unless self.values[:order] end + result = where(primary_key => ids).to_a + if result.size == expected_size return result if self.values[:order] records_by_id = result.index_by(&:id) - ids.first(expected_size).collect { |id| records_by_id[id.to_i] } + ids.collect { |id| records_by_id[id.to_i] }.compact else raise_record_not_found_exception!(ids, result.size, expected_size) end -- cgit v1.2.3 From d3b8216fda928cf26c953dfd51a9a8d7f4732608 Mon Sep 17 00:00:00 2001 From: Miguel Grazziotin Date: Fri, 19 Jun 2015 17:27:17 -0300 Subject: using order_values method instead of relying on ActiveRecord::Relation @values hash --- activerecord/lib/active_record/relation/finder_methods.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 18324cf3c6..3aa38dcf78 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -455,13 +455,13 @@ module ActiveRecord if offset_value && (ids.size - offset_value < expected_size) expected_size = ids.size - offset_value else - ids = ids.first(expected_size) unless self.values[:order] + ids = ids.first(expected_size) if order_values.empty? end result = where(primary_key => ids).to_a if result.size == expected_size - return result if self.values[:order] + return result if order_values.present? records_by_id = result.index_by(&:id) ids.collect { |id| records_by_id[id.to_i] }.compact else -- cgit v1.2.3 From 04309aee82468fa4c4b3d92a533e84a96533f236 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Fri, 18 Dec 2015 15:54:04 +1030 Subject: 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. --- .../lib/active_record/relation/finder_methods.rb | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record/relation/finder_methods.rb') 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 -- cgit v1.2.3