From 3b91cca427e16e9838c207d113398315cc55e797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Po=C5=82e=C4=87?= Date: Fri, 22 Mar 2024 08:49:00 +0100 Subject: [PATCH 1/5] add more numeral finder methods --- lib/active_graph/node/query_methods.rb | 30 ++++++++++++++++++++++++++ spec/e2e/query_proxy_methods_spec.rb | 7 ++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/active_graph/node/query_methods.rb b/lib/active_graph/node/query_methods.rb index 5f52a1e7d..5e5c1232f 100644 --- a/lib/active_graph/node/query_methods.rb +++ b/lib/active_graph/node/query_methods.rb @@ -21,6 +21,36 @@ def last self.query_as(:n).limit(1).order(n: {primary_key => :desc}).pluck(:n).first end + # Returns the second node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def second + self.query_as(:n).order(n: primary_key).limit(1).skip(1).pluck(:n).first + end + + # Returns the third node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def third + self.query_as(:n).order(n: primary_key).limit(1).skip(2).pluck(:n).first + end + + # Returns the fourth node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def fourth + self.query_as(:n).order(n: primary_key).limit(1).skip(3).pluck(:n).first + end + + # Returns the fifth node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def fifth + self.query_as(:n).order(n: primary_key).limit(1).skip(4).pluck(:n).first + end + + # Returns the third to last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def third_to_last + self.query_as(:n).limit(1).order(n: {primary_key => :desc}).skip(2).pluck(:n).first + end + + # Returns the second to last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. + def second_to_last + self.query_as(:n).limit(1).order(n: {primary_key => :desc}).skip(1).pluck(:n).first + end + # @return [Integer] number of nodes of this class def count(distinct = nil) fail(ActiveGraph::InvalidParameterError, ':count accepts the `:distinct` symbol or nil as a parameter') unless distinct.nil? || distinct == :distinct diff --git a/spec/e2e/query_proxy_methods_spec.rb b/spec/e2e/query_proxy_methods_spec.rb index 387d10b9a..e8949d2d1 100644 --- a/spec/e2e/query_proxy_methods_spec.rb +++ b/spec/e2e/query_proxy_methods_spec.rb @@ -177,11 +177,14 @@ def destroy_called end end - describe 'first and last' do + describe 'numeral finder methods (first, last, etc.)' do it 'returns different objects' do - Student.create + 5.times { Student.create } expect(Student.all.count).to be > 1 expect(Student.all.first).to_not eq(Student.all.last) + expect(Student.all.second).to_not eq(Student.all.second_to_last) + expect(Student.all.third).to_not eq(Student.all.third_to_last) + expect(Student.all.fourth).to_not eq(Student.all.fifth) end it 'returns objects across multiple associations' do From 985b7ee84c472113902bf895ef5b9c4c9fe8430b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Po=C5=82e=C4=87?= Date: Fri, 22 Mar 2024 08:51:44 +0100 Subject: [PATCH 2/5] Extract first,second.. common code to private method --- lib/active_graph/node/query_methods.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/active_graph/node/query_methods.rb b/lib/active_graph/node/query_methods.rb index 5e5c1232f..20a98f6cf 100644 --- a/lib/active_graph/node/query_methods.rb +++ b/lib/active_graph/node/query_methods.rb @@ -13,7 +13,7 @@ def exists?(node_condition = nil) # Returns the first node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def first - self.query_as(:n).limit(1).order(n: primary_key).pluck(:n).first + find_nth(0) end # Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. @@ -23,22 +23,22 @@ def last # Returns the second node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def second - self.query_as(:n).order(n: primary_key).limit(1).skip(1).pluck(:n).first + find_nth(1) end # Returns the third node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def third - self.query_as(:n).order(n: primary_key).limit(1).skip(2).pluck(:n).first + find_nth(2) end # Returns the fourth node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def fourth - self.query_as(:n).order(n: primary_key).limit(1).skip(3).pluck(:n).first + find_nth(3) end # Returns the fifth node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def fifth - self.query_as(:n).order(n: primary_key).limit(1).skip(4).pluck(:n).first + find_nth(4) end # Returns the third to last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. @@ -93,6 +93,10 @@ def exists_query_start(node_condition) self.query_as(:n) end end + + def find_nth(index) + self.query_as(:n).order(n: primary_key).limit(1).skip(index).pluck(:n).first + end end end end From 39f7ce5acc55f791e295a3688892ef34ca9b8307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Po=C5=82e=C4=87?= Date: Fri, 22 Mar 2024 08:54:37 +0100 Subject: [PATCH 3/5] Extract 'last' methods common code to private method --- lib/active_graph/node/query_methods.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/active_graph/node/query_methods.rb b/lib/active_graph/node/query_methods.rb index 20a98f6cf..e05b41655 100644 --- a/lib/active_graph/node/query_methods.rb +++ b/lib/active_graph/node/query_methods.rb @@ -18,7 +18,7 @@ def first # Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def last - self.query_as(:n).limit(1).order(n: {primary_key => :desc}).pluck(:n).first + find_nth_from_last(0) end # Returns the second node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. @@ -43,12 +43,12 @@ def fifth # Returns the third to last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def third_to_last - self.query_as(:n).limit(1).order(n: {primary_key => :desc}).skip(2).pluck(:n).first + find_nth_from_last(2) end # Returns the second to last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def second_to_last - self.query_as(:n).limit(1).order(n: {primary_key => :desc}).skip(1).pluck(:n).first + find_nth_from_last(1) end # @return [Integer] number of nodes of this class @@ -97,6 +97,10 @@ def exists_query_start(node_condition) def find_nth(index) self.query_as(:n).order(n: primary_key).limit(1).skip(index).pluck(:n).first end + + def find_nth_from_last(index) + self.query_as(:n).order(n: {primary_key => :desc}).limit(1).skip(index).pluck(:n).first + end end end end From aaf665df0ebcc210a564c5e6135e657e13bda708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Po=C5=82e=C4=87?= Date: Fri, 22 Mar 2024 09:02:21 +0100 Subject: [PATCH 4/5] Add limit parameter to first and last methods, to get more than one record --- lib/active_graph/node/query_methods.rb | 30 +++++++++++++++++--------- spec/e2e/query_proxy_methods_spec.rb | 7 ++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/active_graph/node/query_methods.rb b/lib/active_graph/node/query_methods.rb index e05b41655..8872777ed 100644 --- a/lib/active_graph/node/query_methods.rb +++ b/lib/active_graph/node/query_methods.rb @@ -11,14 +11,16 @@ def exists?(node_condition = nil) !!result end - # Returns the first node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. - def first - find_nth(0) + # Returns the first node (or first N nodes if a parameter is supplied) of this class, sorted by ID. + # Note that this may not be the first node created since Neo4j recycles IDs. + def first(limit = 1) + find_nth(0, limit) end - # Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. - def last - find_nth_from_last(0) + # Returns the last node (or last N nodes if a parameter is supplied) of this class, sorted by ID. + # Note that this may not be the first node created since Neo4j recycles IDs. + def last(limit = 1) + find_nth_from_last(0, limit) end # Returns the second node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. @@ -94,12 +96,20 @@ def exists_query_start(node_condition) end end - def find_nth(index) - self.query_as(:n).order(n: primary_key).limit(1).skip(index).pluck(:n).first + def find_nth(index, limit = 1) + if limit == 1 + self.query_as(:n).order(n: primary_key).limit(limit).skip(index).pluck(:n).first + else + self.query_as(:n).order(n: primary_key).limit(limit).skip(index).pluck(:n).first(limit) + end end - def find_nth_from_last(index) - self.query_as(:n).order(n: {primary_key => :desc}).limit(1).skip(index).pluck(:n).first + def find_nth_from_last(index, limit = 1) + if limit == 1 + self.query_as(:n).order(n: {primary_key => :desc}).limit(limit).skip(index).pluck(:n).first + else + self.query_as(:n).order(n: {primary_key => :desc}).limit(limit).skip(index).pluck(:n).first(limit) + end end end end diff --git a/spec/e2e/query_proxy_methods_spec.rb b/spec/e2e/query_proxy_methods_spec.rb index e8949d2d1..4d5186763 100644 --- a/spec/e2e/query_proxy_methods_spec.rb +++ b/spec/e2e/query_proxy_methods_spec.rb @@ -187,6 +187,13 @@ def destroy_called expect(Student.all.fourth).to_not eq(Student.all.fifth) end + it 'allows to specify limit for first and last methods' do + Student.create + expect(Student.all.count).to be > 1 + expect(Student.first(2)).to eq([Student.all.first, Student.all.second]) + expect(Student.last(2)).to eq([Student.all.last, Student.all.second_to_last]) + end + it 'returns objects across multiple associations' do jimmy.lessons << science science.teachers << mr_adams From 80fe64892376331209e49599a76552017fdaeda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Po=C5=82e=C4=87?= Date: Fri, 22 Mar 2024 09:06:55 +0100 Subject: [PATCH 5/5] refactor query_methods #find_nth_from_last --- lib/active_graph/node/query_methods.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/active_graph/node/query_methods.rb b/lib/active_graph/node/query_methods.rb index 8872777ed..984f9ebe8 100644 --- a/lib/active_graph/node/query_methods.rb +++ b/lib/active_graph/node/query_methods.rb @@ -96,20 +96,16 @@ def exists_query_start(node_condition) end end - def find_nth(index, limit = 1) + def find_nth(index, limit = 1, order = primary_key) if limit == 1 - self.query_as(:n).order(n: primary_key).limit(limit).skip(index).pluck(:n).first + self.query_as(:n).order(n: order).limit(limit).skip(index).pluck(:n).first else - self.query_as(:n).order(n: primary_key).limit(limit).skip(index).pluck(:n).first(limit) + self.query_as(:n).order(n: order).limit(limit).skip(index).pluck(:n).first(limit) end end def find_nth_from_last(index, limit = 1) - if limit == 1 - self.query_as(:n).order(n: {primary_key => :desc}).limit(limit).skip(index).pluck(:n).first - else - self.query_as(:n).order(n: {primary_key => :desc}).limit(limit).skip(index).pluck(:n).first(limit) - end + find_nth(index, limit, {primary_key => :desc}) end end end