kredis 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72d301175c0d6bac257d10d925bddcaaa4d9fda78f0aa75264fc3b6c5a8af677
4
- data.tar.gz: aa7dd573678ca4f8bb18478cf6b606fe2afc3833e6c9b9bb9b693e361f7706ee
3
+ metadata.gz: 15ed6996059d28937ffa4f43a35e53d1e8fbc1894a30446575d9c00c390cd838
4
+ data.tar.gz: 296f80ea7719d69334d50240c9fce5969df4f8d976800013167c1fb0ebe6a0b3
5
5
  SHA512:
6
- metadata.gz: e12490fc43dd3e73dcc39dfe3af5ab0f44405eae7a071b08edb14b1cba08c4b96bdb968af61072b2329e0f5e449c8c281252f4e32f423656d77bcc5ebf0e95e0
7
- data.tar.gz: f047ac1e52365a7b25e10b2d2187df699abe34ced746f4d34b8e47511c019019eee3e9e6f69a5e46d58286a5ad5e38899d0db8517015d809b278ea46526f81b4
6
+ metadata.gz: cae34ebe3f21fe7c0e9cc0da5fc14bdc0d15931436bf7f07c552c14090489806990779ffd219be054f050468c809e23bf79302365f59f2dfced4b6a054ad352c
7
+ data.tar.gz: 96513897d1badc12f4fc6b2e51e017958f7e5eeaa5730d06bcb9d9a12d71ae09a4eb8ce2661e70a70647f4c4d7e5543a30451ab64d290b91de20d47602f30398
data/README.md CHANGED
@@ -21,11 +21,11 @@ integer.value = 5 # => SET myinteger "5"
21
21
  5 == integer.value # => GET myinteger
22
22
 
23
23
  decimal = Kredis.decimal "mydecimal" # accuracy!
24
- decimal.value = "%.47f" % (1.0/10) # => SET mydecimal "0.10000000000000000555111512312578270211815834045"
24
+ decimal.value = "%.47f" % (1.0 / 10) # => SET mydecimal "0.10000000000000000555111512312578270211815834045"
25
25
  BigDecimal("0.10000000000000000555111512312578270211815834045e0") == decimal.value # => GET mydecimal
26
26
 
27
27
  float = Kredis.float "myfloat" # speed!
28
- float.value = 1.0/10 # => SET myfloat "0.1"
28
+ float.value = 1.0 / 10 # => SET myfloat "0.1"
29
29
  0.1 == float.value # => GET myfloat
30
30
 
31
31
  boolean = Kredis.boolean "myboolean"
@@ -49,10 +49,10 @@ list = Kredis.list "mylist"
49
49
  list << "hello world!" # => RPUSH mylist "hello world!"
50
50
  [ "hello world!" ] == list.elements # => LRANGE mylist 0, -1
51
51
 
52
- integer_list = Kredis.list "myintegerlist", typed: :integer
53
- integer_list.append([ 1, 2, 3 ]) # => RPUSH myintegerlist "1" "2" "3"
54
- integer_list << 4 # => RPUSH myintegerlist "4"
55
- [ 1, 2, 3, 4 ] == integer_list.elements # => LRANGE myintegerlist 0 -1
52
+ integer_list = Kredis.list "myintegerlist", typed: :integer, default: [ 1, 2, 3 ] # => EXISTS? myintegerlist, RPUSH myintegerlist "1" "2" "3"
53
+ integer_list.append([ 4, 5, 6 ]) # => RPUSH myintegerlist "4" "5" "6"
54
+ integer_list << 7 # => RPUSH myintegerlist "7"
55
+ [ 1, 2, 3, 4, 5, 6, 7 ] == integer_list.elements # => LRANGE myintegerlist 0 -1
56
56
 
57
57
  unique_list = Kredis.unique_list "myuniquelist"
58
58
  unique_list.append(%w[ 2 3 4 ]) # => LREM myuniquelist 0, "2" + LREM myuniquelist 0, "3" + LREM myuniquelist 0, "4" + RPUSH myuniquelist "2", "3", "4"
@@ -163,15 +163,7 @@ sleep 0.6.seconds
163
163
  false == flag.marked? #=> EXISTS myflag
164
164
  ```
165
165
 
166
- And using structures on a different than the default `shared` redis instance, relying on `config/redis/secondary.yml`:
167
-
168
- ```ruby
169
- one_string = Kredis.string "mystring"
170
- two_string = Kredis.string "mystring", config: :secondary
171
-
172
- one_string.value = "just on shared"
173
- two_string.value != one_string.value
174
- ```
166
+ ### Models
175
167
 
176
168
  You can use all these structures in models:
177
169
 
@@ -197,6 +189,29 @@ person.morning.value = "blue" # => SET people:5:morning
197
189
  true == person.morning.blue? # => GET people:5:morning
198
190
  ```
199
191
 
192
+ ### Default values
193
+
194
+ You can set a default value for all types. For example:
195
+
196
+ ```ruby
197
+ list = Kredis.list "favorite_colors", default: [ "red", "green", "blue" ]
198
+
199
+ # or, in a model
200
+ class Person < ApplicationRecord
201
+ kredis_string :name, default: "Unknown"
202
+ kredis_list :favorite_colors, default: [ "red", "green", "blue" ]
203
+ end
204
+ ```
205
+
206
+ There's a performance overhead to consider though. When you first read or write an attribute in a model, Kredis will
207
+ check if the underlying Redis key exists, while watching for concurrent changes, and if it does not,
208
+ write the specified default value.
209
+
210
+ This means that using default values in a typical Rails app additional Redis calls (WATCH, EXISTS, UNWATCH) will be
211
+ executed for each Kredis attribute with a default value read or written during a request.
212
+
213
+ ### Callbacks
214
+
200
215
  You can also define `after_change` callbacks that trigger on mutations:
201
216
 
202
217
  ```ruby
@@ -209,6 +224,18 @@ class Person < ApplicationRecord
209
224
  end
210
225
  ```
211
226
 
227
+ ### Multiple Redis servers
228
+
229
+ And using structures on a different than the default `shared` redis instance, relying on `config/redis/secondary.yml`:
230
+
231
+ ```ruby
232
+ one_string = Kredis.string "mystring"
233
+ two_string = Kredis.string "mystring", config: :secondary
234
+
235
+ one_string.value = "just on shared"
236
+ two_string.value != one_string.value
237
+ ```
238
+
212
239
  ## Installation
213
240
 
214
241
  1. Run `./bin/bundle add kredis`
@@ -228,14 +255,14 @@ If you need to connect to Redis with SSL, the recommended approach is to set you
228
255
 
229
256
  ```ruby
230
257
  Kredis::Connections.connections[:shared] = Redis.new(
231
- url: ENV['REDIS_URL'],
258
+ url: ENV["REDIS_URL"],
232
259
  ssl_params: {
233
260
  cert_store: OpenSSL::X509::Store.new.tap { |store|
234
- store.add_file(Rails.root.join('config', 'ca_cert.pem').to_s)
261
+ store.add_file(Rails.root.join("config", "ca_cert.pem").to_s)
235
262
  },
236
263
 
237
264
  cert: OpenSSL::X509::Certificate.new(File.read(
238
- Rails.root.join('config', 'client.crt')
265
+ Rails.root.join("config", "client.crt")
239
266
  )),
240
267
 
241
268
  key: OpenSSL::PKey::RSA.new(
@@ -259,6 +286,29 @@ config.kredis.connector = ->(config) { SomeRedisProxy.new(config) }
259
286
 
260
287
  By default Kredis will use `Redis.new(config)`.
261
288
 
289
+ ## Development
290
+
291
+ A development console is available by running `bin/console`.
292
+
293
+ From there, you can experiment with Kredis. e.g.
294
+
295
+ ```erb
296
+ >> str = Kredis.string "mystring"
297
+ Kredis (0.1ms) Connected to shared
298
+ =>
299
+ #<Kredis::Types::Scalar:0x0000000134c7d938
300
+ ...
301
+ >> str.value = "hello, world"
302
+ Kredis Proxy (2.4ms) SET mystring ["hello, world"]
303
+ => "hello, world"
304
+ >> str.value
305
+ ```
306
+
307
+ Run tests with `bin/test`.
308
+
309
+ [`debug`](https://github.com/ruby/debug) can be used in the development console and in the test suite by inserting a
310
+ breakpoint, e.g. `debugger`.
311
+
262
312
  ## License
263
313
 
264
314
  Kredis is released under the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  yaml_path = Rails.root.join("config/redis/shared.yml")
2
4
  unless yaml_path.exist?
3
5
  say "Adding `config/redis/shared.yml`"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kredis::Attributes
2
4
  extend ActiveSupport::Concern
3
5
 
@@ -6,52 +8,56 @@ module Kredis::Attributes
6
8
  kredis_connection_with __method__, name, key, config: config, after_change: after_change
7
9
  end
8
10
 
9
- def kredis_string(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
10
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
11
+ def kredis_string(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
12
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
11
13
  end
12
14
 
13
- def kredis_integer(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
14
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
15
+ def kredis_integer(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
16
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
15
17
  end
16
18
 
17
- def kredis_decimal(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
18
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
19
+ def kredis_decimal(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
20
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
19
21
  end
20
22
 
21
- def kredis_datetime(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
22
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
23
+ def kredis_datetime(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
24
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
23
25
  end
24
26
 
25
- def kredis_flag(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
26
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
27
+ def kredis_flag(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
28
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
27
29
 
28
30
  define_method("#{name}?") do
29
31
  send(name).marked?
30
32
  end
31
33
  end
32
34
 
33
- def kredis_float(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
34
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
35
+ def kredis_float(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
36
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
35
37
  end
36
38
 
37
39
  def kredis_enum(name, key: nil, values:, default:, config: :shared, after_change: nil)
38
40
  kredis_connection_with __method__, name, key, values: values, default: default, config: config, after_change: after_change
39
41
  end
40
42
 
41
- def kredis_json(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
42
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
43
+ def kredis_json(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
44
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
45
+ end
46
+
47
+ def kredis_list(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
48
+ kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
43
49
  end
44
50
 
45
- def kredis_list(name, key: nil, typed: :string, config: :shared, after_change: nil)
46
- kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
51
+ def kredis_unique_list(name, limit: nil, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
52
+ kredis_connection_with __method__, name, key, default: default, limit: limit, typed: typed, config: config, after_change: after_change
47
53
  end
48
54
 
49
- def kredis_unique_list(name, limit: nil, key: nil, typed: :string, config: :shared, after_change: nil)
50
- kredis_connection_with __method__, name, key, limit: limit, typed: typed, config: config, after_change: after_change
55
+ def kredis_set(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
56
+ kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
51
57
  end
52
58
 
53
- def kredis_set(name, key: nil, typed: :string, config: :shared, after_change: nil)
54
- kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
59
+ def kredis_ordered_set(name, limit: nil, default: nil, key: nil, typed: :string, config: :shared, after_change: nil)
60
+ kredis_connection_with __method__, name, key, default: default, limit: limit, typed: typed, config: config, after_change: after_change
55
61
  end
56
62
 
57
63
  def kredis_slot(name, key: nil, config: :shared, after_change: nil)
@@ -62,16 +68,16 @@ module Kredis::Attributes
62
68
  kredis_connection_with __method__, name, key, available: available, config: config, after_change: after_change
63
69
  end
64
70
 
65
- def kredis_counter(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
66
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
71
+ def kredis_counter(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
72
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
67
73
  end
68
74
 
69
- def kredis_hash(name, key: nil, typed: :string, config: :shared, after_change: nil)
70
- kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
75
+ def kredis_hash(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
76
+ kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
71
77
  end
72
78
 
73
- def kredis_boolean(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
74
- kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
79
+ def kredis_boolean(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
80
+ kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
75
81
  end
76
82
 
77
83
  private
@@ -84,6 +90,7 @@ module Kredis::Attributes
84
90
  if instance_variable_defined?(ivar_symbol)
85
91
  instance_variable_get(ivar_symbol)
86
92
  else
93
+ options[:default] = kredis_default_evaluated(options[:default]) if options[:default]
87
94
  new_type = Kredis.send(type, kredis_key_evaluated(key) || kredis_key_for_attribute(name), **options)
88
95
  instance_variable_set ivar_symbol,
89
96
  after_change ? enrich_after_change_with_record_access(new_type, after_change) : new_type
@@ -102,7 +109,7 @@ module Kredis::Attributes
102
109
  end
103
110
 
104
111
  def kredis_key_for_attribute(name)
105
- "#{self.class.name.tableize.gsub("/", ":")}:#{extract_kredis_id}:#{name}"
112
+ "#{self.class.name.tableize.tr("/", ":")}:#{extract_kredis_id}:#{name}"
106
113
  end
107
114
 
108
115
  def extract_kredis_id
@@ -115,4 +122,12 @@ module Kredis::Attributes
115
122
  when Symbol then Kredis::Types::CallbacksProxy.new(type, ->(_) { send(original_after_change) })
116
123
  end
117
124
  end
125
+
126
+ def kredis_default_evaluated(default)
127
+ case default
128
+ when Proc then Proc.new { default.call(self) }
129
+ when Symbol then send(default)
130
+ else default
131
+ end
132
+ end
118
133
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "redis"
2
4
 
3
5
  module Kredis::Connections
@@ -6,10 +8,8 @@ module Kredis::Connections
6
8
  mattr_accessor :connector, default: ->(config) { Redis.new(config) }
7
9
 
8
10
  def configured_for(name)
9
- connections[name] ||= begin
10
- Kredis.instrument :meta, message: "Connected to #{name}" do
11
- connector.call configurator.config_for("redis/#{name}")
12
- end
11
+ connections[name] ||= Kredis.instrument :meta, message: "Connected to #{name}" do
12
+ connector.call configurator.config_for("redis/#{name}")
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kredis::DefaultValues
4
+ extend ActiveSupport::Concern
5
+
6
+ prepended do
7
+ attr_writer :default
8
+
9
+ proxying :watch, :unwatch, :exists?
10
+
11
+ def default
12
+ case @default
13
+ when Proc then @default.call
14
+ when Symbol then send(@default)
15
+ else @default
16
+ end
17
+ end
18
+
19
+ private
20
+ def set_default
21
+ raise NotImplementedError, "Kredis type #{self.class} needs to define #set_default"
22
+ end
23
+ end
24
+
25
+ def initialize(...)
26
+ super
27
+
28
+ if default
29
+ watch do
30
+ set_default unless exists?
31
+
32
+ unwatch
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/log_subscriber"
2
4
 
3
5
  class Kredis::LogSubscriber < ActiveSupport::LogSubscriber
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
 
3
5
  class Kredis::Migration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kredis::Namespace
2
4
  def namespace=(namespace)
3
5
  Thread.current[:kredis_namespace] = namespace
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Railtie < ::Rails::Railtie
2
4
  config.kredis = ActiveSupport::OrderedOptions.new
3
5
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kredis
4
+ module Type
5
+ class Boolean < ActiveModel::Type::Boolean
6
+ def serialize(value)
7
+ super ? 1 : 0
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
  require "active_model/type"
3
- require "kredis/type/json"
5
+ require "kredis/type/boolean"
4
6
  require "kredis/type/datetime"
7
+ require "kredis/type/json"
5
8
 
6
9
  module Kredis::TypeCasting
7
10
  class InvalidType < StandardError; end
@@ -11,7 +14,7 @@ module Kredis::TypeCasting
11
14
  integer: ActiveModel::Type::Integer.new,
12
15
  decimal: ActiveModel::Type::Decimal.new,
13
16
  float: ActiveModel::Type::Float.new,
14
- boolean: ActiveModel::Type::Boolean.new,
17
+ boolean: Kredis::Type::Boolean.new,
15
18
  datetime: Kredis::Type::DateTime.new,
16
19
  json: Kredis::Type::Json.new
17
20
  }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::CallbacksProxy
2
4
  attr_reader :type
3
5
  delegate :to_s, to: :type
@@ -1,18 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Counter < Kredis::Types::Proxying
4
+ prepend Kredis::DefaultValues
5
+
2
6
  proxying :multi, :set, :incrby, :decrby, :get, :del, :exists?
3
7
 
4
8
  attr_accessor :expires_in
5
9
 
6
10
  def increment(by: 1)
7
11
  multi do
8
- set 0, ex: expires_in, nx: true
12
+ set 0, ex: expires_in, nx: true if expires_in
9
13
  incrby by
10
14
  end[-1]
11
15
  end
12
16
 
13
17
  def decrement(by: 1)
14
18
  multi do
15
- set 0, ex: expires_in, nx: true
19
+ set 0, ex: expires_in, nx: true if expires_in
16
20
  decrby by
17
21
  end[-1]
18
22
  end
@@ -24,4 +28,9 @@ class Kredis::Types::Counter < Kredis::Types::Proxying
24
28
  def reset
25
29
  del
26
30
  end
31
+
32
+ private
33
+ def set_default
34
+ increment by: default
35
+ end
27
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Cycle < Kredis::Types::Counter
2
4
  attr_accessor :values
3
5
 
@@ -1,9 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/inclusion"
2
4
 
3
5
  class Kredis::Types::Enum < Kredis::Types::Proxying
4
- proxying :set, :get, :del, :exists?
6
+ prepend Kredis::DefaultValues
7
+
8
+ InvalidDefault = Class.new(StandardError)
5
9
 
6
- attr_accessor :values, :default
10
+ proxying :set, :get, :del, :exists?, :multi
11
+
12
+ attr_accessor :values
7
13
 
8
14
  def initialize(...)
9
15
  super
@@ -17,11 +23,14 @@ class Kredis::Types::Enum < Kredis::Types::Proxying
17
23
  end
18
24
 
19
25
  def value
20
- get || default
26
+ get
21
27
  end
22
28
 
23
29
  def reset
24
- del
30
+ multi do
31
+ del
32
+ set_default
33
+ end
25
34
  end
26
35
 
27
36
  private
@@ -31,4 +40,12 @@ class Kredis::Types::Enum < Kredis::Types::Proxying
31
40
  define_singleton_method("#{defined_value}!") { self.value = defined_value }
32
41
  end
33
42
  end
43
+
44
+ def set_default
45
+ if default.in?(values) || default.nil?
46
+ set default
47
+ else
48
+ raise InvalidDefault, "Default value #{default.inspect} for #{key} is not a valid option (Valid values: #{values.join(", ")})"
49
+ end
50
+ end
34
51
  end
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Flag < Kredis::Types::Proxying
4
+ prepend Kredis::DefaultValues
5
+
2
6
  proxying :set, :exists?, :del
3
7
 
4
8
  attr_accessor :expires_in
@@ -14,4 +18,9 @@ class Kredis::Types::Flag < Kredis::Types::Proxying
14
18
  def remove
15
19
  del
16
20
  end
21
+
22
+ private
23
+ def set_default
24
+ mark if default
25
+ end
17
26
  end
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash"
2
4
 
3
5
  class Kredis::Types::Hash < Kredis::Types::Proxying
6
+ prepend Kredis::DefaultValues
7
+
4
8
  proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?
5
9
 
6
10
  attr_accessor :typed
@@ -14,7 +18,7 @@ class Kredis::Types::Hash < Kredis::Types::Proxying
14
18
  end
15
19
 
16
20
  def update(**entries)
17
- hset entries.transform_values{ |val| type_to_string(val, typed) } if entries.flatten.any?
21
+ hset entries.transform_values { |val| type_to_string(val, typed) } if entries.flatten.any?
18
22
  end
19
23
 
20
24
  def values_at(*keys)
@@ -42,4 +46,9 @@ class Kredis::Types::Hash < Kredis::Types::Proxying
42
46
  def values
43
47
  strings_to_types(hvals || [], typed)
44
48
  end
49
+
50
+ private
51
+ def set_default
52
+ update(**default)
53
+ end
45
54
  end
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::List < Kredis::Types::Proxying
4
+ prepend Kredis::DefaultValues
5
+
2
6
  proxying :lrange, :lrem, :lpush, :ltrim, :rpush, :exists?, :del
3
7
 
4
8
  attr_accessor :typed
@@ -28,4 +32,9 @@ class Kredis::Types::List < Kredis::Types::Proxying
28
32
  def last(n = nil)
29
33
  n ? lrange(-n, -1) : lrange(-1, -1).first
30
34
  end
35
+
36
+ private
37
+ def set_default
38
+ append default
39
+ end
31
40
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::OrderedSet < Kredis::Types::Proxying
2
- proxying :multi, :zrange, :zrem, :zadd, :zremrangebyrank, :zcard, :exists?, :del
4
+ prepend Kredis::DefaultValues
5
+
6
+ proxying :multi, :zrange, :zrem, :zadd, :zremrangebyrank, :zcard, :exists?, :del, :zscore
3
7
 
4
8
  attr_accessor :typed
5
9
  attr_reader :limit
@@ -13,6 +17,10 @@ class Kredis::Types::OrderedSet < Kredis::Types::Proxying
13
17
  zrem(types_to_strings(elements, typed))
14
18
  end
15
19
 
20
+ def include?(element)
21
+ !!zscore(type_to_string(element, typed))
22
+ end
23
+
16
24
  def prepend(elements)
17
25
  insert(elements, prepending: true)
18
26
  end
@@ -42,7 +50,7 @@ class Kredis::Types::OrderedSet < Kredis::Types::Proxying
42
50
  base_score + incremental_score
43
51
  end
44
52
 
45
- [ score , element ]
53
+ [ score, element ]
46
54
  end
47
55
 
48
56
  multi do
@@ -72,4 +80,8 @@ class Kredis::Types::OrderedSet < Kredis::Types::Proxying
72
80
  zremrangebyrank(0, -(limit + 1))
73
81
  end
74
82
  end
83
+
84
+ def set_default
85
+ append default
86
+ end
75
87
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kredis::Types::Proxy::Failsafe
2
4
  def initialize(*)
3
5
  super
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Proxy
2
4
  require_relative "proxy/failsafe"
3
5
  include Failsafe
@@ -20,6 +22,16 @@ class Kredis::Types::Proxy
20
22
  end
21
23
  end
22
24
 
25
+ def watch(&block)
26
+ redis.watch(key) do
27
+ block.call
28
+ end
29
+ end
30
+
31
+ def unwatch
32
+ redis.unwatch
33
+ end
34
+
23
35
  def method_missing(method, *args, **kwargs)
24
36
  Kredis.instrument :proxy, **log_message(method, *args, **kwargs) do
25
37
  failsafe do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
 
3
5
  class Kredis::Types::Proxying
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Scalar < Kredis::Types::Proxying
4
+ prepend Kredis::DefaultValues
5
+
2
6
  proxying :set, :get, :exists?, :del, :expire, :expireat
3
7
 
4
- attr_accessor :typed, :default, :expires_in
8
+ attr_accessor :typed, :expires_in
5
9
 
6
10
  def value=(value)
7
11
  set type_to_string(value, typed), ex: expires_in
@@ -36,4 +40,9 @@ class Kredis::Types::Scalar < Kredis::Types::Proxying
36
40
  def expire_at(datetime)
37
41
  expireat datetime.to_i
38
42
  end
43
+
44
+ private
45
+ def set_default
46
+ self.value = default
47
+ end
39
48
  end
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Set < Kredis::Types::Proxying
4
+ prepend Kredis::DefaultValues
5
+
2
6
  proxying :smembers, :sadd, :srem, :multi, :del, :sismember, :scard, :spop, :exists?, :srandmember
3
7
 
4
8
  attr_accessor :typed
@@ -47,4 +51,9 @@ class Kredis::Types::Set < Kredis::Types::Proxying
47
51
  strings_to_types(srandmember(count), typed)
48
52
  end
49
53
  end
54
+
55
+ private
56
+ def set_default
57
+ add default
58
+ end
50
59
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Kredis::Types::Slots < Kredis::Types::Proxying
2
4
  class NotAvailable < StandardError; end
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # You'd normally call this a set, but Redis already has another data type for that
2
4
  class Kredis::Types::UniqueList < Kredis::Types::List
3
5
  proxying :multi, :ltrim, :exists?
data/lib/kredis/types.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kredis::Types
2
4
  autoload :CallbacksProxy, "kredis/types/callbacks_proxy"
3
5
 
@@ -39,40 +41,40 @@ module Kredis::Types
39
41
  end
40
42
 
41
43
 
42
- def counter(key, expires_in: nil, config: :shared, after_change: nil)
43
- type_from(Counter, config, key, after_change: after_change, expires_in: expires_in)
44
+ def counter(key, expires_in: nil, default: nil, config: :shared, after_change: nil)
45
+ type_from(Counter, config, key, after_change: after_change, default: default, expires_in: expires_in)
44
46
  end
45
47
 
46
48
  def cycle(key, values:, expires_in: nil, config: :shared, after_change: nil)
47
49
  type_from(Cycle, config, key, after_change: after_change, values: values, expires_in: expires_in)
48
50
  end
49
51
 
50
- def flag(key, config: :shared, after_change: nil, expires_in: nil)
51
- type_from(Flag, config, key, after_change: after_change, expires_in: expires_in)
52
+ def flag(key, default: nil, config: :shared, after_change: nil, expires_in: nil)
53
+ type_from(Flag, config, key, after_change: after_change, default: default, expires_in: expires_in)
52
54
  end
53
55
 
54
56
  def enum(key, values:, default:, config: :shared, after_change: nil)
55
57
  type_from(Enum, config, key, after_change: after_change, values: values, default: default)
56
58
  end
57
59
 
58
- def hash(key, typed: :string, config: :shared, after_change: nil)
59
- type_from(Hash, config, key, after_change: after_change, typed: typed)
60
+ def hash(key, typed: :string, default: nil, config: :shared, after_change: nil)
61
+ type_from(Hash, config, key, after_change: after_change, default: default, typed: typed)
60
62
  end
61
63
 
62
- def list(key, typed: :string, config: :shared, after_change: nil)
63
- type_from(List, config, key, after_change: after_change, typed: typed)
64
+ def list(key, default: nil, typed: :string, config: :shared, after_change: nil)
65
+ type_from(List, config, key, after_change: after_change, default: default, typed: typed)
64
66
  end
65
67
 
66
- def unique_list(key, typed: :string, limit: nil, config: :shared, after_change: nil)
67
- type_from(UniqueList, config, key, after_change: after_change, typed: typed, limit: limit)
68
+ def unique_list(key, default: nil, typed: :string, limit: nil, config: :shared, after_change: nil)
69
+ type_from(UniqueList, config, key, after_change: after_change, default: default, typed: typed, limit: limit)
68
70
  end
69
71
 
70
- def set(key, typed: :string, config: :shared, after_change: nil)
71
- type_from(Set, config, key, after_change: after_change, typed: typed)
72
+ def set(key, default: nil, typed: :string, config: :shared, after_change: nil)
73
+ type_from(Set, config, key, after_change: after_change, default: default, typed: typed)
72
74
  end
73
75
 
74
- def ordered_set(key, typed: :string, limit: nil, config: :shared, after_change: nil)
75
- type_from(OrderedSet, config, key, after_change: after_change, typed: typed, limit: limit)
76
+ def ordered_set(key, default: nil, typed: :string, limit: nil, config: :shared, after_change: nil)
77
+ type_from(OrderedSet, config, key, after_change: after_change, default: default, typed: typed, limit: limit)
76
78
  end
77
79
 
78
80
  def slot(key, config: :shared, after_change: nil)
@@ -1,3 +1,3 @@
1
1
  module Kredis
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.0"
3
3
  end
data/lib/kredis.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
4
  require "active_support/core_ext/module/attribute_accessors"
3
5
  require "active_support/core_ext/module/attribute_accessors_per_thread"
@@ -8,6 +10,7 @@ require "kredis/connections"
8
10
  require "kredis/log_subscriber"
9
11
  require "kredis/namespace"
10
12
  require "kredis/type_casting"
13
+ require "kredis/default_values"
11
14
  require "kredis/types"
12
15
  require "kredis/attributes"
13
16
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :kredis do
2
4
  desc "Install kredis"
3
5
  task :install do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kredis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Timm Hansen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-06-26 00:00:00.000000000 Z
12
+ date: 2023-10-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -86,10 +86,12 @@ files:
86
86
  - lib/kredis.rb
87
87
  - lib/kredis/attributes.rb
88
88
  - lib/kredis/connections.rb
89
+ - lib/kredis/default_values.rb
89
90
  - lib/kredis/log_subscriber.rb
90
91
  - lib/kredis/migration.rb
91
92
  - lib/kredis/namespace.rb
92
93
  - lib/kredis/railtie.rb
94
+ - lib/kredis/type/boolean.rb
93
95
  - lib/kredis/type/datetime.rb
94
96
  - lib/kredis/type/json.rb
95
97
  - lib/kredis/type_casting.rb
@@ -130,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
132
  - !ruby/object:Gem::Version
131
133
  version: '0'
132
134
  requirements: []
133
- rubygems_version: 3.4.10
135
+ rubygems_version: 3.4.20
134
136
  signing_key:
135
137
  specification_version: 4
136
138
  summary: Higher-level data structures built on Redis.