airrel 0.2.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: 6b961c23489f4318b5feaceb9dd0b278a402ae3361a7516b4f7f5c7514459843
4
- data.tar.gz: 5635e4654a366fec1e9aff98394d99675dba861d8514845fbf75cd64ac88ba53
3
+ metadata.gz: 6db8b37d78ff312a990135ce202982f4e171295e298c23a538f9c6561b899979
4
+ data.tar.gz: df005dbf7fd3259b3947a372e974bebe67712e06df2cbefd0829e8d82f011adf
5
5
  SHA512:
6
- metadata.gz: 0cd6592f458ad4aa04a3d43dcbf6d9fe737a9a10a8998b6efa9bc268bd119fa35e0303a8a76a9343007967111a8033fe6762228e966939d7ac97b944772a43a7
7
- data.tar.gz: e406cf4797e68a2ee05765bf67cc0cd7900cfddb70d7530e88bbe17ee1dd62c1cc0c29fd2a89a80e6aa7838763f5882a5f073b7811f3e27c5b923ed7d56c2f21
6
+ metadata.gz: ad00efa854c772d5ca66d5a7eae1d80ac382fe2c3bfd17f7ced82e253991433442ae36c28ccde1144d165314883d7db032f054e03368575ec8ffa563d7674311
7
+ data.tar.gz: 54124653722d4d3fb13e0d2c5b4e9f892a7e8dda909e6bfdb1a9f542efbf792fa626d3c8ece35a57c89a18e7623b3182044d7fff39defda7387c7c90e3ba41c2
data/examples/demo.rb CHANGED
@@ -16,10 +16,10 @@ end
16
16
  # basic chaining
17
17
  puts "=== basic chaining ==="
18
18
  relation = Airrel::Relation.new(User)
19
- .where(role: "admin")
20
- .where(active: true)
21
- .order(created_at: :desc)
22
- .limit(10)
19
+ .where(role: "admin")
20
+ .where(active: true)
21
+ .order(created_at: :desc)
22
+ .limit(10)
23
23
 
24
24
  puts relation.to_airtable
25
25
  puts
@@ -28,7 +28,7 @@ puts
28
28
  puts "=== hash to formula ==="
29
29
  puts Airrel::FormulaBuilder.hash_to_formula(email: "test@example.com", age: 25)
30
30
  puts Airrel::FormulaBuilder.hash_to_formula(age: 18..65)
31
- puts Airrel::FormulaBuilder.hash_to_formula(role: ["admin", "moderator"])
31
+ puts Airrel::FormulaBuilder.hash_to_formula(role: %w[admin moderator])
32
32
  puts Airrel::FormulaBuilder.hash_to_formula(deleted_at: nil)
33
33
  puts
34
34
 
@@ -10,7 +10,7 @@ module Airrel
10
10
  build_predicate(field_name, value)
11
11
  end
12
12
 
13
- formulas.size == 1 ? formulas.first : "AND(#{formulas.join(', ')})"
13
+ formulas.size == 1 ? formulas.first : "AND(#{formulas.join(", ")})"
14
14
  end
15
15
 
16
16
  def build_predicate(field, value)
@@ -34,7 +34,7 @@ module Airrel
34
34
  when Array
35
35
  # IN query - use OR
36
36
  or_conditions = value.map { |v| build_predicate(field, v) }
37
- "OR(#{or_conditions.join(', ')})"
37
+ "OR(#{or_conditions.join(", ")})"
38
38
  else
39
39
  # fallback - convert to string and escape
40
40
  "{#{field}} = #{escape_string(value.to_s)}"
@@ -46,7 +46,7 @@ module Airrel
46
46
  # so we need to escape backslashes first, then quotes
47
47
  def escape_string(str)
48
48
  # escape backslashes first (\ -> \\), then quotes (' -> \', " -> \")
49
- escaped = str.to_s.gsub('\\', '\\\\\\\\').gsub(/['"]/, '\\\\\0')
49
+ escaped = str.to_s.gsub("\\", "\\\\\\\\").gsub(/['"]/, '\\\\\0')
50
50
  "'#{escaped}'"
51
51
  end
52
52
 
@@ -70,62 +70,34 @@ module Airrel
70
70
 
71
71
  # helper methods for building formulas programmatically
72
72
 
73
- def all(*formulas)
74
- "AND(#{formulas.join(', ')})"
75
- end
73
+ def all(*formulas) = "AND(#{formulas.join(", ")})"
76
74
 
77
- def any(*formulas)
78
- "OR(#{formulas.join(', ')})"
79
- end
75
+ def any(*formulas) = "OR(#{formulas.join(", ")})"
80
76
 
81
- def none(formula)
82
- "NOT(#{formula})"
83
- end
77
+ def none(formula) = "NOT(#{formula})"
84
78
 
85
- def eq(field, value)
86
- build_predicate(field, value)
87
- end
79
+ def eq(field, value) = build_predicate(field, value)
88
80
 
89
- def neq(field, value)
90
- none(eq(field, value))
91
- end
81
+ def neq(field, value) = none(eq(field, value))
92
82
 
93
- def gt(field, value)
94
- "{#{field}} > #{value}"
95
- end
83
+ def gt(field, value) = "{#{field}} > #{value}"
96
84
 
97
- def gte(field, value)
98
- "{#{field}} >= #{value}"
99
- end
85
+ def gte(field, value) = "{#{field}} >= #{value}"
100
86
 
101
- def lt(field, value)
102
- "{#{field}} < #{value}"
103
- end
87
+ def lt(field, value) = "{#{field}} < #{value}"
104
88
 
105
- def lte(field, value)
106
- "{#{field}} <= #{value}"
107
- end
89
+ def lte(field, value) = "{#{field}} <= #{value}"
108
90
 
109
- def blank(field)
110
- "{#{field}} = BLANK()"
111
- end
91
+ def blank(field) = "{#{field}} = BLANK()"
112
92
 
113
- def present(field)
114
- none(blank(field))
115
- end
93
+ def present(field) = none(blank(field))
116
94
 
117
- def find(field, search_string)
118
- "FIND(#{escape_string(search_string)}, {#{field}})"
119
- end
95
+ def find(field, search_string) = "FIND(#{escape_string(search_string)}, {#{field}})"
120
96
 
121
- def search(field, search_string)
122
- "SEARCH(#{escape_string(search_string)}, {#{field}})"
123
- end
97
+ def search(field, search_string) = "SEARCH(#{escape_string(search_string)}, {#{field}})"
124
98
 
125
99
  # for multi-select fields (checks if array contains value)
126
- def contains(field, value)
127
- "FIND(#{escape_string(value.to_s)}, {#{field}})"
128
- end
100
+ def contains(field, value) = "FIND(#{escape_string(value.to_s)}, {#{field}})"
129
101
 
130
102
  # check if multi-select contains ANY of the values
131
103
  def contains_any(field, *values)
@@ -17,46 +17,36 @@ module Airrel
17
17
  end
18
18
 
19
19
  # chaining methods (return new relations)
20
-
21
- def where(conditions)
22
- spawn.where!(conditions)
23
- end
20
+
21
+ def where(conditions) = spawn.where!(conditions)
24
22
 
25
23
  def where!(conditions)
26
24
  @where_clause = @where_clause.merge(conditions)
27
25
  self
28
26
  end
29
27
 
30
- def order(*args)
31
- spawn.order!(*args)
32
- end
28
+ def order(*args) = spawn.order!(*args)
33
29
 
34
30
  def order!(*args)
35
31
  @order_values += parse_order_args(args)
36
32
  self
37
33
  end
38
34
 
39
- def limit(value)
40
- spawn.limit!(value)
41
- end
35
+ def limit(value) = spawn.limit!(value)
42
36
 
43
37
  def limit!(value)
44
38
  @limit_value = value
45
39
  self
46
40
  end
47
41
 
48
- def offset(value)
49
- spawn.offset!(value)
50
- end
42
+ def offset(value) = spawn.offset!(value)
51
43
 
52
44
  def offset!(value)
53
45
  @offset_value = value
54
46
  self
55
47
  end
56
48
 
57
- def reorder(*args)
58
- spawn.reorder!(*args)
59
- end
49
+ def reorder(*args) = spawn.reorder!(*args)
60
50
 
61
51
  def reorder!(*args)
62
52
  @order_values = parse_order_args(args)
@@ -81,7 +71,7 @@ module Airrel
81
71
  if @order_values.empty?
82
72
  raise ArgumentError, "last requires an order to be specified (use .order(:created_at) or similar)"
83
73
  end
84
-
74
+
85
75
  reversed = reverse_order
86
76
  if limit
87
77
  # only load what we need
@@ -92,13 +82,9 @@ module Airrel
92
82
  end
93
83
  end
94
84
 
95
- def find(id)
96
- klass.find(id)
97
- end
85
+ def find(id) = klass.find(id)
98
86
 
99
- def find_by(conditions)
100
- where(conditions).first
101
- end
87
+ def find_by(conditions) = where(conditions).first
102
88
 
103
89
  def find_by!(conditions)
104
90
  # Raise error class that will be defined by the consumer (norairrecord)
@@ -106,19 +92,13 @@ module Airrel
106
92
  find_by(conditions) || raise(error_class, "Record not found")
107
93
  end
108
94
 
109
- def all
110
- spawn
111
- end
95
+ def all = spawn
112
96
 
113
- def to_a
114
- load_records
115
- end
97
+ def to_a = load_records
116
98
 
117
99
  alias to_ary to_a
118
100
 
119
- def each(&block)
120
- load_records.each(&block)
121
- end
101
+ def each(&block) = load_records.each(&block)
122
102
 
123
103
  # batch iteration for large result sets
124
104
  def find_each(batch_size: 100, &block)
@@ -127,43 +107,35 @@ module Airrel
127
107
  end
128
108
  end
129
109
 
130
- def find_in_batches(batch_size: 100, &block)
110
+ def find_in_batches(batch_size: 100)
131
111
  current_offset = 0
132
-
112
+
133
113
  loop do
134
114
  # create a new relation with limit and offset
135
115
  batch_relation = spawn
136
116
  batch_relation.instance_variable_set(:@limit_value, batch_size)
137
117
  batch_relation.instance_variable_set(:@offset_value, current_offset)
138
-
118
+
139
119
  batch = batch_relation.to_a
140
120
  break if batch.empty?
141
-
121
+
142
122
  yield batch
143
-
123
+
144
124
  break if batch.size < batch_size # last batch
125
+
145
126
  current_offset += batch_size
146
127
  end
147
128
  end
148
129
 
149
- def count
150
- # airtable doesn't have a count API, but we can optimize by limiting fields
151
- # or using exists? check for any?
152
- load_records.size
153
- end
130
+ # airtable doesn't have a count API >:-/ we gotta paginate through EVERYTHING...
131
+ def count = load_records.size
154
132
 
155
- def empty?
156
- !any?
157
- end
133
+ def empty? = !any?
158
134
 
159
- def any?
160
- # optimize: only load 1 record to check existence
161
- limit(1).load_records.any?
162
- end
163
-
164
- def exists?
165
- any?
166
- end
135
+ # OPTIMIZE: only load 1 record to check existence
136
+ def any? = limit(1).load_records.any?
137
+
138
+ def exists? = any?
167
139
 
168
140
  # inspection
169
141
 
@@ -171,16 +143,12 @@ module Airrel
171
143
  entries = load_records.take(11).map!(&:inspect)
172
144
  entries[10] = "..." if entries.size == 11
173
145
 
174
- "#<#{self.class.name} [#{entries.join(', ')}]>"
146
+ "#<#{self.class.name} [#{entries.join(", ")}]>"
175
147
  end
176
148
 
177
- def to_airtable
178
- to_airtable_params
179
- end
180
-
181
- def to_sql
182
- to_airtable_params.inspect
183
- end
149
+ def to_airtable = to_airtable_params
150
+
151
+ def to_sql = to_airtable_params.inspect
184
152
 
185
153
  # execution
186
154
 
@@ -194,9 +162,7 @@ module Airrel
194
162
  load
195
163
  end
196
164
 
197
- def loaded?
198
- @loaded
199
- end
165
+ def loaded? = @loaded
200
166
 
201
167
  def reset
202
168
  @loaded = false
@@ -212,9 +178,7 @@ module Airrel
212
178
 
213
179
  protected
214
180
 
215
- def spawn
216
- clone.tap { |r| r.reset }
217
- end
181
+ def spawn = clone.tap(&:reset)
218
182
 
219
183
  def load_records
220
184
  load unless loaded?
@@ -229,25 +193,23 @@ module Airrel
229
193
 
230
194
  def to_airtable_params
231
195
  params = {}
232
-
196
+
233
197
  # filter
234
- if @where_clause.any?
235
- params[:filter] = @where_clause.to_airtable_formula
236
- end
198
+ params[:filter] = @where_clause.to_airtable_formula if @where_clause.any?
237
199
 
238
200
  # sort
239
201
  if @order_values.any?
240
- params[:sort] = @order_values.map { |field, direction|
202
+ params[:sort] = @order_values.map do |field, direction|
241
203
  { field: field.to_s, direction: direction.to_s }
242
- }
204
+ end
243
205
  end
244
206
 
245
207
  # limit
246
208
  params[:max_records] = @limit_value if @limit_value
247
-
209
+
248
210
  # offset (airtable calls it offset in pagination)
249
211
  params[:offset] = @offset_value if @offset_value
250
-
212
+
251
213
  # pagination control
252
214
  params[:paginate] = @paginate if defined?(@paginate)
253
215
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Airrel
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
@@ -23,19 +23,15 @@ module Airrel
23
23
  WhereClause.new(@predicates + new_predicates)
24
24
  end
25
25
 
26
- def any?
27
- @predicates.any?
28
- end
26
+ def any? = @predicates.any?
29
27
 
30
28
  def to_airtable_formula
31
29
  return nil if @predicates.empty?
32
30
  return @predicates.first if @predicates.size == 1
33
31
 
34
- "AND(#{@predicates.join(', ')})"
32
+ "AND(#{@predicates.join(", ")})"
35
33
  end
36
34
 
37
- def inspect
38
- @predicates.inspect
39
- end
35
+ def inspect = @predicates.inspect
40
36
  end
41
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airrel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - 24c02