svelte-on-rails 5.3.2 → 6.0.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 +4 -4
- data/README.md +35 -5
- data/lib/svelte-on-rails.rb +1 -0
- data/lib/svelte_on_rails/active_record_extensions.rb +26 -27
- data/lib/svelte_on_rails/lib/to_svelte.rb +190 -0
- data/lib/svelte_on_rails/lib/utils.rb +0 -126
- data/lib/svelte_on_rails/railtie.rb +8 -0
- data/templates/all_features_test/app/controllers/svelte_on_rails_hello_world_controller.rb +0 -4
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72ff2251a05680fdb51fa556c72aaba218728a0040265412544d838ef7a4b4e7
|
4
|
+
data.tar.gz: 394c75169ba815b224e74f5b4c3e2675f50845505f4e00c52bdecf363b9db4ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfbbe11843b3b00a104bba37d942c98f5e49aca735f0b933475a3ee77b495418758eb83638b073dd7ed5e866a32bacc4c434e6daaa33e7b98303aa8731093bfe
|
7
|
+
data.tar.gz: a228c78ccf69847ff2f61d360734af6d1e7cb912b3928d6af056585fa1cabc0d121405c5d7b9099b659d15143a1771937e6d3745aa80bfd8a39d73e0fea66b0a
|
data/README.md
CHANGED
@@ -302,13 +302,18 @@ But, in normal cases it should not be neccessary testing ssr explicitly.
|
|
302
302
|
|
303
303
|
## ActiveRecord helpers
|
304
304
|
|
305
|
-
Adds the `#
|
305
|
+
Adds the `#to_svelte` helper to your models, example:
|
306
306
|
|
307
307
|
```ruby
|
308
|
-
@book.
|
308
|
+
@book.to_svelte(
|
309
309
|
:name,
|
310
310
|
:calculation_method,
|
311
|
-
author: [:name]
|
311
|
+
author: [:name],
|
312
|
+
editions: [
|
313
|
+
:date,
|
314
|
+
offset: 2,
|
315
|
+
limit: 1
|
316
|
+
]
|
312
317
|
)
|
313
318
|
```
|
314
319
|
|
@@ -322,6 +327,11 @@ would result in something like this:
|
|
322
327
|
"author" => {
|
323
328
|
"name" => "Michael Hartl"
|
324
329
|
},
|
330
|
+
"editions" => [
|
331
|
+
{
|
332
|
+
date: "2025-02-03"
|
333
|
+
}
|
334
|
+
]
|
325
335
|
},
|
326
336
|
"book_labels" => {
|
327
337
|
"name" => "Name", # translated by human_attribute_name..
|
@@ -330,15 +340,35 @@ would result in something like this:
|
|
330
340
|
},
|
331
341
|
"author_labels": {
|
332
342
|
"name" => "Name"
|
343
|
+
},
|
344
|
+
"edition_labels" => {
|
345
|
+
"date" => "Date"
|
333
346
|
}
|
334
347
|
}
|
335
348
|
```
|
336
349
|
|
337
350
|
This should ease transferring data you need within the component mostly.
|
338
351
|
|
339
|
-
|
352
|
+
The same method is applicable for:
|
353
|
+
|
354
|
+
- The model itself
|
355
|
+
- It returns only the labels: Same result like above, but without the `values` key
|
356
|
+
- `ActiveRecord::Relation`
|
357
|
+
- Same result like above, but `values` then is a Array.
|
358
|
+
|
359
|
+
If a association returns a empty result, the labels are still calculated.
|
360
|
+
|
361
|
+
`offset` and `limit` are reserved keys, so, columns with the same name would be ignored.
|
362
|
+
|
363
|
+
**Caching:**
|
364
|
+
|
365
|
+
Caching Capability is not implemented on this method, you easily can wrap it by `Redis`
|
340
366
|
|
341
|
-
|
367
|
+
If used on the `cached_svelte_component` view helper,
|
368
|
+
the component's attributes are used to generate a checksum, which serves as the
|
369
|
+
cache key for efficient storage and retrieval. So, this method is meant to
|
370
|
+
make it easier to exactly filter out only the information that is needed
|
371
|
+
on the component.
|
342
372
|
|
343
373
|
## Caching
|
344
374
|
|
data/lib/svelte-on-rails.rb
CHANGED
@@ -1,41 +1,40 @@
|
|
1
1
|
# lib/svelte_on_rails/active_record_extensions.rb
|
2
2
|
module SvelteOnRails
|
3
3
|
module ActiveRecordExtensions
|
4
|
-
def self.included(base)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
4
|
+
# def self.included(base)
|
5
|
+
# unless defined?(ActiveRecord::Base) && base.ancestors.include?(ActiveRecord::Base)
|
6
|
+
# raise 'SvelteOnRails::ActiveRecordExtensions can only be included in ActiveRecord models'
|
7
|
+
# end
|
8
|
+
# end
|
9
9
|
|
10
10
|
# Returns a hash of attributes, methods, and associations formatted for Svelte components
|
11
|
-
def
|
12
|
-
@
|
11
|
+
def to_svelte(*attributes)
|
12
|
+
@to_svelte ||= begin
|
13
13
|
|
14
|
-
|
14
|
+
cl = SvelteOnRails::Lib::SvelteAttributes
|
15
|
+
cl.new.calculate_instance(self, attributes)
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
opts = h.first.symbolize_keys
|
19
|
-
offset = opts[:offset]
|
20
|
-
limit = opts[:limit]
|
21
|
-
if offset || limit
|
22
|
-
unless self.respond_to?(:each)
|
23
|
-
raise 'offset and limit are only supported for record sets that respond to :each'
|
24
|
-
end
|
25
|
-
_opts = opts.reject { |key, _| [:offset, :limit].include?(key) }
|
26
|
-
attributes.select { |item| !item.is_a?(Hash) }.push(_opts)
|
27
|
-
else
|
28
|
-
attributes
|
29
|
-
end
|
30
|
-
else
|
31
|
-
attributes
|
32
|
-
end
|
17
|
+
end
|
18
|
+
end
|
33
19
|
|
34
|
-
|
35
|
-
utils.svelte_attributes(self, attr, offset: offset, limit: limit)
|
20
|
+
end
|
36
21
|
|
22
|
+
module ActiveRecordClassExtensions
|
23
|
+
def to_svelte(*attributes)
|
24
|
+
@to_svelte ||= begin
|
25
|
+
cl = SvelteOnRails::Lib::SvelteAttributes
|
26
|
+
cl.new.calculate_class(self, attributes)
|
37
27
|
end
|
38
28
|
end
|
29
|
+
end
|
39
30
|
|
31
|
+
module ActiveRecordRelationExtensions
|
32
|
+
def to_svelte(*attributes)
|
33
|
+
@to_svelte ||= begin
|
34
|
+
cl = SvelteOnRails::Lib::SvelteAttributes
|
35
|
+
cl.new.calculate_relation(self, attributes)
|
36
|
+
end
|
37
|
+
end
|
40
38
|
end
|
39
|
+
|
41
40
|
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module SvelteOnRails
|
2
|
+
module Lib
|
3
|
+
class SvelteAttributes
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@labels = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def calculate_instance(record, attributes, call_stack: 0, offset: nil, limit: nil)
|
10
|
+
|
11
|
+
next_stack = call_stack + 1
|
12
|
+
|
13
|
+
if record.respond_to?(:each)
|
14
|
+
|
15
|
+
recs2 = if offset || limit
|
16
|
+
if (record.is_a?(ActiveRecord::Relation) || record.is_a?(ActiveRecord::Associations::CollectionProxy) rescue false)
|
17
|
+
_recs = (offset ? record.offset(offset) : record)
|
18
|
+
(limit ? _recs.limit(limit) : _recs)
|
19
|
+
elsif record.respond_to?(:drop) && record.respond_to?(:take) # that might be a array
|
20
|
+
_recs = offset ? record.drop(offset) : record
|
21
|
+
limit ? _recs.take(limit) : _recs
|
22
|
+
else
|
23
|
+
raise "[svelte-on-rails:to_svelte] unknown class for records: #{record}"
|
24
|
+
end
|
25
|
+
else
|
26
|
+
record
|
27
|
+
end
|
28
|
+
|
29
|
+
set_labels(record.first, attributes)
|
30
|
+
|
31
|
+
values = recs2.map do |rec|
|
32
|
+
calculate_instance(rec, attributes, call_stack: next_stack)
|
33
|
+
end
|
34
|
+
|
35
|
+
else
|
36
|
+
|
37
|
+
# we have a single record
|
38
|
+
|
39
|
+
values = {}
|
40
|
+
|
41
|
+
set_labels(record, attributes)
|
42
|
+
|
43
|
+
attributes.each do |attr|
|
44
|
+
|
45
|
+
if attr.is_a? Hash
|
46
|
+
|
47
|
+
# we have associations
|
48
|
+
attr.each do |key, value|
|
49
|
+
next if ['offset', 'limit'].include?(key.to_s)
|
50
|
+
_offset, _limit, _value = extract_limit(value)
|
51
|
+
|
52
|
+
_key = key.to_s
|
53
|
+
|
54
|
+
# inspect association and set_labels
|
55
|
+
|
56
|
+
reflect = record.class.reflect_on_association(_key)
|
57
|
+
raise "invalid association: #{_key}" unless reflect
|
58
|
+
set_labels(reflect, value)
|
59
|
+
|
60
|
+
# values
|
61
|
+
|
62
|
+
recs = record.send(_key)
|
63
|
+
if recs.present?
|
64
|
+
if recs.respond_to?(:each)
|
65
|
+
values[_key] = calculate_instance(
|
66
|
+
recs,
|
67
|
+
value,
|
68
|
+
call_stack: next_stack,
|
69
|
+
offset: _offset,
|
70
|
+
limit: _limit
|
71
|
+
)
|
72
|
+
else
|
73
|
+
values[_key] = calculate_instance(
|
74
|
+
recs,
|
75
|
+
value,
|
76
|
+
call_stack: next_stack
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
else
|
83
|
+
# we have attributes
|
84
|
+
raise 'Invalid attribute' unless [Symbol, String].include?(attr.class)
|
85
|
+
_key = attr.to_s
|
86
|
+
|
87
|
+
values[_key] = record.send(_key)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if call_stack >= 1
|
94
|
+
values
|
95
|
+
else
|
96
|
+
{ 'values' => values }.merge(@labels)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def calculate_class(model, attributes, call_stack: 0)
|
102
|
+
|
103
|
+
next_stack = call_stack + 1
|
104
|
+
|
105
|
+
set_labels(model, attributes)
|
106
|
+
|
107
|
+
hash = attributes.find { |element| element.is_a?(Hash) } || {}
|
108
|
+
hash.each do |key, value|
|
109
|
+
reflect = model.reflect_on_association(key.to_s)
|
110
|
+
if reflect
|
111
|
+
calculate_class(
|
112
|
+
reflect,
|
113
|
+
value,
|
114
|
+
call_stack: next_stack
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if call_stack == 0
|
120
|
+
@labels
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def calculate_relation(relation, attributes, call_stack: 0)
|
125
|
+
set_labels(relation.klass, attributes)
|
126
|
+
values = relation.map do |rec|
|
127
|
+
calculate_instance(rec, attributes)['values']
|
128
|
+
end
|
129
|
+
{
|
130
|
+
'values' => values
|
131
|
+
}.merge(@labels)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def extract_limit(attributes)
|
137
|
+
|
138
|
+
_hash_args = attributes.grep(Hash).first.dup
|
139
|
+
attr, lim = if _hash_args.present?
|
140
|
+
hash_args = _hash_args.transform_keys { |key| key.to_s } # multiple arrays is not possible
|
141
|
+
hash_remainder = hash_args.reject { |key, _| %w[offset limit].include?(key.to_s) }
|
142
|
+
_attr = attributes.reject { |item| item.is_a?(Hash) }
|
143
|
+
[
|
144
|
+
if hash_remainder.any?
|
145
|
+
_attr + [hash_remainder]
|
146
|
+
else
|
147
|
+
_attr
|
148
|
+
end,
|
149
|
+
hash_args
|
150
|
+
]
|
151
|
+
else
|
152
|
+
[
|
153
|
+
attributes,
|
154
|
+
{}
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
[
|
159
|
+
lim['offset'],
|
160
|
+
lim['limit'],
|
161
|
+
attr
|
162
|
+
]
|
163
|
+
end
|
164
|
+
|
165
|
+
def set_labels(record, keys)
|
166
|
+
|
167
|
+
first_hash = keys.find { |element| element.is_a?(Hash) }
|
168
|
+
_keys = keys.reject { |element| element.is_a?(Hash) }
|
169
|
+
_keys += first_hash.keys if first_hash
|
170
|
+
|
171
|
+
_keys.each do |attr|
|
172
|
+
unless attr.respond_to?(:each)
|
173
|
+
obj = if record.respond_to?(:human_attribute_name)
|
174
|
+
record
|
175
|
+
elsif record.class.respond_to?(:human_attribute_name)
|
176
|
+
record.class
|
177
|
+
end
|
178
|
+
|
179
|
+
next unless obj
|
180
|
+
|
181
|
+
@labels["#{obj.to_s.underscore}_labels"] ||= {}
|
182
|
+
@labels["#{obj.to_s.underscore}_labels"][attr.to_s] ||= obj.human_attribute_name(attr)
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -163,132 +163,6 @@ module SvelteOnRails
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
-
def self.svelte_attributes(record, attributes, labels: {}, call_stack: 0, offset: nil, limit: nil)
|
167
|
-
|
168
|
-
if record.is_a?(Class)
|
169
|
-
|
170
|
-
# this is the case if a belongs_to association is empty; In that case we pass the class itself and extract only the labels
|
171
|
-
raise 'limit and offset are supported only for iterable objects' if limit || offset
|
172
|
-
attributes.each do |attr|
|
173
|
-
unless attr.respond_to?(:each)
|
174
|
-
labels["#{record.to_s.underscore}_labels"] ||= {}
|
175
|
-
labels["#{record.to_s.underscore}_labels"][attr.to_s] ||= record.human_attribute_name(attr)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
values = {}
|
179
|
-
|
180
|
-
elsif record.respond_to?(:each)
|
181
|
-
|
182
|
-
unless record.is_a?(ActiveRecord::Relation) || record.is_a?(ActiveRecord::Associations::CollectionProxy)
|
183
|
-
raise 'record set must be a Article::ActiveRecord_Associations_CollectionProxy'
|
184
|
-
end
|
185
|
-
|
186
|
-
recs = (offset ? record.offset(offset) : record)
|
187
|
-
recs2 = (limit ? recs.limit(limit) : recs)
|
188
|
-
|
189
|
-
values = recs2.map do |rec|
|
190
|
-
svelte_attributes(rec, attributes, labels: labels, call_stack: call_stack + 1)
|
191
|
-
end
|
192
|
-
|
193
|
-
else
|
194
|
-
|
195
|
-
# we have a single record
|
196
|
-
|
197
|
-
raise 'limit and offset are supported only for iterable objects' if limit || offset
|
198
|
-
values = {}
|
199
|
-
|
200
|
-
table_name = record.class.to_s.underscore
|
201
|
-
|
202
|
-
attributes.each do |attr|
|
203
|
-
|
204
|
-
if attr.is_a? Hash
|
205
|
-
|
206
|
-
# we have associations
|
207
|
-
attr.each do |key, value|
|
208
|
-
_key = key.to_s
|
209
|
-
|
210
|
-
# skip and fetch offset and limit
|
211
|
-
if key.to_s.match(/_limit$/) && !record.respond_to?(key)
|
212
|
-
raise 'Invalid attribute' unless record.respond_to?(key.to_s[0..-7])
|
213
|
-
next
|
214
|
-
end
|
215
|
-
if key.to_s.match(/_offset$/) && !record.respond_to?(key)
|
216
|
-
raise 'Invalid attribute' unless record.respond_to?(key.to_s[0..-8])
|
217
|
-
next
|
218
|
-
end
|
219
|
-
offs, lim = svelte_attribute_extract_limit(record, attributes, _key)
|
220
|
-
|
221
|
-
labels["#{table_name}_labels"] ||= {}
|
222
|
-
labels["#{table_name}_labels"][_key] ||= record.class.human_attribute_name(_key)
|
223
|
-
|
224
|
-
# values
|
225
|
-
|
226
|
-
reflect = record.class.reflect_on_association(_key)
|
227
|
-
if reflect
|
228
|
-
recs = record.send(_key)
|
229
|
-
content = (recs.present? ? recs : reflect.active_record) # if no record, we extract only the labels
|
230
|
-
if content.respond_to?(:each)
|
231
|
-
values[_key] = svelte_attributes(
|
232
|
-
content,
|
233
|
-
value,
|
234
|
-
labels: labels,
|
235
|
-
call_stack: call_stack + 1,
|
236
|
-
offset: offs,
|
237
|
-
limit: lim
|
238
|
-
)
|
239
|
-
else
|
240
|
-
values[_key] = svelte_attributes(
|
241
|
-
content,
|
242
|
-
value,
|
243
|
-
labels: labels,
|
244
|
-
call_stack: call_stack + 1,
|
245
|
-
offset: offs,
|
246
|
-
limit: lim
|
247
|
-
)
|
248
|
-
end
|
249
|
-
else
|
250
|
-
raise "invalid association: #{_key}"
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
else
|
255
|
-
# we have attributes
|
256
|
-
raise 'Invalid attribute' unless [Symbol, String].include?(attr.class)
|
257
|
-
_key = attr.to_s
|
258
|
-
|
259
|
-
labels["#{table_name}_labels"] ||= {}
|
260
|
-
labels["#{table_name}_labels"][_key] ||= record.class.human_attribute_name(_key)
|
261
|
-
|
262
|
-
values[_key] = record.send(_key)
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
if call_stack >= 1
|
269
|
-
values
|
270
|
-
else
|
271
|
-
{ 'values' => values }.merge(labels)
|
272
|
-
end
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
private
|
277
|
-
|
278
|
-
def self.svelte_attribute_extract_limit(record, attributes, key)
|
279
|
-
|
280
|
-
hash_args = attributes.grep(Hash).first.with_indifferent_access # multiple arrays is not possible
|
281
|
-
|
282
|
-
offset = if hash_args["#{key}_offset"] && !record.respond_to?("#{key}_offset")
|
283
|
-
hash_args["#{key}_offset"]
|
284
|
-
end
|
285
|
-
|
286
|
-
limit = if hash_args["#{key}_limit"] && !record.respond_to?("#{key}_limit")
|
287
|
-
hash_args["#{key}_limit"]
|
288
|
-
end
|
289
|
-
|
290
|
-
[offset, limit]
|
291
|
-
end
|
292
166
|
end
|
293
167
|
end
|
294
168
|
end
|
@@ -15,10 +15,18 @@ module SvelteOnRails
|
|
15
15
|
|
16
16
|
initializer 'svelte_on_rails.active_record_extensions' do
|
17
17
|
ActiveSupport.on_load(:active_record) do
|
18
|
+
# Include instance-level extensions
|
18
19
|
include SvelteOnRails::ActiveRecordExtensions
|
20
|
+
# Extend with class-level extensions
|
21
|
+
extend SvelteOnRails::ActiveRecordClassExtensions
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
25
|
+
# Extend ActiveRecord::Relation
|
26
|
+
ActiveSupport.on_load(:active_record_relation) do
|
27
|
+
include SvelteOnRails::ActiveRecordRelationExtensions
|
28
|
+
end
|
29
|
+
|
22
30
|
rake_tasks do
|
23
31
|
load File.expand_path("../../tasks/svelte_on_rails_tasks.rake", __FILE__)
|
24
32
|
end
|
@@ -5,10 +5,6 @@ class SvelteOnRailsHelloWorldController < ApplicationController
|
|
5
5
|
|
6
6
|
def web_socket_action
|
7
7
|
|
8
|
-
# render plain: Article.first.svelte_attributes(:name) #(:name, :calc_method, children: [:name], children_limit: 2, parent: [:name]).to_json
|
9
|
-
#
|
10
|
-
# return
|
11
|
-
|
12
8
|
comp = 'ReceiveFromChannel'
|
13
9
|
|
14
10
|
case params['stream']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: svelte-on-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Sedlmair
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- lib/svelte_on_rails/installer/utils.rb
|
44
44
|
- lib/svelte_on_rails/installer/vite.rb
|
45
45
|
- lib/svelte_on_rails/lib/development_utils.rb
|
46
|
+
- lib/svelte_on_rails/lib/to_svelte.rb
|
46
47
|
- lib/svelte_on_rails/lib/utils.rb
|
47
48
|
- lib/svelte_on_rails/lib/view_helper_support.rb
|
48
49
|
- lib/svelte_on_rails/railtie.rb
|