From e217f77c7b065479c4dfe80ae5f99ceb38da0f63 Mon Sep 17 00:00:00 2001
From: Mikhail Varabyou <varaby_m@modulotech.fr>
Date: Sun, 31 Mar 2024 11:09:58 +0200
Subject: [PATCH 1/4] add List#size and List#first. allow to pass range to
 List#elements. fix List#last to return typed.

---
 lib/kredis/types/list.rb | 18 +++++++---
 test/types/list_test.rb  | 72 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/lib/kredis/types/list.rb b/lib/kredis/types/list.rb
index 0c1e06f..be13695 100644
--- a/lib/kredis/types/list.rb
+++ b/lib/kredis/types/list.rb
@@ -3,12 +3,12 @@
 class Kredis::Types::List < Kredis::Types::Proxying
   prepend Kredis::DefaultValues
 
-  proxying :lrange, :lrem, :lpush, :ltrim, :rpush, :exists?, :del
+  proxying :lrange, :lrem, :lpush, :ltrim, :rpush, :exists?, :del, :llen
 
   attr_accessor :typed
 
-  def elements
-    strings_to_types(lrange(0, -1) || [], typed)
+  def elements(start = 0, stop = -1)
+    strings_to_types(lrange(start, stop) || [], typed)
   end
   alias to_a elements
 
@@ -29,10 +29,20 @@ def clear
     del
   end
 
+  def first(n = nil)
+    n ? elements(0, n - 1) : elements(0, 0).first
+  end
+
   def last(n = nil)
-    n ? lrange(-n, -1) : lrange(-1, -1).first
+    n ? elements(-n, -1) : elements(-1, -1).first
   end
 
+  def size
+    llen
+  end
+
+  alias length size
+
   private
     def set_default
       append default
diff --git a/test/types/list_test.rb b/test/types/list_test.rb
index 7507548..2052ad1 100644
--- a/test/types/list_test.rb
+++ b/test/types/list_test.rb
@@ -6,6 +6,12 @@
 class ListTest < ActiveSupport::TestCase
   setup { @list = Kredis.list "mylist" }
 
+  test "elements" do
+    @list.clear
+    @list.append %w[ 1 2 3 ]
+    assert_equal %w[ 1 2 3 ], @list.elements
+  end
+
   test "append" do
     @list.append(%w[ 1 2 3 ])
     @list << 4
@@ -43,6 +49,16 @@ class ListTest < ActiveSupport::TestCase
     assert_equal [], @list.elements
   end
 
+  test "first" do
+    @list.prepend(%w[ 1 2 3 ])
+    assert_equal "3", @list.first
+  end
+
+  test "first(n)" do
+    @list.prepend(%w[ 1 2 3 ])
+    assert_equal %w[ 3 2 ], @list.first(2)
+  end
+
   test "last" do
     @list.append(%w[ 1 2 3 ])
     assert_equal "3", @list.last
@@ -53,14 +69,15 @@ class ListTest < ActiveSupport::TestCase
     assert_equal %w[ 2 3 ], @list.last(2)
   end
 
-  test "typed as datetime" do
-    @list = Kredis.list "mylist", typed: :datetime
-
-    @list.append [ 1.day.from_now.midnight.in_time_zone("Pacific Time (US & Canada)"), 2.days.from_now.midnight.in_time_zone("UTC") ]
-    assert_equal [ 1.day.from_now.midnight, 2.days.from_now.midnight ], @list.elements
+  test "size" do
+    @list.clear
+    @list.append(%w[ 1 2 3 ])
+    assert_equal 3, @list.size
+  end
 
-    @list.remove(2.days.from_now.midnight)
-    assert_equal [ 1.day.from_now.midnight ], @list.elements
+  test "size when list removed" do
+    @list.clear
+    assert_equal 0, @list.size
   end
 
   test "exists?" do
@@ -76,7 +93,6 @@ class ListTest < ActiveSupport::TestCase
     assert_equal %w[ 2 3 ], @list.elements
   end
 
-
   test "default" do
     @list = Kredis.list "mylist", default: %w[ 1 2 3 ]
 
@@ -132,3 +148,43 @@ class ListTest < ActiveSupport::TestCase
     assert_equal [ 0, 1, 2, 3, 4, 10, 20, 30 ], Kredis.list("mylist", typed: :integer).to_a.sort
   end
 end
+
+class TypedListTest < ActiveSupport::TestCase
+  setup { @list = Kredis.list "mylist.typed", typed: :integer }
+
+  test "elements" do
+    @list.clear
+    @list.append 1, 2, 3
+    assert_equal [ 1, 2, 3 ], @list.elements
+  end
+
+  test "first" do
+    @list.prepend 1, 2, 3
+    assert_equal 3, @list.first
+  end
+
+  test "first(n)" do
+    @list.prepend 3, 2, 1
+    assert_equal [ 1, 2 ], @list.first(2)
+  end
+
+  test "last" do
+    @list.append 1, 2, 3
+    assert_equal 3, @list.last
+  end
+
+  test "last(n)" do
+    @list.append 1, 2, 3
+    assert_equal [ 2, 3 ], @list.last(2)
+  end
+
+  test "typed as datetime" do
+    @list = Kredis.list "mylist", typed: :datetime
+
+    @list.append [ 1.day.from_now.midnight.in_time_zone("Pacific Time (US & Canada)"), 2.days.from_now.midnight.in_time_zone("UTC") ]
+    assert_equal [ 1.day.from_now.midnight, 2.days.from_now.midnight ], @list.elements
+
+    @list.remove(2.days.from_now.midnight)
+    assert_equal [ 1.day.from_now.midnight ], @list.elements
+  end
+end

From a39bb28b87c113355ca384ed9afbea775ea7a25b Mon Sep 17 00:00:00 2001
From: Mikhail Varabyou <varaby_m@modulotech.fr>
Date: Thu, 23 May 2024 14:21:24 +0200
Subject: [PATCH 2/4] add Hash#expire_at.

---
 lib/kredis/types/hash.rb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/kredis/types/hash.rb b/lib/kredis/types/hash.rb
index b441a19..47210ae 100644
--- a/lib/kredis/types/hash.rb
+++ b/lib/kredis/types/hash.rb
@@ -5,7 +5,7 @@
 class Kredis::Types::Hash < Kredis::Types::Proxying
   prepend Kredis::DefaultValues
 
-  proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?
+  proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?, :expire, :expireat
 
   attr_accessor :typed
 
@@ -47,6 +47,10 @@ def values
     strings_to_types(hvals || [], typed)
   end
 
+  def expire_at(datetime)
+    expireat datetime.to_i
+  end
+
   private
     def set_default
       update(**default)

From 6681929d445bda0af0707177cfa9f3b4d8bafa36 Mon Sep 17 00:00:00 2001
From: Mikhail Varabyou <varaby_m@modulotech.fr>
Date: Sat, 19 Apr 2025 16:17:16 +0200
Subject: [PATCH 3/4] will be moved to separate pr.

---
 lib/kredis/types/hash.rb | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lib/kredis/types/hash.rb b/lib/kredis/types/hash.rb
index 47210ae..b441a19 100644
--- a/lib/kredis/types/hash.rb
+++ b/lib/kredis/types/hash.rb
@@ -5,7 +5,7 @@
 class Kredis::Types::Hash < Kredis::Types::Proxying
   prepend Kredis::DefaultValues
 
-  proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?, :expire, :expireat
+  proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?
 
   attr_accessor :typed
 
@@ -47,10 +47,6 @@ def values
     strings_to_types(hvals || [], typed)
   end
 
-  def expire_at(datetime)
-    expireat datetime.to_i
-  end
-
   private
     def set_default
       update(**default)

From 9b1100eb12070fb67a948226d0d5958552010f42 Mon Sep 17 00:00:00 2001
From: Mikhail Varabyou <varaby_m@modulotech.fr>
Date: Sat, 19 Apr 2025 16:42:15 +0200
Subject: [PATCH 4/4] add #slice and make #elements use it. remove extra #clear
 test.

---
 lib/kredis/types/list.rb | 12 ++++++++----
 test/types/list_test.rb  |  6 +-----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/lib/kredis/types/list.rb b/lib/kredis/types/list.rb
index be13695..22c7e1f 100644
--- a/lib/kredis/types/list.rb
+++ b/lib/kredis/types/list.rb
@@ -7,11 +7,15 @@ class Kredis::Types::List < Kredis::Types::Proxying
 
   attr_accessor :typed
 
-  def elements(start = 0, stop = -1)
-    strings_to_types(lrange(start, stop) || [], typed)
+  def elements
+    slice(0, -1)
   end
   alias to_a elements
 
+  def slice(start = 0, stop = -1)
+    strings_to_types(lrange(start, stop) || [], typed)
+  end
+
   def remove(*elements)
     types_to_strings(elements, typed).each { |element| lrem 0, element }
   end
@@ -30,11 +34,11 @@ def clear
   end
 
   def first(n = nil)
-    n ? elements(0, n - 1) : elements(0, 0).first
+    n ? slice(0, n - 1) : slice(0, 0).first
   end
 
   def last(n = nil)
-    n ? elements(-n, -1) : elements(-1, -1).first
+    n ? slice(-n, -1) : slice(-1, -1).first
   end
 
   def size
diff --git a/test/types/list_test.rb b/test/types/list_test.rb
index 2052ad1..10e7336 100644
--- a/test/types/list_test.rb
+++ b/test/types/list_test.rb
@@ -71,15 +71,11 @@ class ListTest < ActiveSupport::TestCase
 
   test "size" do
     @list.clear
+    assert_equal 0, @list.size
     @list.append(%w[ 1 2 3 ])
     assert_equal 3, @list.size
   end
 
-  test "size when list removed" do
-    @list.clear
-    assert_equal 0, @list.size
-  end
-
   test "exists?" do
     assert_not @list.exists?