motion 0.4.3 → 0.7.0

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: d25829b24f8c2781bcc44f9132061532d3c5b3466e60e69ab646407d27c32519
4
- data.tar.gz: c3e69af9595e1fe7b659a6ed51a57c252d2028581aa4f154e4a150ee2a74b12c
3
+ metadata.gz: ff2870c4229fefaba7ff72f8275b969006a6b0db22144c234e5dd3554523a95d
4
+ data.tar.gz: 5c5488e3dd2ae17e8bd4db86c5daf64db3093bcf35729a2d185965cc84f8be27
5
5
  SHA512:
6
- metadata.gz: f1bb6c0022e3636d62d6ba054aeac9e16c353bc5d646aa83c460a0eaf1f0fc0774efd71b03d3eb47456a033a66521907fc3e23e29fc02c4d09124a03732e940c
7
- data.tar.gz: aa336213b2487da46b868b8c89f74ff55ec745078ffdb1e75fdeafe7d7707870f8f140013d8d9218e68998f89911813f9e0437d75f9261ccc29ec957990b6b02
6
+ metadata.gz: af5d390212fac33bc5db249f23d9401b5ca5da3c2ef4edfd6a606d68ce5fa4fc8c5153b5e29ee2fb8b4a8d5c07e40aa543e1ef35cef0682c021675a24fcb7fed
7
+ data.tar.gz: 4418c496d43ea478b16c828538fc3a18850c8ba60d68646a715453ee47b80c9751aa1948df1c423002c4b19b223be115d12b9ed4be7ce28cc14db611272d4f04
@@ -13,7 +13,7 @@ module Motion
13
13
  ACTION_METHODS = Set.new(["process_motion"]).freeze
14
14
  private_constant :ACTION_METHODS
15
15
 
16
- # Don't use the ActionCable huertistic for deciding what actions can be
16
+ # Don't use the ActionCable heuristic for deciding what actions can be
17
17
  # called from JavaScript. Instead, hard-code the list so we can make other
18
18
  # methods public without worrying about them being called from JavaScript.
19
19
  def self.action_methods
@@ -66,7 +66,7 @@ module Motion
66
66
 
67
67
  def synchronize
68
68
  component_connection.if_render_required do |component|
69
- transmit(renderer.render(component))
69
+ transmit(renderer.render(component, layout: nil))
70
70
  end
71
71
 
72
72
  streaming_from component_connection.broadcasts,
@@ -84,7 +84,7 @@ module Motion
84
84
  @log_helper ||= LogHelper.for_channel(self)
85
85
  end
86
86
 
87
- # Memoize the renderer on the connection so that it can be shared accross
87
+ # Memoize the renderer on the connection so that it can be shared across
88
88
  # all components. `ActionController::Renderer` is already thread-safe and
89
89
  # designed to be reused.
90
90
  def renderer
@@ -23,9 +23,14 @@ module Motion
23
23
  @controller
24
24
  @request
25
25
  @tag_builder
26
+
27
+ @asset_resolver_strategies
28
+ @assets_environment
26
29
  ].freeze
27
30
 
28
- private_constant :STATE_EXCLUDED_IVARS
31
+ STATE_IVAR_OBFUSCATION_PREFIX = "@__vc_"
32
+
33
+ private_constant :STATE_EXCLUDED_IVARS, :STATE_IVAR_OBFUSCATION_PREFIX
29
34
 
30
35
  def rerender!
31
36
  @_awaiting_forced_rerender = true
@@ -53,7 +58,7 @@ module Motion
53
58
  view_context.capture { super }
54
59
  }
55
60
 
56
- raise RenderAborted, self if html == false
61
+ raise RenderAborted, self unless html
57
62
 
58
63
  Motion.markup_transformer.add_state_to_html(self, html)
59
64
  end
@@ -66,6 +71,7 @@ module Motion
66
71
 
67
72
  def marshal_dump
68
73
  (instance_variables - STATE_EXCLUDED_IVARS)
74
+ .reject { |ivar| ivar.start_with? STATE_IVAR_OBFUSCATION_PREFIX }
69
75
  .map { |ivar| [ivar, instance_variable_get(ivar)] }
70
76
  .to_h
71
77
  end
@@ -41,7 +41,7 @@ module Motion
41
41
  end
42
42
 
43
43
  def process_motion(motion, event = nil)
44
- timing("Proccessed #{motion}") do
44
+ timing("Processed #{motion}") do
45
45
  component.process_motion(motion, event)
46
46
  end
47
47
 
@@ -53,7 +53,7 @@ module Motion
53
53
  end
54
54
 
55
55
  def process_broadcast(broadcast, message)
56
- timing("Proccessed broadcast to #{broadcast}") do
56
+ timing("Processed broadcast to #{broadcast}") do
57
57
  component.process_broadcast broadcast, message
58
58
  end
59
59
 
@@ -65,7 +65,7 @@ module Motion
65
65
  end
66
66
 
67
67
  def process_periodic_timer(timer)
68
- timing("Proccessed periodic timer #{timer}") do
68
+ timing("Processed periodic timer #{timer}") do
69
69
  component.process_periodic_timer timer
70
70
  end
71
71
 
@@ -22,6 +22,10 @@ module Motion
22
22
  raw["value"]
23
23
  end
24
24
 
25
+ def checked?
26
+ raw["checked"]
27
+ end
28
+
25
29
  def attributes
26
30
  raw.fetch("attributes", {})
27
31
  end
data/lib/motion/errors.rb CHANGED
@@ -68,7 +68,7 @@ module Motion
68
68
  class InvalidComponentStateError < ComponentError; end
69
69
 
70
70
  class UnrepresentableStateError < InvalidComponentStateError
71
- def initialize(component, cause)
71
+ def initialize(component, cause, failing_ivars)
72
72
  super(
73
73
  component,
74
74
  "Some state prevented `#{component.class}` from being serialized " \
@@ -79,6 +79,9 @@ module Motion
79
79
  "\n" \
80
80
  "The specific error from `Marshal.dump` was: #{cause}\n" \
81
81
  "\n" \
82
+ "unserializable ivars: #{failing_ivars.join(", ")}\n"\
83
+ "\n" \
84
+ "\n" \
82
85
  "Hint: Ensure that any exotic state variables in " \
83
86
  "`#{component.class}` are removed or replaced."
84
87
  )
@@ -114,7 +117,7 @@ module Motion
114
117
  "of the application to be mounted because new code with old state " \
115
118
  "can lead to unpredictable and unsafe behavior.\n" \
116
119
  "\n" \
117
- "Hint: If you would like to allow this component to surive " \
120
+ "Hint: If you would like to allow this component to survive " \
118
121
  "deployments, consider providing an alternative implimentation for " \
119
122
  "`#{component.class}.upgrade_from`."
120
123
  )
@@ -61,10 +61,22 @@ module Motion
61
61
 
62
62
  private
63
63
 
64
- def dump(component)
64
+ def dump!(component)
65
65
  Marshal.dump(component)
66
+ end
67
+
68
+ def dump(component)
69
+ dump!(component)
66
70
  rescue TypeError => e
67
- raise UnrepresentableStateError.new(component, e.message)
71
+ failing_ivars = []
72
+
73
+ component.marshal_dump.each do |ivar_name, ivar_value|
74
+ dump!(ivar_value)
75
+ rescue TypeError
76
+ failing_ivars << ivar_name
77
+ end
78
+
79
+ raise UnrepresentableStateError.new(component, e.message, failing_ivars)
68
80
  end
69
81
 
70
82
  def load(state)
@@ -4,6 +4,14 @@ require "motion"
4
4
 
5
5
  module Motion
6
6
  module TestHelpers
7
+ class MockComponent < ViewComponent::Base
8
+ include Motion::Component
9
+ end
10
+
11
+ def callback_stub(method_name = :bound)
12
+ Motion::Callback.new(MockComponent.new, method_name)
13
+ end
14
+
7
15
  def assert_motion(component, motion_name)
8
16
  assert motion?(component, motion_name)
9
17
  end
@@ -16,14 +24,47 @@ module Motion
16
24
  component.motions.include?(motion_name.to_s)
17
25
  end
18
26
 
19
- def run_motion(component, motion_name)
27
+ def run_motion(component, motion_name, event = motion_event)
20
28
  if block_given?
21
29
  c = component.dup
22
- c.process_motion(motion_name.to_s)
30
+ c.process_motion(motion_name.to_s, event)
23
31
  yield c
24
32
  else
25
- component.process_motion(motion_name.to_s)
33
+ component.process_motion(motion_name.to_s, event)
26
34
  end
27
35
  end
36
+
37
+ def process_broadcast(component, method_name, msg)
38
+ callback = component.bind(method_name)
39
+ component.process_broadcast(callback.broadcast, msg)
40
+ end
41
+
42
+ def assert_timer(component, method_name, interval)
43
+ assert_equal interval, component.periodic_timers[method_name.to_s]
44
+ end
45
+
46
+ def refute_timer(component, method_name)
47
+ refute timer?(component, method_name)
48
+ end
49
+
50
+ def timer?(component, method_name)
51
+ component.periodic_timers.include?(method_name.to_s)
52
+ end
53
+
54
+ def motion_event(attributes = {})
55
+ Motion::Event.new(ActiveSupport::JSON.decode(attributes.to_json)).tap do |event|
56
+ set_form_data(event, attributes)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def set_form_data(event, attrs)
63
+ return event unless attrs.fetch(:element, nil)
64
+
65
+ form_data = attrs.dig(:element, :formData) || {}
66
+ params = ActionController::Parameters.new(form_data)
67
+ event.element.instance_variable_set(:@form_data, params)
68
+ end
28
69
  end
29
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Motion
4
- VERSION = "0.4.3"
4
+ VERSION = "0.7.0"
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alec Larsen
8
8
  - Drew Ulmer
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-22 00:00:00.000000000 Z
12
+ date: 2022-06-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '5.1'
34
+ version: '5.2'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '5.1'
41
+ version: '5.2'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: lz4-ruby
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -102,7 +102,7 @@ metadata:
102
102
  source_code_uri: https://github.com/unabridged/motion
103
103
  post_install_message: |
104
104
  Friendly reminder: When updating the motion gem, don't forget to update the
105
- NPM package as well (`bin/yarn add '@unabridged/motion@0.4.3'`).
105
+ NPM package as well (`bin/yarn add '@unabridged/motion@0.7.0'`).
106
106
  rdoc_options: []
107
107
  require_paths:
108
108
  - lib
@@ -117,8 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 3.0.3
121
- signing_key:
120
+ rubygems_version: 3.1.6
121
+ signing_key:
122
122
  specification_version: 4
123
123
  summary: Reactive frontend UI components for Rails in pure Ruby.
124
124
  test_files: []