active_postgrest 0.1.0 → 0.2.1

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: cbb8484a4d524bbe396c3cb4a87dade05a3e8628aa2e0703c84b749287a86e67
4
- data.tar.gz: 8640a588f4fac91e890575794632d154cec30ab699aea4057f3ce1d4245ea7fa
3
+ metadata.gz: e0147542053d10ed15478ba0b808b81c761079420879dec931e7cfe420de7e29
4
+ data.tar.gz: 841544cc15094bf18837bd218190243f11aedf82e57dc5c2d0d2e1b38094ad94
5
5
  SHA512:
6
- metadata.gz: '097618ab9f67309599c73848566398f423c8d584f8844e603a9a25f845be8a359cb4f3e347de72c888c7b42b10ea30ded62e2f3418743394085d521b80d47fc7'
7
- data.tar.gz: baef5f5829e50eef2d9f012a275d8391b73b4f269c5053c4286ff1290ca5593160da71cd6a12347a8fcd18151a82df7f6d1874b3f89ff2345d60f896b72254a3
6
+ metadata.gz: e2b816ce049bcef9e2fe9a0dbe4e80a012d1343765c14935940bd736b1674d46b2b3502a666a4feb4d888de6b42596b4e627985d40c5db76b5a940f79f4623b8
7
+ data.tar.gz: 3375df0a6a37cf1036b7a5e20142cea242bac393c516ca4eb33792a660695e06d0f5b092d600b63d7b83b0fd8c14505db3b79beddb447badb29a0cda91e97184
checksums.yaml.gz.sig ADDED
Binary file
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEUjCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5ldmdl
3
+ bnkuc29rb2xvdi9EQz1nbWFpbC9EQz1jb20wHhcNMjYwNjE4MTE0NDQ3WhcNMjcw
4
+ NjE4MTE0NDQ3WjApMScwJQYDVQQDDB5ldmdlbnkuc29rb2xvdi9EQz1nbWFpbC9E
5
+ Qz1jb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDInkRoXT6ySd5G
6
+ BuDN0QUAqbWqrqAShEwA0zQIVooLu9SF5pV7MCXTU4w3b12qLX0irddo3qrFp9rz
7
+ c/P+gX737W8CdglkboI0lGikghH0A23V7h1omv303kVrZHEKzOklu77cpVMhVeaO
8
+ y6KVd4N8o4AQF/D2IKM1Fi2o3uvcj9IK38W+939YMlZrilD1NSgnbQYcVI8Pcqwr
9
+ hpCGO7PGo5Ns3b9TSErCfEH+DbNovRfoYPNCXtbFdVym4qSl5SyNGZEvUcw22ZfE
10
+ BiN5iGC6W7kvwKUBMDyRibqu+1J76rpgpz15iXxqs62QqOrXpN9Id3IlFFRuRVu3
11
+ LtaPfd+y3AATtUsIMTg73Wv2g4EHT0h5v2raiQ/7O8fM3aKW6n3c6p6POAgOhohR
12
+ F2lcsgbH55tz8lymdmgz5rke5CpZaOiHqcE7LKFKdKEDtACB3GEDfy69VqzqkcqG
13
+ wwwHZYbhB1+1WZCFmIVHeQEg1Mmgy7joOHzNjEgwzzcuZICnsuUCAwEAAaOBhDCB
14
+ gTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUzhn3dA5CJtlBTkc0
15
+ 7hxTo2PvpiMwIwYDVR0RBBwwGoEYZXZnZW55LnNva29sb3ZAZ21haWwuY29tMCMG
16
+ A1UdEgQcMBqBGGV2Z2VueS5zb2tvbG92QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsF
17
+ AAOCAYEAadjhjeh6S9/kv7jvJ4AlyhWfO7r0xqkwpTECuJmDWKDQeIZs8yKvgsYl
18
+ RPss8oJZ2OVkEOnMFx4fL+RB19oTEp5ZUrtZq+Nt47Ypci93mTFOykMRyu42HQ1W
19
+ BEsgwGRLuloYBD+Eubghm1Mll5T2qo/jYPvs9av+Ma2bkp/NoMGxajVzBHFe39PN
20
+ 0wP8BokxXTtexk7ybnqIePVPTvhHo/VrMMfD2SAy7o0WPT2UwWZNfjd59aaW7ruc
21
+ 5jgdKw4qfnIXrVbISSZaovUdvCVloYOcKUFI+K4BEFFjIcfbCxrnU6GfonAEyzxJ
22
+ 84+w5Rus55cqLKEiFIR7auVJkbLsrIHsbrH+2uJDgxgXGryUq3I/k5ZaORg2gocP
23
+ DvU/iWx+jPPscxukSQ+1qVLfWOYZlQ0BEqFJJrvro9lEbimK1j6aibza2InnPwTn
24
+ tC9NYXuv1LyPD+PZZRO4LDDSjUVx+RF/dJIE23hzgbLexpyriCMFyKGhHi2KApEl
25
+ eIQUsjZL
26
+ -----END CERTIFICATE-----
@@ -0,0 +1,37 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Evgeny Sokolov (FastJoe)
3
+
4
+ require 'active_model'
5
+ require 'active_postgrest'
6
+
7
+ module ActivePostgrest
8
+ module ActiveModelSupport
9
+ def self.included(base)
10
+ base.include ::ActiveModel::Validations
11
+ base.extend ::ActiveModel::Naming
12
+ base.include ::ActiveModel::Conversion
13
+ base.prepend SaveWithValidations
14
+ end
15
+
16
+ def read_attribute_for_validation(key)
17
+ @attributes[key.to_s]
18
+ end
19
+
20
+ # Returns primary key value(s) for ActionView form helpers.
21
+ def to_key
22
+ pk = self.class.primary_key
23
+ val = @attributes[pk]
24
+ val ? [val] : nil
25
+ end
26
+
27
+ module SaveWithValidations
28
+ def save
29
+ return false unless valid?
30
+
31
+ super
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ ActivePostgrest::Base.include(ActivePostgrest::ActiveModelSupport)
@@ -81,7 +81,7 @@ module ActivePostgrest
81
81
  val = @attributes[key]
82
82
  return nil if val.nil? || (val.is_a?(Array) && val.empty?)
83
83
 
84
- klass.constantize.new(val.is_a?(Array) ? val.first : val)
84
+ klass.constantize.new(val.is_a?(Array) ? val.first : val, true)
85
85
  end
86
86
 
87
87
  define_singleton_method(:"with_#{assoc}") do |fields: []|
@@ -101,7 +101,7 @@ module ActivePostgrest
101
101
  val = @attributes[assoc]
102
102
  return nil if val.nil? || (val.is_a?(Array) && val.empty?)
103
103
 
104
- klass.constantize.new(val.is_a?(Array) ? val.first : val)
104
+ klass.constantize.new(val.is_a?(Array) ? val.first : val, true)
105
105
  end
106
106
 
107
107
  define_singleton_method(:"with_#{assoc}") do |fields: []|
@@ -117,7 +117,7 @@ module ActivePostgrest
117
117
  val = @attributes[assoc]
118
118
  return [] if val.nil?
119
119
 
120
- Array(val).map { klass.constantize.new(_1) }
120
+ (val.is_a?(Array) ? val : [val]).map { klass.constantize.new(_1, true) }
121
121
  end
122
122
 
123
123
  define_singleton_method(:"with_#{assoc}") do |fields: []|
@@ -171,14 +171,42 @@ module ActivePostgrest
171
171
  def self.one? = relation.one?
172
172
  def self.many? = relation.many?
173
173
 
174
- def initialize(attrs = {})
174
+ def self.create(attrs)
175
+ relation.insert(attrs)
176
+ end
177
+
178
+ def self.create!(attrs)
179
+ relation.insert(attrs) || raise(RecordNotSaved.new(self, attrs))
180
+ end
181
+
182
+ def self.insert(attrs) = relation.insert(attrs)
183
+ def self.insert_all(records) = relation.insert_all(records)
184
+ def self.upsert(attrs) = relation.upsert(attrs)
185
+ def self.upsert_all(records) = relation.upsert_all(records)
186
+ def self.update_all(attrs) = relation.update_all(attrs)
187
+ def self.delete_all = relation.delete_all
188
+
189
+ def initialize(attrs = {}, persisted = false, client = nil) # rubocop:disable Style/OptionalBooleanParameter
175
190
  types = self.class.attribute_types
176
191
  @attributes = attrs.to_h.transform_keys(&:to_s).to_h do |k, v|
177
192
  [k, types[k] ? cast_attribute(v, types[k]) : v]
178
193
  end
194
+ @new_record = !persisted
195
+ @destroyed = false
196
+ @_client = client
179
197
  end
180
198
 
199
+ def new_record? = @new_record
200
+ def persisted? = !@new_record && !@destroyed
201
+ def destroyed? = @destroyed
202
+
181
203
  def [](key) = @attributes[key.to_s]
204
+
205
+ def []=(key, value)
206
+ str_key = key.to_s
207
+ type = self.class.attribute_types[str_key]
208
+ @attributes[str_key] = type ? cast_attribute(value, type) : value
209
+ end
182
210
  attr_reader :attributes
183
211
 
184
212
  def to_h = @attributes
@@ -187,19 +215,87 @@ module ActivePostgrest
187
215
  "#<#{self.class.name} #{@attributes.map { "#{_1}: #{_2.inspect}" }.join(', ')}>"
188
216
  end
189
217
 
190
- def method_missing(name, *)
218
+ def method_missing(name, *args)
191
219
  key = name.to_s
192
- return @attributes[key] if @attributes.key?(key)
220
+ if key.end_with?('=')
221
+ attr = key.delete_suffix('=')
222
+ if @attributes.key?(attr)
223
+ type = self.class.attribute_types[attr]
224
+ return @attributes[attr] = type ? cast_attribute(args.first, type) : args.first
225
+ end
226
+ elsif @attributes.key?(key)
227
+ return @attributes[key]
228
+ end
193
229
 
194
230
  super
195
231
  end
196
232
 
197
233
  def respond_to_missing?(name, include_private = false)
198
- @attributes.key?(name.to_s) || super
234
+ key = name.to_s
235
+ attr = key.delete_suffix('=')
236
+ @attributes.key?(attr) || super
237
+ end
238
+
239
+ def save # rubocop:disable Naming/PredicateMethod
240
+ return false if @destroyed
241
+
242
+ if new_record?
243
+ saved = self.class.insert(@attributes)
244
+ return false unless saved
245
+
246
+ @attributes = saved.attributes
247
+ @new_record = false
248
+ else
249
+ pk = self.class.primary_key
250
+ pk_val = @attributes[pk]
251
+ raise ArgumentError, 'Cannot save a record without a primary key value' if pk_val.nil?
252
+
253
+ saved = _base_relation.where(pk => pk_val).update_all(scalar_attributes.except(pk)).first
254
+ return false unless saved
255
+
256
+ @attributes = saved.attributes
257
+ end
258
+ true
259
+ end
260
+
261
+ def update(attrs)
262
+ attrs.each { |k, v| @attributes[k.to_s] = v }
263
+ save
264
+ end
265
+
266
+ def destroy
267
+ pk = self.class.primary_key
268
+ pk_val = @attributes[pk]
269
+ raise ArgumentError, 'Cannot destroy a record without a primary key value' if pk_val.nil?
270
+
271
+ _base_relation.where(pk => pk_val).delete_all
272
+ @destroyed = true
273
+ self
274
+ end
275
+
276
+ def reload
277
+ raise RecordNotFound.new(self.class, nil) unless persisted?
278
+
279
+ pk = self.class.primary_key
280
+ fresh = _base_relation.where(pk => @attributes[pk]).first
281
+ raise RecordNotFound.new(self.class, @attributes[pk]) unless fresh
282
+
283
+ @attributes = fresh.attributes
284
+ self
199
285
  end
200
286
 
201
287
  private
202
288
 
289
+ def scalar_attributes
290
+ @attributes.reject { |_, v| v.is_a?(Hash) || v.is_a?(Array) }
291
+ end
292
+
293
+ def _base_relation
294
+ client = @_client || self.class.connection
295
+ rel = ActivePostgrest::Relation.new(self.class.table_name, client, self.class)
296
+ self.class.schema_name ? rel.with_schema(self.class.schema_name) : rel
297
+ end
298
+
203
299
  def cast_attribute(value, type)
204
300
  return nil if value.nil?
205
301
 
@@ -44,6 +44,38 @@ module ActivePostgrest
44
44
  response
45
45
  end
46
46
 
47
+ def post(resource, body, prefer: 'return=representation', schema: nil)
48
+ response = @conn.post(resource, body) do |req|
49
+ auth_headers(req)
50
+ req.headers['Prefer'] = prefer
51
+ req.headers['Content-Profile'] = schema if schema
52
+ end
53
+ raise_on_error!(response)
54
+ response
55
+ end
56
+
57
+ def patch(resource, params, body, prefer: 'return=representation', schema: nil)
58
+ response = @conn.patch(resource, body) do |req|
59
+ auth_headers(req)
60
+ req.params.update(params)
61
+ req.headers['Prefer'] = prefer
62
+ req.headers['Content-Profile'] = schema if schema
63
+ end
64
+ raise_on_error!(response)
65
+ response
66
+ end
67
+
68
+ def delete(resource, params, prefer: 'return=representation', schema: nil)
69
+ response = @conn.delete(resource) do |req|
70
+ auth_headers(req)
71
+ req.params.update(params)
72
+ req.headers['Prefer'] = prefer
73
+ req.headers['Content-Profile'] = schema if schema
74
+ end
75
+ raise_on_error!(response)
76
+ response
77
+ end
78
+
47
79
  def anonymous
48
80
  self.class.new(@base_url)
49
81
  end
@@ -29,4 +29,18 @@ module ActivePostgrest
29
29
  class UnprocessableEntity < Error; end
30
30
  # 5xx
31
31
  class ServerError < Error; end
32
+
33
+ class RecordNotFound < StandardError
34
+ def initialize(model, id)
35
+ super("#{model.name} not found: #{id.inspect}")
36
+ end
37
+ end
38
+
39
+ class RecordNotSaved < StandardError
40
+ def initialize(model, attrs)
41
+ super("#{model.name} could not be saved: #{attrs.inspect}")
42
+ end
43
+ end
44
+
45
+ class CountNotAvailable < StandardError; end
32
46
  end
@@ -0,0 +1,67 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Evgeny Sokolov (FastJoe)
3
+
4
+ module ActivePostgrest
5
+ module Mutations
6
+ def create(attrs)
7
+ insert(attrs)
8
+ end
9
+
10
+ def create!(attrs)
11
+ insert(attrs) || raise(ActivePostgrest::RecordNotSaved.new(@model_class, attrs))
12
+ end
13
+
14
+ def insert(attrs)
15
+ result = @client.post(@table, attrs, prefer: 'return=representation', schema: @schema)
16
+ instantiate_result(result.body)
17
+ end
18
+
19
+ def insert_all(records)
20
+ result = @client.post(@table, records, prefer: 'return=representation', schema: @schema)
21
+ instantiate_all(result.body)
22
+ end
23
+
24
+ def upsert(attrs)
25
+ result = @client.post(@table, attrs,
26
+ prefer: 'return=representation,resolution=merge-duplicates',
27
+ schema: @schema)
28
+ instantiate_result(result.body)
29
+ end
30
+
31
+ def upsert_all(records)
32
+ result = @client.post(@table, records,
33
+ prefer: 'return=representation,resolution=merge-duplicates',
34
+ schema: @schema)
35
+ instantiate_all(result.body)
36
+ end
37
+
38
+ def update_all(attrs)
39
+ return [] if @null
40
+
41
+ result = @client.patch(@table, build_params, attrs,
42
+ prefer: 'return=representation',
43
+ schema: @schema)
44
+ instantiate_all(result.body)
45
+ end
46
+
47
+ def delete_all
48
+ return [] if @null
49
+
50
+ result = @client.delete(@table, build_params,
51
+ prefer: 'return=representation',
52
+ schema: @schema)
53
+ instantiate_all(result.body)
54
+ end
55
+
56
+ private
57
+
58
+ def instantiate_all(body)
59
+ Array(body).map { @model_class.new(_1, true, @client) }
60
+ end
61
+
62
+ def instantiate_result(body)
63
+ attrs = Array(body).first
64
+ attrs ? @model_class.new(attrs, true, @client) : nil
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,12 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Evgeny Sokolov (FastJoe)
3
+
4
+ require 'rails/railtie'
5
+
6
+ module ActivePostgrest
7
+ class Railtie < Rails::Railtie
8
+ initializer 'active_postgrest.active_model' do
9
+ require 'active_postgrest/active_model'
10
+ end
11
+ end
12
+ end
@@ -2,14 +2,6 @@
2
2
  # Copyright 2026 Evgeny Sokolov (FastJoe)
3
3
 
4
4
  module ActivePostgrest
5
- class RecordNotFound < StandardError
6
- def initialize(model, id)
7
- super("#{model.name} not found: #{id.inspect}")
8
- end
9
- end
10
-
11
- class CountNotAvailable < StandardError; end
12
-
13
5
  class Relation
14
6
  include Enumerable
15
7
 
@@ -89,6 +81,23 @@ module ActivePostgrest
89
81
  clone_with { @or_conditions.concat(parts) }
90
82
  end
91
83
 
84
+ # where(a: 1).or(where(b: 2)) → or=(a.eq.1,b.eq.2)
85
+ # where(a: 1).where(c: 3).or(where(b: 2)) → or=(and(a.eq.1,c.eq.3),b.eq.2)
86
+ def or(other)
87
+ other_or = other.instance_variable_get(:@or_conditions)
88
+ other_and = other.instance_variable_get(:@and_conditions)
89
+ if @or_conditions.any? || @and_conditions.any? || other_or.any? || other_and.any?
90
+ raise ArgumentError, '#or does not support a relation with existing or_where/and_where conditions'
91
+ end
92
+
93
+ left = or_group(encoded_filter_conditions)
94
+ right = or_group(other.encoded_filter_conditions)
95
+ clone_with do
96
+ @filters = {}
97
+ @or_conditions.concat([left, right].compact)
98
+ end
99
+ end
100
+
92
101
  # and_where([{ age: { gt: 18 } }, { status: "active" }]) → and=(age.gt.18,status.eq.active)
93
102
  def and_where(conditions)
94
103
  parts = Array(conditions).flat_map { |f| condition_parts(f) }
@@ -118,7 +127,8 @@ module ActivePostgrest
118
127
  def to_a
119
128
  return [] if @null
120
129
 
121
- Array(@client.get(@table, build_params, schema: @schema).body).map { |attrs| @model_class.new(attrs) }
130
+ Array(@client.get(@table, build_params, schema: @schema).body)
131
+ .map { |attrs| @model_class.new(attrs, true, @client) }
122
132
  end
123
133
 
124
134
  def first
@@ -221,6 +231,9 @@ module ActivePostgrest
221
231
  end
222
232
 
223
233
  include SqlBuilder
234
+ include Mutations
235
+
236
+ protected :encoded_filter_conditions
224
237
 
225
238
  private
226
239
 
@@ -276,12 +289,6 @@ module ActivePostgrest
276
289
  end.to_a.first&.[](key)
277
290
  end
278
291
 
279
- def condition_parts(filters)
280
- filters.flat_map do |col, val|
281
- Array(encode_value(val)).map { "#{col}.#{_1}" }
282
- end
283
- end
284
-
285
292
  def build_params
286
293
  params = {}
287
294
  params[:select] = build_select if @selects.any? || @joins.any?
@@ -81,6 +81,22 @@ module ActivePostgrest
81
81
  val
82
82
  end
83
83
 
84
+ def encoded_filter_conditions
85
+ @filters.flat_map { |col, enc| Array(enc).map { "#{col}.#{_1}" } }
86
+ end
87
+
88
+ def or_group(conditions)
89
+ return nil if conditions.empty?
90
+
91
+ conditions.one? ? conditions.first : "and(#{conditions.join(',')})"
92
+ end
93
+
94
+ def condition_parts(filters)
95
+ filters.flat_map do |col, val|
96
+ Array(encode_value(val)).map { "#{col}.#{_1}" }
97
+ end
98
+ end
99
+
84
100
  def merge_filter!(col, encoded)
85
101
  existing = @filters[col]
86
102
  @filters[col] = existing ? [*Array(existing), *Array(encoded)] : encoded
@@ -106,6 +122,11 @@ module ActivePostgrest
106
122
  end
107
123
 
108
124
  def decode_condition(cond)
125
+ if cond.start_with?('and(') && cond.end_with?(')')
126
+ inner = cond[4..-2]
127
+ return "(#{split_conditions(inner).map { decode_condition(_1) }.join(' AND ')})"
128
+ end
129
+
109
130
  parts = cond.split('.')
110
131
  op_idx = parts.index { KNOWN_OP_KEYS.include?(_1) }
111
132
  return cond unless op_idx
@@ -115,6 +136,25 @@ module ActivePostgrest
115
136
  decode_filter(col, encoded)
116
137
  end
117
138
 
139
+ def split_conditions(str)
140
+ depth = 0
141
+ start = 0
142
+ result = []
143
+ str.each_char.with_index do |c, i|
144
+ case c
145
+ when '(' then depth += 1
146
+ when ')' then depth -= 1
147
+ when ','
148
+ if depth.zero?
149
+ result << str[start...i]
150
+ start = i + 1
151
+ end
152
+ end
153
+ end
154
+ result << str[start..]
155
+ result.reject(&:empty?)
156
+ end
157
+
118
158
  def sql_quote(val)
119
159
  return val if val&.match?(/\A-?\d+(\.\d+)?\z/)
120
160
 
@@ -2,5 +2,5 @@
2
2
  # Copyright 2026 Evgeny Sokolov (FastJoe)
3
3
 
4
4
  module ActivePostgrest
5
- VERSION = '0.1.0'.freeze
5
+ VERSION = '0.2.1'.freeze
6
6
  end
@@ -10,5 +10,6 @@ require 'active_postgrest/version'
10
10
  require 'active_postgrest/errors'
11
11
  require 'active_postgrest/client'
12
12
  require 'active_postgrest/sql_builder'
13
+ require 'active_postgrest/mutations'
13
14
  require 'active_postgrest/relation'
14
15
  require 'active_postgrest/base'
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,14 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_postgrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeny Sokolov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
- cert_chain: []
11
- date: 2026-06-17 00:00:00.000000000 Z
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEUjCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5ldmdl
14
+ bnkuc29rb2xvdi9EQz1nbWFpbC9EQz1jb20wHhcNMjYwNjE4MTE0NDQ3WhcNMjcw
15
+ NjE4MTE0NDQ3WjApMScwJQYDVQQDDB5ldmdlbnkuc29rb2xvdi9EQz1nbWFpbC9E
16
+ Qz1jb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDInkRoXT6ySd5G
17
+ BuDN0QUAqbWqrqAShEwA0zQIVooLu9SF5pV7MCXTU4w3b12qLX0irddo3qrFp9rz
18
+ c/P+gX737W8CdglkboI0lGikghH0A23V7h1omv303kVrZHEKzOklu77cpVMhVeaO
19
+ y6KVd4N8o4AQF/D2IKM1Fi2o3uvcj9IK38W+939YMlZrilD1NSgnbQYcVI8Pcqwr
20
+ hpCGO7PGo5Ns3b9TSErCfEH+DbNovRfoYPNCXtbFdVym4qSl5SyNGZEvUcw22ZfE
21
+ BiN5iGC6W7kvwKUBMDyRibqu+1J76rpgpz15iXxqs62QqOrXpN9Id3IlFFRuRVu3
22
+ LtaPfd+y3AATtUsIMTg73Wv2g4EHT0h5v2raiQ/7O8fM3aKW6n3c6p6POAgOhohR
23
+ F2lcsgbH55tz8lymdmgz5rke5CpZaOiHqcE7LKFKdKEDtACB3GEDfy69VqzqkcqG
24
+ wwwHZYbhB1+1WZCFmIVHeQEg1Mmgy7joOHzNjEgwzzcuZICnsuUCAwEAAaOBhDCB
25
+ gTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUzhn3dA5CJtlBTkc0
26
+ 7hxTo2PvpiMwIwYDVR0RBBwwGoEYZXZnZW55LnNva29sb3ZAZ21haWwuY29tMCMG
27
+ A1UdEgQcMBqBGGV2Z2VueS5zb2tvbG92QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsF
28
+ AAOCAYEAadjhjeh6S9/kv7jvJ4AlyhWfO7r0xqkwpTECuJmDWKDQeIZs8yKvgsYl
29
+ RPss8oJZ2OVkEOnMFx4fL+RB19oTEp5ZUrtZq+Nt47Ypci93mTFOykMRyu42HQ1W
30
+ BEsgwGRLuloYBD+Eubghm1Mll5T2qo/jYPvs9av+Ma2bkp/NoMGxajVzBHFe39PN
31
+ 0wP8BokxXTtexk7ybnqIePVPTvhHo/VrMMfD2SAy7o0WPT2UwWZNfjd59aaW7ruc
32
+ 5jgdKw4qfnIXrVbISSZaovUdvCVloYOcKUFI+K4BEFFjIcfbCxrnU6GfonAEyzxJ
33
+ 84+w5Rus55cqLKEiFIR7auVJkbLsrIHsbrH+2uJDgxgXGryUq3I/k5ZaORg2gocP
34
+ DvU/iWx+jPPscxukSQ+1qVLfWOYZlQ0BEqFJJrvro9lEbimK1j6aibza2InnPwTn
35
+ tC9NYXuv1LyPD+PZZRO4LDDSjUVx+RF/dJIE23hzgbLexpyriCMFyKGhHi2KApEl
36
+ eIQUsjZL
37
+ -----END CERTIFICATE-----
38
+ date: 2026-06-18 00:00:00.000000000 Z
12
39
  dependencies:
13
40
  - !ruby/object:Gem::Dependency
14
41
  name: faraday
@@ -66,6 +93,20 @@ dependencies:
66
93
  - - "~>"
67
94
  - !ruby/object:Gem::Version
68
95
  version: '3.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: simplecov
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.22'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.22'
69
110
  - !ruby/object:Gem::Dependency
70
111
  name: rubocop
71
112
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +121,36 @@ dependencies:
80
121
  - - "~>"
81
122
  - !ruby/object:Gem::Version
82
123
  version: '1.0'
83
- description: Query PostgREST APIs using a familiar ActiveRecord-like interface
124
+ - !ruby/object:Gem::Dependency
125
+ name: rubocop-rspec
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '3.0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '3.0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: bundler-audit
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.9'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.9'
152
+ description: 'ActiveRecord-style ORM for PostgREST: queries, CRUD operations, associations,
153
+ scopes, and ActiveModel integration'
84
154
  email:
85
155
  - evgeny.sokolov@gmail.com
86
156
  executables: []
@@ -88,10 +158,14 @@ extensions: []
88
158
  extra_rdoc_files: []
89
159
  files:
90
160
  - LICENSE
161
+ - certs/gem-public_cert.pem
91
162
  - lib/active_postgrest.rb
163
+ - lib/active_postgrest/active_model.rb
92
164
  - lib/active_postgrest/base.rb
93
165
  - lib/active_postgrest/client.rb
94
166
  - lib/active_postgrest/errors.rb
167
+ - lib/active_postgrest/mutations.rb
168
+ - lib/active_postgrest/railtie.rb
95
169
  - lib/active_postgrest/relation.rb
96
170
  - lib/active_postgrest/sql_builder.rb
97
171
  - lib/active_postgrest/version.rb
@@ -102,7 +176,8 @@ licenses:
102
176
  metadata:
103
177
  source_code_uri: https://github.com/FastJoe/active-postgrest
104
178
  changelog_uri: https://github.com/FastJoe/active-postgrest/blob/main/CHANGELOG.md
105
- post_install_message:
179
+ rubygems_mfa_required: 'true'
180
+ post_install_message:
106
181
  rdoc_options: []
107
182
  require_paths:
108
183
  - lib
@@ -117,8 +192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
192
  - !ruby/object:Gem::Version
118
193
  version: '0'
119
194
  requirements: []
120
- rubygems_version: 3.0.3.1
121
- signing_key:
195
+ rubygems_version: 3.5.22
196
+ signing_key:
122
197
  specification_version: 4
123
- summary: ActiveRecord-style Ruby client for PostgREST
198
+ summary: ActiveRecord-style Ruby ORM for PostgREST
124
199
  test_files: []
metadata.gz.sig ADDED
Binary file