kweerie 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f11c69ed8356612d3a1df5dfb98b4751061db706908f7b2efe6ace375f53c73e
4
- data.tar.gz: b33644c5b64bb941bf88bf6207ced00706e84a1c83c2b60fa9c7dddc680dd0fe
3
+ metadata.gz: d8c4f949ad0ee144a37015f2444ad19721390ee94a59b1fc118599409b6b0f0a
4
+ data.tar.gz: a8b741b11e8dd572f6fccba9f06becbb75b06f0444e879f43b21f70d164d2ba7
5
5
  SHA512:
6
- metadata.gz: 9f05d4db4050c840ac87c60b60e44dd27413fc3fee685cd81fd5320d6bb9d37f01ee5a1f29691989f1ec4f3de2a566d1a8fd0057696b54982bdd012170a0ea2b
7
- data.tar.gz: 11560ae4acff559585472f020d29d0367ca431cd3f9398cfb75aa1e27b6a08057e8f6b1d5270b7f6ef043551c9f15d3b95434d586400390c512c75b410dc7661
6
+ metadata.gz: 368206d1376231a56d197911245878f8efdf8eb33f86f47135c079f2d3c28b2ac5a70786b7bafaa694b980f6f192ea6ac2d43ffcdb41f77bbd24aee295c7b9c4
7
+ data.tar.gz: 82c8cb0e9a1171f3a0e90b0db23ebc5f35e2b82401f4db2066b3903db383b8e08f619ab25edefbc0bea4ebab93fde9072d86895bfa864a1f793c4370f5f02f03
data/.rake_tasks~ ADDED
@@ -0,0 +1,20 @@
1
+ build
2
+ build:checksum
3
+ clean
4
+ clobber
5
+ default
6
+ install
7
+ install:local
8
+ release[remote]
9
+ release:guard_clean
10
+ release:rubygem_push
11
+ release:source_control_push[remote]
12
+ rubocop
13
+ rubocop:auto_correct
14
+ rubocop:autocorrect
15
+ rubocop:autocorrect_all
16
+ test
17
+ test:cmd
18
+ test:deps
19
+ test:isolated
20
+ test:slow
data/README.md CHANGED
@@ -74,6 +74,96 @@ user.name # => "Claude"
74
74
  user.created_at # => 2024-01-01 00:00:00 +0000 (Time object)
75
75
  ```
76
76
 
77
+ ## Querying
78
+
79
+ Kweerie provides two main ways to execute queries based on whether they have parameters:
80
+
81
+ ### Parameterized Queries
82
+
83
+ When your query needs parameters, use the `.with` method:
84
+
85
+ ```ruby
86
+ class UsersByDepartment < Kweerie::Base
87
+ bind :department, as: '$1'
88
+ bind :active, as: '$2'
89
+ end
90
+
91
+ # app/queries/users_by_department.sql
92
+ SELECT *
93
+ FROM users
94
+ WHERE department = $1
95
+ AND active = $2;
96
+
97
+ # Using the query
98
+ users = UsersByDepartment.with(
99
+ department: 'Engineering',
100
+ active: true
101
+ )
102
+ ```
103
+
104
+ ### Parameter-free Queries
105
+
106
+ For queries that don't require any parameters, you can use the more semantically appropriate `.all` method:
107
+
108
+ ```ruby
109
+ class AllUsers < Kweerie::Base
110
+ end
111
+
112
+ # app/queries/all_users.sql
113
+ SELECT *
114
+ FROM users
115
+ WHERE active = true
116
+ ORDER BY created_at DESC;
117
+
118
+ # Using the query
119
+ users = AllUsers.all
120
+ ```
121
+
122
+ The `.all` method provides a cleaner interface when you're not binding any parameters. It will raise an error if you try to use it on a query class that has parameter bindings:
123
+
124
+ ```ruby
125
+ # This will raise an ArgumentError
126
+ UsersByDepartment.all
127
+ # => ArgumentError: Cannot use .all on queries with bindings. Use .with instead.
128
+ ```
129
+
130
+ ### Choosing Between .all and .with
131
+
132
+ - Use `.all` when your SQL query is completely static with no parameters
133
+ - Use `.with` when you need to pass parameters to your query
134
+ - Even for parameterized queries, you can use `.with` without arguments if all parameters are optional
135
+
136
+ ```ruby
137
+ # A query with no parameters
138
+ class RecentUsers < Kweerie::Base
139
+ end
140
+ RecentUsers.all # ✓ Clean and semantic
141
+ RecentUsers.with # ✓ Works but less semantic
142
+
143
+ # A query with parameters
144
+ class UsersByStatus < Kweerie::Base
145
+ bind :status, as: '$1'
146
+ end
147
+ UsersByStatus.all # ✗ Raises ArgumentError
148
+ UsersByStatus.with(status: 'active') # ✓ Correct usage
149
+ ```
150
+
151
+ Both methods work with `Kweerie::Base` and `Kweerie::BaseObjects`, returning arrays of hashes or objects respectively:
152
+
153
+ ```ruby
154
+ # Returns array of hashes
155
+ class AllUsers < Kweerie::Base
156
+ end
157
+ users = AllUsers.all
158
+ # => [{"id" => 1, "name" => "Claude"}, ...]
159
+
160
+ # Returns array of objects
161
+ class AllUsers < Kweerie::BaseObjects
162
+ end
163
+ users = AllUsers.all
164
+ # => [#<AllUsers id=1 name="Claude">, ...]
165
+ ```
166
+
77
167
  ### Automatic Type Casting
78
168
 
79
169
  BaseObjects automatically casts common PostgreSQL types to their Ruby equivalents:
@@ -147,7 +237,7 @@ user.changes # => Hash of changes with [old, new] values
147
237
  user.original_attributes # => Original attributes from DB
148
238
  ```
149
239
 
150
- ## PostgreSQL Array Support
240
+ ### PostgreSQL Array Support
151
241
 
152
242
  BaseObjects handles PostgreSQL arrays by converting them to Ruby arrays with proper type casting:
153
243
 
@@ -167,7 +257,7 @@ user.tags # => ["ruby", "rails"]
167
257
  user.scores # => [98.5, 87.2, 92.0]
168
258
  ```
169
259
 
170
- ## Performance Considerations
260
+ ### Performance Considerations
171
261
 
172
262
  BaseObjects creates a unique class for each query result set, with the following optimizations:
173
263
 
@@ -179,7 +269,7 @@ BaseObjects creates a unique class for each query result set, with the following
179
269
 
180
270
  For queries where you don't need the object interface, use `Kweerie::Base` instead for slightly better performance.
181
271
 
182
- ### Rails Generator
272
+ ## Rails Generator
183
273
 
184
274
  If you're using Rails, you can use the generator to create new query files:
185
275
 
@@ -193,7 +283,7 @@ rails generate kweerie UserSearch email name
193
283
 
194
284
  This will create both the Ruby class and SQL file with the appropriate structure.
195
285
 
196
- ### Configuration
286
+ ## Configuration
197
287
 
198
288
  By default, Kweerie uses ActiveRecord's connection if available. You can configure this and other options:
199
289
 
@@ -222,7 +312,7 @@ end
222
312
  - ✅ Configurable connection handling
223
313
  - ✅ Parameter validation
224
314
 
225
- ## Why Kweerie?
315
+ ### Why Kweerie?
226
316
 
227
317
  - **SQL Views Overkill**: When a database view is too heavy-handed but you still want to keep SQL separate from Ruby
228
318
  - **Version Control**: Keep your SQL under version control alongside your Ruby code
@@ -230,11 +320,11 @@ end
230
320
  - **Simple Interface**: Clean, simple API for executing parameterized queries
231
321
  - **Rails Integration**: Works seamlessly with Rails and ActiveRecord
232
322
 
233
- ## Development
323
+ ### Development
234
324
 
235
325
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
236
326
 
237
- ## Contributing
327
+ ### Contributing
238
328
 
239
329
  1. Fork it
240
330
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -242,7 +332,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
242
332
  4. Push to the branch (`git push origin my-new-feature`)
243
333
  5. Create a new Pull Request
244
334
 
245
- ## License
335
+ ### License
246
336
 
247
337
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
248
338
 
data/lib/kweerie/base.rb CHANGED
@@ -45,6 +45,12 @@ module Kweerie
45
45
  result.to_a
46
46
  end
47
47
 
48
+ def all
49
+ raise ArgumentError, "Cannot use .all on queries with bindings. Use .with instead." if bindings.any?
50
+
51
+ with
52
+ end
53
+
48
54
  private
49
55
 
50
56
  def validate_params!(params)
@@ -20,7 +20,7 @@ module Kweerie
20
20
  private
21
21
 
22
22
  def generate_result_class(attribute_names)
23
- @generate_result_class ||= Class.new do
23
+ @generate_result_class ||= Class.new(self) do
24
24
  # Include comparison and serialization modules
25
25
  include Comparable
26
26
 
@@ -29,6 +29,20 @@ module Kweerie
29
29
  attr_reader name
30
30
  end
31
31
 
32
+ define_method :initialize do |attrs|
33
+ # Store both raw and casted versions
34
+ @_raw_original_attributes = attrs.dup
35
+ @_original_attributes = attrs.transform_keys(&:to_s).transform_values do |value|
36
+ type_cast_value(value)
37
+ end
38
+
39
+ attrs.each do |name, value|
40
+ casted_value = type_cast_value(value)
41
+ instance_variable_set("@#{name}", casted_value)
42
+ end
43
+ super() if defined?(super)
44
+ end
45
+
32
46
  define_method :type_cast_value do |value|
33
47
  case value
34
48
  when /^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$/ # DateTime check
@@ -64,17 +78,6 @@ module Kweerie
64
78
  end
65
79
  end
66
80
 
67
- define_method :initialize do |attrs|
68
- # Store original attributes with the same type casting
69
- @_original_attributes = attrs.transform_keys(&:to_s).transform_values do |value|
70
- type_cast_value(value)
71
- end
72
-
73
- attrs.each do |name, value|
74
- casted_value = type_cast_value(value)
75
- instance_variable_set("@#{name}", casted_value)
76
- end
77
- end
78
81
  define_method :parse_pg_array do |value|
79
82
  # Remove the curly braces
80
83
  clean_value = value.gsub(/^{|}$/, "")
@@ -115,7 +118,7 @@ module Kweerie
115
118
  attrs = attribute_names.map do |name|
116
119
  "#{name}=#{instance_variable_get("@#{name}").inspect}"
117
120
  end.join(" ")
118
- "#<#{self.class.name || "Record"} #{attrs}>"
121
+ "#<#{self.class.superclass.name} #{attrs}>"
119
122
  end
120
123
 
121
124
  # Hash-like access
@@ -184,6 +187,11 @@ module Kweerie
184
187
  @_original_attributes
185
188
  end
186
189
 
190
+ # Raw attributes access
191
+ define_method :raw_original_attributes do
192
+ @_raw_original_attributes
193
+ end
194
+
187
195
  # ActiveModel-like changes tracking
188
196
  define_method :changed? do
189
197
  to_h != @_original_attributes
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kweerie
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kweerie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-06 00:00:00.000000000 Z
11
+ date: 2024-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -59,6 +59,7 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".rake_tasks~"
62
63
  - ".rubocop.yml"
63
64
  - CHANGELOG.md
64
65
  - LICENSE.txt