inertia_builder 0.1.1 → 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: db89ab90b2cb82bff0edc49732dfb8662a1e1af582fa0a81b8b7b569f631f107
4
- data.tar.gz: 63832da96a198430e738e3ca368ed9a3977415b615039d8a81c4c3dcec2b7a5a
3
+ metadata.gz: c2db7cf7bc04f52285ccfb06231fcb67cca0038b80140b84ec314f2cf9f1196b
4
+ data.tar.gz: '02989fb26e14f25cbfe80ca52559813137c7cbf67c9983afed7f0cb23ad59451'
5
5
  SHA512:
6
- metadata.gz: 790787ba727eb3473a560275061fc28fe9a80a29bf8218a560471acb760b01b09599194542aa6b0bed8c491fad95d2c5741fa8b514ed149bd00e93d6ea175fdb
7
- data.tar.gz: a1c8f57f40b69b96f2597614ef2e801bcabb21d7b019de7ebb0fe9c0feab8ca233c755c8d126d42cc0dc44e1d191431c834157cbdedbf20fcdc098c01d45722a
6
+ metadata.gz: faf2b72091c7fecc1c74f51b91e3a1e2237e8878d61777b8b6f5ed9505185c8a81c5cca058b0fcc470f42d98014783cd6b28a5494125a76df4525cbaac82b537
7
+ data.tar.gz: 359cfcca048b25bde18ac719f9a2a3dbccb02d1081d5c3886b424afcab8ef202d3d4997323640490ab3b63d1c48fa0806da861fa13dda60c7195442c3aa05d85
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InertiaBuilder
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.1'
5
5
  end
@@ -4,18 +4,52 @@ require 'jbuilder/jbuilder_template'
4
4
  require 'inertia_builder/handler'
5
5
  require 'inertia_builder/controller'
6
6
  require 'inertia_builder/renderer'
7
- require 'inertia_builder/railtie' if defined?(Rails)
7
+ require 'inertia_builder/railtie'
8
8
 
9
9
  class JbuilderTemplate
10
- self.template_lookup_options = { handlers: [:inertia] }
10
+ self.template_lookup_options = { handlers: %i[inertia jbuilder] }
11
11
  end
12
12
 
13
13
  module InertiaBuilder
14
14
  class PropBuilder < JbuilderTemplate
15
15
  alias props attributes!
16
16
 
17
+ def optional!(&block)
18
+ _call_inertia_block(:optional, &block)
19
+ end
20
+
21
+ def always!(&block)
22
+ _call_inertia_block(:always, &block)
23
+ end
24
+
25
+ def defer!(**opts, &block)
26
+ _call_inertia_block(:defer, **opts, &block)
27
+ end
28
+
29
+ def method_missing(name, *args, &block)
30
+ prop = self
31
+
32
+ if @inertia_block
33
+ method, opts = @inertia_block
34
+ _set_value(name, ::InertiaRails.send(method, **opts) { prop.set!(name, *args, &block) })
35
+ elsif !@in_scope
36
+ # Lazy evaluate outermost properties.
37
+ _set_value(name, -> { prop.set!(name, *args, &block); })
38
+ else
39
+ super
40
+ end
41
+ end
42
+
17
43
  private
18
44
 
45
+ def _call_inertia_block(method, **opts)
46
+ ::Kernel.raise "Nesting #{method}! in a #{@inertia_block[0]}! block is not allowed" if @inertia_block
47
+
48
+ @inertia_block = [method, opts]
49
+ yield
50
+ @inertia_block = nil
51
+ end
52
+
19
53
  def _render_partial_with_options(options)
20
54
  options[:locals] ||= options.except(:partial, :as, :collection, :cached)
21
55
  options[:locals][:prop] = self
@@ -30,5 +64,25 @@ module InertiaBuilder
30
64
  def _render_active_model_partial(object)
31
65
  @context.render object, prop: self
32
66
  end
67
+
68
+ def _scope
69
+ has_parent_scope = @in_scope
70
+ @in_scope = true
71
+ super
72
+ ensure
73
+ @in_scope = false unless has_parent_scope
74
+ end
75
+
76
+ def _merge_values(current_value, updates)
77
+ # Always override lazy evaluation procs. For the other special prop types, InertiaRails already handles merging.
78
+ if current_value.is_a?(::Proc) ||
79
+ current_value.is_a?(::InertiaRails::OptionalProp) ||
80
+ current_value.is_a?(::InertiaRails::AlwaysProp) ||
81
+ current_value.is_a?(::InertiaRails::DeferProp)
82
+ updates
83
+ else
84
+ super
85
+ end
86
+ end
33
87
  end
34
88
  end
@@ -8,6 +8,11 @@ class User < Struct.new(:id, :first_name, :last_name, :email)
8
8
  include ActiveModel::Conversion
9
9
  end
10
10
 
11
+ class Item < Struct.new(:id, :title)
12
+ extend ActiveModel::Naming
13
+ include ActiveModel::Conversion
14
+ end
15
+
11
16
  class InertiaBuilderTest < Minitest::Test
12
17
  USER_PARTIAL = <<~INERTIA
13
18
  prop.id user.id
@@ -16,8 +21,14 @@ class InertiaBuilderTest < Minitest::Test
16
21
  prop.email user.email
17
22
  INERTIA
18
23
 
24
+ ITEM_PARTIAL = <<~INERTIA
25
+ prop.id item.id
26
+ prop.title item.title
27
+ INERTIA
28
+
19
29
  PARTIALS = {
20
- 'users/_user.html.inertia' => USER_PARTIAL
30
+ 'users/_user.html.inertia' => USER_PARTIAL,
31
+ 'items/_item.html.inertia' => ITEM_PARTIAL
21
32
  }
22
33
 
23
34
  def test_basic_html_rendering
@@ -47,8 +58,8 @@ class InertiaBuilderTest < Minitest::Test
47
58
  }
48
59
  }
49
60
 
50
- assert_equal inertia_html_with_props(expected_props), render_view(template)
51
61
  assert_equal inertia_json_with_props(expected_props), render_view(template, json: true)
62
+ assert_equal inertia_html_with_props(expected_props), render_view(template)
52
63
  end
53
64
 
54
65
  def test_collection_prop
@@ -75,9 +86,9 @@ class InertiaBuilderTest < Minitest::Test
75
86
 
76
87
  expected_props = { products: products }
77
88
 
78
- assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { products: products })
79
89
  assert_equal inertia_json_with_props(expected_props),
80
90
  render_view(template, assigns: { products: products }, json: true)
91
+ assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { products: products })
81
92
  end
82
93
 
83
94
  def test_basic_partial_prop
@@ -91,8 +102,8 @@ class InertiaBuilderTest < Minitest::Test
91
102
 
92
103
  expected_props = { user: user }
93
104
 
94
- assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { user: user })
95
105
  assert_equal inertia_json_with_props(expected_props), render_view(template, assigns: { user: user }, json: true)
106
+ assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { user: user })
96
107
  end
97
108
 
98
109
  def test_collection_partial_prop
@@ -119,12 +130,23 @@ class InertiaBuilderTest < Minitest::Test
119
130
  User.new({ id: 43, first_name: 'Jane', last_name: 'Smith', email: 'jane@email.com' })
120
131
  ]
121
132
 
122
- template = "prop.users @users, partial: 'users/user', as: :user"
133
+ items = [
134
+ Item.new({ id: 1, title: 'Item 1' }),
135
+ Item.new({ id: 2, title: 'Item 2' })
136
+ ]
123
137
 
124
- expected_props = { users: users }
138
+ template = <<~INERTIA
139
+ prop.data do
140
+ prop.users @users, partial: 'users/user', as: :user
141
+ prop.items @items, partial: 'items/item', as: :item
142
+ end
143
+ INERTIA
125
144
 
126
- assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { users: users })
127
- assert_equal inertia_json_with_props(expected_props), render_view(template, assigns: { users: users }, json: true)
145
+ expected_props = { data: { users: users, items: items } }
146
+
147
+ assert_equal inertia_json_with_props(expected_props),
148
+ render_view(template, assigns: { users: users, items: items }, json: true)
149
+ assert_equal inertia_html_with_props(expected_props), render_view(template, assigns: { users: users, items: items })
128
150
  end
129
151
 
130
152
  def test_nil_prop_block
@@ -140,11 +162,110 @@ class InertiaBuilderTest < Minitest::Test
140
162
  assert_equal inertia_json_with_props(expected_props), render_view(template, json: true)
141
163
  end
142
164
 
165
+ def test_optional_block
166
+ template = <<~INERTIA
167
+ prop.id 1
168
+ prop.optional! do
169
+ prop.user do
170
+ prop.id 1
171
+ prop.email 'user@email.com'
172
+ end
173
+ prop.calculation 'Calculation'
174
+ end
175
+ INERTIA
176
+
177
+ partial_headers = {
178
+ 'X-Inertia-Partial-Data' => 'user,calculation',
179
+ 'X-Inertia-Partial-Component' => '/'
180
+ }
181
+ assert_equal inertia_json_with_props({ id: 1 }), render_view(template, json: true)
182
+ assert_equal inertia_json_with_props({ user: { id: 1, email: 'user@email.com' }, calculation: 'Calculation' }),
183
+ render_view(template, json: true, headers: partial_headers)
184
+ end
185
+
186
+ def test_always_block
187
+ template = <<~INERTIA
188
+ prop.id 1
189
+ prop.always! do
190
+ prop.user do
191
+ prop.id 1
192
+ prop.email 'user@email.com'
193
+ end
194
+ end
195
+ prop.optional! do
196
+ prop.calculation 'Calculation'
197
+ end
198
+ INERTIA
199
+
200
+ partial_headers = {
201
+ 'X-Inertia-Partial-Data' => 'calculation',
202
+ 'X-Inertia-Partial-Component' => '/'
203
+ }
204
+ assert_equal inertia_json_with_props({ id: 1, user: { id: 1, email: 'user@email.com' } }),
205
+ render_view(template, json: true)
206
+ assert_equal inertia_json_with_props({ user: { id: 1, email: 'user@email.com' }, calculation: 'Calculation' }),
207
+ render_view(template, json: true, headers: partial_headers)
208
+ end
209
+
210
+ def test_defer_block
211
+ template = <<~INERTIA
212
+ prop.id 1
213
+ prop.defer! do
214
+ prop.user do
215
+ prop.id 1
216
+ prop.email 'user@email.com'
217
+ end
218
+ prop.calculation 'Calculation'
219
+ end
220
+ INERTIA
221
+
222
+ assert_equal inertia_json_with_props({ id: 1 }, deferredProps: { default: %w[user calculation] }),
223
+ render_view(template, json: true)
224
+ end
225
+
226
+ def test_defer_block_grouping
227
+ template = <<~INERTIA
228
+ prop.id 1
229
+ prop.defer! group: 'group1' do
230
+ prop.user 'User'
231
+ end
232
+ prop.defer! group: 'group2' do
233
+ prop.calculation 'Calculation'
234
+ end
235
+ INERTIA
236
+
237
+ assert_equal inertia_json_with_props({ id: 1 }, deferredProps: { group1: ['user'], group2: ['calculation'] }),
238
+ render_view(template, json: true)
239
+ end
240
+
241
+ def test_defer_block_fetching
242
+ user = User.new({ id: 1, email: 'user@email.com' })
243
+
244
+ template = <<~INERTIA
245
+ prop.id 1
246
+ prop.defer! do
247
+ prop.user do
248
+ prop.partial! @user
249
+ end
250
+ prop.calculation 'Calculation'
251
+ end
252
+ INERTIA
253
+
254
+ partial_headers = {
255
+ 'X-Inertia-Partial-Data' => 'user,calculation',
256
+ 'X-Inertia-Partial-Component' => '/'
257
+ }
258
+
259
+ assert_equal inertia_json_with_props({ user: user, calculation: 'Calculation' }),
260
+ render_view(template, assigns: { user: user }, json: true, headers: partial_headers)
261
+ end
262
+
143
263
  private
144
264
 
145
- def render_view(source, assigns: {}, json: false)
265
+ def render_view(source, **opts)
146
266
  req = ActionDispatch::TestRequest.create
147
- req.headers['X-Inertia'] = 'true' if json
267
+ req.headers.merge!(opts[:headers] || {})
268
+ req.headers['X-Inertia'] = 'true' if opts[:json]
148
269
 
149
270
  controller = ActionView::TestCase::TestController.new
150
271
  controller.request = req
@@ -152,7 +273,7 @@ class InertiaBuilderTest < Minitest::Test
152
273
  resolver = ActionView::FixtureResolver.new(PARTIALS.merge('source.html.inertia' => source))
153
274
  lookup = ActionView::LookupContext.new([resolver], {}, [''])
154
275
 
155
- view = ActionView::Base.with_empty_template_cache.new(lookup, assigns, controller)
276
+ view = ActionView::Base.with_empty_template_cache.new(lookup, opts[:assigns] || [], controller)
156
277
 
157
278
  view.render(template: 'source')
158
279
  end
@@ -163,7 +284,7 @@ class InertiaBuilderTest < Minitest::Test
163
284
  HTML
164
285
  end
165
286
 
166
- def inertia_json_with_props(props)
287
+ def inertia_json_with_props(props, **extra_fields)
167
288
  {
168
289
  component: '/',
169
290
  props: { errors: {} }.merge(props),
@@ -171,6 +292,6 @@ class InertiaBuilderTest < Minitest::Test
171
292
  version: nil,
172
293
  encryptHistory: false,
173
294
  clearHistory: false
174
- }.to_json
295
+ }.merge(extra_fields).to_json
175
296
  end
176
297
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inertia_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Lima
@@ -70,8 +70,8 @@ licenses:
70
70
  - MIT
71
71
  metadata:
72
72
  bug_tracker_uri: https://github.com/rodrigotavio91/inertia-builder/issues
73
- changelog_uri: https://github.com/rodrigotavio91/inertia-builder/releases/tag/v0.1.1
74
- source_code_uri: https://github.com/rodrigotavio91/inertia-builder/tree/v0.1.1
73
+ changelog_uri: https://github.com/rodrigotavio91/inertia-builder/releases/tag/v0.2.1
74
+ source_code_uri: https://github.com/rodrigotavio91/inertia-builder/tree/v0.2.1
75
75
  rubygems_mfa_required: 'true'
76
76
  rdoc_options: []
77
77
  require_paths: