svelte-on-rails 5.3.2 → 6.0.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: 66ba05e463ee27dcf6234fd49f46f1879daecd331f52549080d1d9f2f9e0748d
4
- data.tar.gz: 1947be68d44b723ed074098728db6a0aaba6e5c5bbbb72dc09604b5fc4dc93f3
3
+ metadata.gz: 6a07c9c33f2ef2d71acbd9986cc841fada803a3692abec84719648e9d5d94c79
4
+ data.tar.gz: 8677455b7ef6137269451b12f9ed8350ff7ba842198f89e2864f7e6c5615a20e
5
5
  SHA512:
6
- metadata.gz: 3c4a60a0c0f2d372535af2a7972c4df70ecb2958e0f0f2e9c718f6aeeccbab8f2797c329ec8ea789e5aa9d9e5154bc5b5cc88f70d0a5211416aa1d5d0296d8ad
7
- data.tar.gz: afa1cef4cef2787e3da4d0a040b6261f1313b503ae149238faa74f779c46a5d78a569a4ac98c84d0e76276c514d8940f9dd6b6086a58c9c7e54490a2671d18a1
6
+ metadata.gz: 9a97fd9a881d5fa6b32f4faacf87ded1210939984e01274b4fb334b6f5444624ede7dac476e8fa2daa83f960d2f34ecacdc49cbebb4d0ed548c05f5425900622
7
+ data.tar.gz: 1caab439e622e43009cbc1ff2ee193fa35e0bbc0b63128ca0c917787536a01d3e92910f52e110fcec38d17533e6e7c7415d05ce87970d07fd9f45287801c8355
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 `#svelte_attributes` helper to your models, example:
305
+ Adds the `#to_svelte` helper to your models, example:
306
306
 
307
307
  ```ruby
308
- @book.svelte_attributes(
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,23 +327,48 @@ 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
- "name" => "Name", # translated by human_attribute_name..
337
+ "name" => "Name", # translated by human_attribute_name
328
338
  "calculation_method" => "Calculation method",
329
339
  "author" => "Author"
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
- If an optional `belongs_to` association is empty, the labels are still calculated.
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
- **Caching:** The component's attributes are used to generate a checksum, which serves as the cache key for efficient storage and retrieval.
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
 
@@ -10,6 +10,7 @@ require "svelte_on_rails/renderer/renderer"
10
10
 
11
11
  require "svelte_on_rails/lib/utils"
12
12
  require "svelte_on_rails/lib/view_helper_support"
13
+ require "svelte_on_rails/lib/to_svelte"
13
14
 
14
15
  # installer
15
16
  require 'svelte_on_rails/installer/utils'
@@ -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
- unless defined?(ActiveRecord::Base) && base.ancestors.include?(ActiveRecord::Base)
6
- raise 'SvelteOnRails::ActiveRecordExtensions can only be included in ActiveRecord models'
7
- end
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 svelte_attributes(*attributes)
12
- @svelte_attributes ||= begin
11
+ def to_svelte(*attributes)
12
+ @to_svelte ||= begin
13
13
 
14
- # separate offset and limit
14
+ cl = SvelteOnRails::Lib::SvelteAttributes
15
+ cl.new.calculate_instance(self, attributes)
15
16
 
16
- h = attributes.grep(Hash)
17
- attr = if h.present?
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
- utils = SvelteOnRails::Lib::Utils
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,192 @@
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
+ raise "[svelte-on-rails:to_svelte] #{record.class} does not respond to: #{key}" unless record.respond_to?(key)
51
+ _offset, _limit, _value = extract_limit(value)
52
+
53
+ _key = key.to_s
54
+
55
+ # inspect association and set_labels
56
+
57
+ reflect = record.class.reflect_on_association(_key)
58
+ raise "invalid association: #{_key}" unless reflect
59
+ set_labels(reflect, value)
60
+
61
+ # values
62
+
63
+ recs = record.send(_key)
64
+ if recs.present?
65
+ if recs.respond_to?(:each)
66
+ values[_key] = calculate_instance(
67
+ recs,
68
+ value,
69
+ call_stack: next_stack,
70
+ offset: _offset,
71
+ limit: _limit
72
+ )
73
+ else
74
+ values[_key] = calculate_instance(
75
+ recs,
76
+ value,
77
+ call_stack: next_stack
78
+ )
79
+ end
80
+ end
81
+ end
82
+
83
+ else
84
+ # we have attributes
85
+ raise 'Invalid attribute' unless [Symbol, String].include?(attr.class)
86
+ raise "[svelte-on-rails:to_svelte] #{record.class} does not respond to: #{attr}" unless record.respond_to?(attr)
87
+ _key = attr.to_s
88
+
89
+ values[_key] = record.send(_key)
90
+ end
91
+
92
+ end
93
+ end
94
+
95
+ if call_stack >= 1
96
+ values
97
+ else
98
+ { 'values' => values }.merge(@labels)
99
+ end
100
+
101
+ end
102
+
103
+ def calculate_class(model, attributes, call_stack: 0)
104
+
105
+ next_stack = call_stack + 1
106
+
107
+ set_labels(model, attributes)
108
+
109
+ hash = attributes.find { |element| element.is_a?(Hash) } || {}
110
+ hash.each do |key, value|
111
+ reflect = model.reflect_on_association(key.to_s)
112
+ if reflect
113
+ calculate_class(
114
+ reflect,
115
+ value,
116
+ call_stack: next_stack
117
+ )
118
+ end
119
+ end
120
+
121
+ if call_stack == 0
122
+ @labels
123
+ end
124
+ end
125
+
126
+ def calculate_relation(relation, attributes, call_stack: 0)
127
+ set_labels(relation.klass, attributes)
128
+ values = relation.map do |rec|
129
+ calculate_instance(rec, attributes)['values']
130
+ end
131
+ {
132
+ 'values' => values
133
+ }.merge(@labels)
134
+ end
135
+
136
+ private
137
+
138
+ def extract_limit(attributes)
139
+
140
+ _hash_args = attributes.grep(Hash).first.dup
141
+ attr, lim = if _hash_args.present?
142
+ hash_args = _hash_args.transform_keys { |key| key.to_s } # multiple arrays is not possible
143
+ hash_remainder = hash_args.reject { |key, _| %w[offset limit].include?(key.to_s) }
144
+ _attr = attributes.reject { |item| item.is_a?(Hash) }
145
+ [
146
+ if hash_remainder.any?
147
+ _attr + [hash_remainder]
148
+ else
149
+ _attr
150
+ end,
151
+ hash_args
152
+ ]
153
+ else
154
+ [
155
+ attributes,
156
+ {}
157
+ ]
158
+ end
159
+
160
+ [
161
+ lim['offset'],
162
+ lim['limit'],
163
+ attr
164
+ ]
165
+ end
166
+
167
+ def set_labels(record, keys)
168
+
169
+ first_hash = keys.find { |element| element.is_a?(Hash) }
170
+ _keys = keys.reject { |element| element.is_a?(Hash) }
171
+ _keys += first_hash.keys if first_hash
172
+
173
+ _keys.each do |attr|
174
+ unless attr.respond_to?(:each)
175
+ obj = if record.respond_to?(:human_attribute_name)
176
+ record
177
+ elsif record.class.respond_to?(:human_attribute_name)
178
+ record.class
179
+ end
180
+
181
+ next unless obj
182
+
183
+ @labels["#{obj.to_s.underscore}_labels"] ||= {}
184
+ @labels["#{obj.to_s.underscore}_labels"][attr.to_s] ||= obj.human_attribute_name(attr)
185
+
186
+ end
187
+ end
188
+ end
189
+
190
+ end
191
+ end
192
+ 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: 5.3.2
4
+ version: 6.0.1
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