dynamic-records-meritfront 3.0.1 → 3.0.6
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +50 -29
- data/lib/dynamic-records-meritfront/version.rb +1 -1
- data/lib/dynamic-records-meritfront.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa816c1fc2d4e08950ff1f91c1bb4aa1d8025a4e845d62919e7254e449a6901f
|
4
|
+
data.tar.gz: 4649ad599b97346ca16ddbb5f07298fd0408d5028795fcfcb3e5f0b5d1f906c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2dbba9dee9ca11dab5665b0d96a2b13840f7bfff8eb28c859e8628119efb420924435ed06ca380dc9fec7408231cf7a7f9671429cc34c18c2e0536646324a3ba
|
7
|
+
data.tar.gz: cddf05b9c1f9eb9df8c1c7fb1a586dc618eed8a5f3fd0a0b8f8b4017d3bbb0beee66143c4925bd102af52d2ea6e302c5fda7384ca8c4f7cfafa8b481afefc0f8
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -11,14 +11,12 @@ Note that postgres is currently a requirement for this gem.
|
|
11
11
|
```ruby
|
12
12
|
# returns a json-like hash list of user data
|
13
13
|
users = ApplicationRecord.dynamic_sql(
|
14
|
-
'get_5_users',
|
15
14
|
'select * from users limit :our_limit',
|
16
15
|
our_limit: 5
|
17
16
|
)
|
18
17
|
|
19
18
|
#returns a list of users (each an instance of User)
|
20
19
|
users = User.dynamic_sql(
|
21
|
-
'get_users_from_ids',
|
22
20
|
'select * from users where id = ANY (:ids)',
|
23
21
|
ids: [1,2,3]
|
24
22
|
)
|
@@ -53,28 +51,34 @@ Or install it yourself as:
|
|
53
51
|
class ApplicationRecord < ActiveRecord::Base
|
54
52
|
self.abstract_class = true
|
55
53
|
include DynamicRecordsMeritfront
|
56
|
-
|
54
|
+
|
55
|
+
#DYNAMIC_SQL_RAW determines whether dynamic_sql method returns a ActiveRecord::Response object or an Array.
|
56
|
+
#They both have pros and cons. False returns the array.
|
57
|
+
DynamicRecordsMeritfront::DYNAMIC_SQL_RAW = false
|
57
58
|
end
|
58
59
|
```
|
59
60
|
|
60
61
|
### SQL methods
|
61
62
|
|
62
|
-
|
63
|
+
Methods written for easier sql usage.
|
63
64
|
|
64
|
-
#### self.dynamic_sql(name, sql, opts = { })
|
65
|
+
#### self.dynamic_sql( *optional* name, sql, opts = { })
|
65
66
|
A better and safer way to write sql. Can return either a Hash, ActiveRecord::Response object, or an instantiated model.
|
66
67
|
|
68
|
+
```ruby
|
69
|
+
User.dynamic_sql('select * from users') #returns all users
|
70
|
+
ApplicationRecord.dynamic_sql('select * from users') #returns all user column information in an array
|
71
|
+
```
|
72
|
+
|
67
73
|
with options:
|
68
74
|
- options not stated below: considered sql arguments, and will replace their ":option_name" with a sql argument. Always use sql arguments to avoid sql injection. Lists are converted into a format such as ```{1,2,3,4}```. Lists of lists are converted into ```(1,2,3), (4,5,6), (7,8,9)``` etc. So as to allow easy inserts/upserts.
|
69
75
|
- raw: whether to return a ActiveRecord::Response object or a hash when called on an abstract class (like ApplicationRecord). Default can be switched with DYNAMIC_SQL_RAW variable on the class level.
|
70
|
-
- instantiate_class: determines what format to return. Can return ActiveRecord objects (User, Post, etc), or whatever raw is set to. I prefer doing the alterantive ```User.dynamic_sql(...)``` which is also supported. For example, ```User.dynamic_sql(...)``` will return User records. ```ApplicationRecord.dynamic_sql(..., raw: false)``` will return a List of Hashes with the column names as keys. ```ApplicationRecord.dynamic_sql(..., raw: true)``` will return an ActiveRecord::Response.
|
71
76
|
|
72
|
-
other options:
|
77
|
+
other less critical options:
|
73
78
|
|
74
79
|
- prepare: Defaults to true. Gets passed to ActiveRecord::Base.connection.exec_query as a parameter. Should change whether the command will be prepared, which means that on subsequent calls the command will be faster. Downsides are when, for example, the sql query has hard-coded arguments, the query always changes, causing technical issues as the number of prepared statements stack up.
|
75
|
-
- name_modifiers: allows one to change the associated name dynamically.
|
76
80
|
- multi_query: allows more than one query (you can seperate an insert and an update with ';' I dont know how else to say it.)
|
77
|
-
this disables other options including
|
81
|
+
this disables other options including sql_arguments. Not sure how it effects prepared statements. Not super useful.
|
78
82
|
- async: Defaults to false. Gets passed to ActiveRecord::Base.connection.exec_query as a parameter. See that methods documentation for more. I was looking through the source code, and I think it only effects how it logs to the logfile?
|
79
83
|
|
80
84
|
<details>
|
@@ -91,7 +95,7 @@ Delete Friend Requests between two users after they have become friends.
|
|
91
95
|
</details>
|
92
96
|
|
93
97
|
<details>
|
94
|
-
<summary>
|
98
|
+
<summary>example usage with interpreted sql string</summary>
|
95
99
|
Get all users who have made a friend request to a particular user with an optional limit.
|
96
100
|
This is an example of why this method is good for dynamic prepared statements.
|
97
101
|
|
@@ -106,9 +110,7 @@ This is an example of why this method is good for dynamic prepared statements.
|
|
106
110
|
) AS all_friend_requests
|
107
111
|
ORDER BY all_friend_requests.created_at DESC
|
108
112
|
#{"LIMIT :limit" if limit > 0}
|
109
|
-
}, uid: u, limit: limit
|
110
|
-
limit > 0 ? 'limited' : nil
|
111
|
-
])
|
113
|
+
}, uid: u, limit: limit)
|
112
114
|
```
|
113
115
|
</details>
|
114
116
|
|
@@ -117,13 +119,13 @@ This is an example of why this method is good for dynamic prepared statements.
|
|
117
119
|
|
118
120
|
```ruby
|
119
121
|
#get a normal test vote
|
120
|
-
test = Vote.dynamic_sql(
|
122
|
+
test = Vote.dynamic_sql(%Q{
|
121
123
|
SELECT id FROM votes LIMIT 1
|
122
124
|
}).first
|
123
125
|
v.inspect # "#<Vote id: 696969>"
|
124
126
|
|
125
127
|
#get a cool test vote. Note that is_this_vote_cool is not on the vote table.
|
126
|
-
test = Vote.dynamic_sql(
|
128
|
+
test = Vote.dynamic_sql(%Q{
|
127
129
|
SELECT id, 'yes' AS is_this_vote_cool FROM votes LIMIT 1
|
128
130
|
}).first
|
129
131
|
test.inspect # #<Vote id: 696969, is_this_vote_cool: "yes"> #getting attributes added dynamically to the models, and also showing up on inspects, was... more difficult than i anticipated.
|
@@ -147,27 +149,28 @@ Get users who match a list of ids. Uses a postgresql Array, see the potential is
|
|
147
149
|
Do an upsert
|
148
150
|
|
149
151
|
```ruby
|
152
|
+
time = DateTime.now
|
150
153
|
rows = uzrs.map{|u| [
|
151
154
|
u.id, #user_id
|
152
155
|
self.id, #conversation_id
|
153
156
|
from, #invited_by
|
154
|
-
|
155
|
-
|
157
|
+
:time, #created_at (We use symbols to denote other sql arguments)
|
158
|
+
:time, #updated_at
|
156
159
|
]}
|
157
160
|
ApplicationRecord.dynamic_sql("upsert_conversation_invites_2", %Q{
|
158
161
|
INSERT INTO conversation_participants (user_id, conversation_id, invited_by, created_at, updated_at)
|
159
162
|
VALUES :rows
|
160
163
|
ON CONFLICT (conversation_id,user_id)
|
161
164
|
DO UPDATE SET updated_at = :time
|
162
|
-
}, rows: rows, time:
|
165
|
+
}, rows: rows, time: time)
|
163
166
|
```
|
164
|
-
This will output sql similar to below. Note this can be done for multiple conversation_participants. Also note that
|
167
|
+
This will output sql similar to below. Note this can be done for multiple conversation_participants. Also note that we sent only one time variable during our request instead of duplicating it.
|
165
168
|
```sql
|
166
169
|
INSERT INTO conversation_participants (user_id, conversation_id, invited_by, created_at, updated_at)
|
167
170
|
VALUES ($1,$2,$3,$4,$4)
|
168
171
|
ON CONFLICT (conversation_id,user_id)
|
169
172
|
DO UPDATE SET updated_at = $4
|
170
|
-
-- [["rows_1", 15], ["rows_2", 67], ["rows_3", 6], [
|
173
|
+
-- [["rows_1", 15], ["rows_2", 67], ["rows_3", 6], [:time, "2022-10-13 20:49:27.441372"]]
|
171
174
|
```
|
172
175
|
</details>
|
173
176
|
|
@@ -175,6 +178,10 @@ This will output sql similar to below. Note this can be done for multiple conver
|
|
175
178
|
#### self.dynamic_preload(records, associations)
|
176
179
|
Preloads from a list of records, and not from a ActiveRecord_Relation. This will be useful when using the above dynamic_sql method (as it returns a list of records, and not a record relation). This is basically the same as a normal relation preload but it works on a list.
|
177
180
|
|
181
|
+
```ruby
|
182
|
+
ApplicationRecord.dynamic_preload(comments, [:votes])
|
183
|
+
```
|
184
|
+
|
178
185
|
<details>
|
179
186
|
<summary>example usage</summary>
|
180
187
|
Preload :votes on some comments. :votes is an active record has_many relation.
|
@@ -184,7 +191,7 @@ Preload :votes on some comments. :votes is an active record has_many relation.
|
|
184
191
|
SELECT * FROM comments LIMIT 4
|
185
192
|
})
|
186
193
|
comments.class.to_s # 'Array' note: not a relation.
|
187
|
-
ApplicationRecord.
|
194
|
+
ApplicationRecord.dynamic_preload(comments, [:votes])
|
188
195
|
puts comments[0].votes #this line should be preloaded and hence not call the database
|
189
196
|
|
190
197
|
#note that this above is basically the same as doing the below assuming there is a comments relation on the user model.
|
@@ -199,6 +206,10 @@ good during enum migrations as the code to migrate wont run if enumerate is ther
|
|
199
206
|
as it is not yet enumerated (causing an error when it loads the class that will have the
|
200
207
|
enumeration in it). This can lead it to being impossible to commit clean code.
|
201
208
|
|
209
|
+
```ruby
|
210
|
+
ApplicationRecord.has_run_migration?('UserImageRelationsTwo')
|
211
|
+
```
|
212
|
+
|
202
213
|
<details><summary>example usage</summary>
|
203
214
|
only load relationa if it exists in the database
|
204
215
|
|
@@ -219,6 +230,10 @@ end
|
|
219
230
|
|
220
231
|
accepts a list of association names, checks if the model has those associations
|
221
232
|
|
233
|
+
```ruby
|
234
|
+
obj.has_association?(:votes)
|
235
|
+
```
|
236
|
+
|
222
237
|
<details><summary>example usage</summary>
|
223
238
|
Check if object is a votable class
|
224
239
|
|
@@ -230,19 +245,27 @@ obj.has_association?(:votes) #false
|
|
230
245
|
```
|
231
246
|
</details>
|
232
247
|
|
233
|
-
#### self.
|
248
|
+
#### self.instaload_sql( *optional* name, insta_array, opts = { })
|
234
249
|
*instaloads* a bunch of diffrent models at the same time by casting them to json before returning them. Kinda cool. Maybe a bit overcomplicated. Seems to be more efficient to preloading when i tested it.
|
235
250
|
- name is passed to dynamic_sql and is the name of the sql request
|
236
251
|
- opts are passed to dynamic_sql (except for the raw option which is set to true. Raw output is not allowed on this request)
|
237
252
|
- requires a list of instaload method output which provides information for how to treat each sql block.
|
238
|
-
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
out = ApplicationRecord.instaload_sql([
|
256
|
+
ApplicationRecord.instaload("SELECT id FROM users", relied_on: true, dont_return: true, table_name: "users_2"),
|
257
|
+
ApplicationRecord.instaload("SELECT id FROM users_2 WHERE id % 2 != 0 LIMIT :limit", table_name: 'a'),
|
258
|
+
User.instaload("SELECT id FROM users_2 WHERE id % 2 != 1 LIMIT :limit", table_name: 'b')
|
259
|
+
], limit: 2)
|
260
|
+
```
|
261
|
+
|
239
262
|
<details>
|
240
263
|
<summary>example usage</summary>
|
241
264
|
#get list of users, those users friends, and who those users follow, all in one request.
|
242
265
|
|
243
266
|
```ruby
|
244
267
|
# the ruby entered
|
245
|
-
output = ApplicationRecord.
|
268
|
+
output = ApplicationRecord.instaload_sql([
|
246
269
|
User.instaload('SELECT id FROM users WHERE users.id = ANY (:user_ids) AND users.created_at > :time', table_name: 'limited_users', relied_on: true),
|
247
270
|
User.instaload(%Q{
|
248
271
|
SELECT friends.smaller_user_id AS id, friends.bigger_user_id AS friended_to
|
@@ -297,13 +320,11 @@ the output:
|
|
297
320
|
{"followable_id"=>932, "follower_id"=>23},
|
298
321
|
{"followable_id"=>935, "follower_id"=>19},
|
299
322
|
...]}
|
300
|
-
|
301
|
-
|
302
323
|
```
|
303
324
|
</details>
|
304
325
|
|
305
326
|
#### self.instaload(sql, table_name: nil, relied_on: false, dont_return: false)
|
306
|
-
A method used to prepare data for the
|
327
|
+
A method used to prepare data for the instaload_sql method. It returns a hash of options.
|
307
328
|
- klass called on: if called on an abstract class (ApplicationRecord) it will return a list of hashes with the data. Otherwise returns a list of the classes records.
|
308
329
|
- table_name: sets the name of the temporary postgresql table. This can then be used in further instaload sql snippets.
|
309
330
|
- relied_on: will make it so other instaload sql snippets can reference this table (it makes it use posrgresql's WITH operator)
|
@@ -329,7 +350,7 @@ User.instaload('SELECT id FROM users WHERE users.id = ANY (:user_ids) AND users.
|
|
329
350
|
</details>
|
330
351
|
|
331
352
|
#### self.dynamic_attach(instaload_sql_output, base_name, attach_name, base_on: nil, attach_on: nil, one_to_one: false)
|
332
|
-
taking the output of the
|
353
|
+
taking the output of the instaload_sql method, this method creates relations between the models.
|
333
354
|
- base_name: the name of the table we will be attaching to
|
334
355
|
- attach_name: the name of the table that will be attached
|
335
356
|
- base_on: put a proc here to override the matching key for the base table. Default is, for a user and post type, {|user| user.id}
|
@@ -337,7 +358,7 @@ taking the output of the dynamic_instaload_sql, this method attaches the models
|
|
337
358
|
- one_to_one: switches between a one-to-one relationship or not
|
338
359
|
|
339
360
|
<details>
|
340
|
-
<summary> attach information for each limited_user in the
|
361
|
+
<summary> attach information for each limited_user in the instaload_sql example </summary>
|
341
362
|
|
342
363
|
```ruby
|
343
364
|
|
@@ -17,7 +17,7 @@ module DynamicRecordsMeritfront
|
|
17
17
|
#should work, probably able to override by redefining in ApplicationRecord class.
|
18
18
|
#Note we defined here as it breaks early on as Rails.application returns nil
|
19
19
|
PROJECT_NAME = Rails.application.class.to_s.split("::").first.to_s.downcase
|
20
|
-
DYNAMIC_SQL_RAW =
|
20
|
+
DYNAMIC_SQL_RAW = true
|
21
21
|
end
|
22
22
|
class DynamicSqlVariables
|
23
23
|
attr_accessor :sql_hash
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic-records-meritfront
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Clancy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashid-rails
|