view_component_reflex 1.0.1 → 1.4.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: 82d4e40f0f58fd47d6c163e9054b3497eb46ec96a1e963037d96793dbea35530
4
- data.tar.gz: d169f2e5a7816ee41f56cf033037c61ebb4085b201c85185c8df1cccadbbadb6
3
+ metadata.gz: f79604a043d4aa353ade5fec1bb3c1d7f263352304555fe3fe70dfd35fc921b9
4
+ data.tar.gz: 88259eb0924cf1508df64f5bb3565fac61134871d2ac210c3166c560bb0f028e
5
5
  SHA512:
6
- metadata.gz: 61562e94b88bc140382c480f61e0b9e6afb7024177378978b14fd02a7d2658042fc530798ccafb65cea2092d0438a968b32361afde80b0fb23deea73b2475f5a
7
- data.tar.gz: b7b4d73cca02d7a2b70d4b43570e09a2a7acede221d9516c29aa68232d421f05cb27da0a743f532369f0db068e01c30c7ed207c426e48a9b2e1fd7857383efab
6
+ metadata.gz: 30d400ca7ace85a4f9bc9b25b6e4cdddfceb6518c980cbcb35f6e6f2216b03a5615cb882b91f9f9097bbce2b2495d306698b4c5bbedecae4259e97750d396bc9
7
+ data.tar.gz: 1c70cda5b7f89057079b86729d97a47a5b429e5f0bdd56732c4695841fe933c0ff57bf1b5143ec0fb7c54cac67bbc8a9c32d031337f33ec91949eb420eba67ac
data/README.md CHANGED
@@ -34,6 +34,42 @@ end
34
34
  <% end %>
35
35
  ```
36
36
 
37
+ ## Collections
38
+
39
+ In order to reconcile state to components in collections, you can specify a `collection_key` method that returns some
40
+ value unique to that component.
41
+
42
+ ```
43
+ class TodoComponent < ViewComponentReflex::Component
44
+ def initialize(todo:)
45
+ @todo = todo
46
+ end
47
+
48
+ def collection_key
49
+ @todo.id
50
+ end
51
+ end
52
+ #
53
+ <%= render(TodoComponent.with_collection(Todo.all)) %>
54
+ ```
55
+
56
+ ## API
57
+
58
+ ### permit_parameter?(initial_param, new_params)
59
+ If a new parameter is passed to the component during rendering, it is used instead of what's in state.
60
+ If you're storing instances in state, you can use this to properly compare them.
61
+
62
+ ### omitted_from_state
63
+ Return an array of instance variables you want to omit from state. Useful if you have an object
64
+ that isn't serializable as an instance variable, like a form.
65
+
66
+ ```
67
+ def omitted_from_state
68
+ [:@form]
69
+ end
70
+ ```
71
+
72
+
37
73
  ## Custom State Adapters
38
74
 
39
75
  ViewComponentReflex uses session for its state by default. To change this, add
@@ -57,13 +93,13 @@ class YourAdapter
57
93
  end
58
94
 
59
95
  ##
60
- # set_state is used to modify the state. It accepts a reflex, which gives you
61
- # access to the request, as well as the controller and other useful objects.
96
+ # set_state is used to modify the state.
62
97
  #
63
- # reflex - The reflex instance that's trying to set the state
98
+ # request - a rails request object
99
+ # controller - the current controller
64
100
  # key - a unique string that identifies the component
65
101
  # new_state - the new state to set
66
- def self.set_state(reflex, key, new_state)
102
+ def self.set_state(request, controller, key, new_state)
67
103
  # update the state
68
104
  end
69
105
 
@@ -4,7 +4,7 @@ module ViewComponentReflex
4
4
  def init_stimulus_reflex
5
5
  klass = self
6
6
  @stimulus_reflex ||= Object.const_set(name + "Reflex", Class.new(StimulusReflex::Reflex) {
7
- def refresh!(primary_selector = "[data-controller=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]", *selectors)
7
+ def refresh!(primary_selector = "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]", *selectors)
8
8
  save_state
9
9
  @channel.send :render_page_and_broadcast_morph, self, [primary_selector, *selectors], {
10
10
  "dataset" => element.dataset.to_h,
@@ -43,7 +43,11 @@ module ViewComponentReflex
43
43
  component.instance_variable_set(k, v)
44
44
  end
45
45
  name.to_proc.call(component, *args)
46
- refresh!
46
+ refresh! unless @prevent_refresh
47
+ end
48
+
49
+ def prevent_refresh!
50
+ @prevent_refresh = true
47
51
  end
48
52
 
49
53
  define_method :component_class do
@@ -62,7 +66,7 @@ module ViewComponentReflex
62
66
  return @component if @component
63
67
  @component = component_class.allocate
64
68
  reflex = self
65
- exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller]
69
+ exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller, :session, :prevent_refresh!]
66
70
  exposed_methods.each do |meth|
67
71
  @component.define_singleton_method(meth) do |*a|
68
72
  reflex.send(meth, *a)
@@ -72,7 +76,7 @@ module ViewComponentReflex
72
76
  end
73
77
 
74
78
  def set_state(new_state = {})
75
- ViewComponentReflex::Engine.state_adapter.set_state(self, element.dataset[:key], new_state)
79
+ ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
76
80
  end
77
81
 
78
82
  def state
@@ -98,24 +102,42 @@ module ViewComponentReflex
98
102
  helpers.controller.instance_variable_get(:@stimulus_reflex)
99
103
  end
100
104
 
101
- def component_controller(&blk)
102
- opts = {data: {controller: self.class.stimulus_controller, key: key}}
103
- view_context.content_tag :div, capture(&blk), opts
105
+ def component_controller(opts = {}, &blk)
106
+ self.class.init_stimulus_reflex
107
+ init_key
108
+ opts[:data] = {
109
+ controller: self.class.stimulus_controller,
110
+ key: key,
111
+ **(opts[:data] || {})
112
+ }
113
+ content_tag :div, capture(&blk), opts
104
114
  end
105
115
 
106
116
  # key is required if you're using state
107
117
  # We can't initialize the session state in the initial method
108
118
  # because it doesn't have a view_context yet
109
119
  # This is the next best place to do it
110
- def key
111
- self.class.init_stimulus_reflex
120
+ def init_key
112
121
  # we want the erb file that renders the component. `caller` gives the file name,
113
122
  # and line number, which should be unique. We hash it to make it a nice number
114
123
  key = caller.select { |p| p.include? ".html.erb" }[1]&.hash.to_s
115
- if @key.nil? || @key.empty?
116
- @key = key
117
- end
124
+ key += collection_key.to_s if collection_key
125
+ @key = key
126
+ end
118
127
 
128
+ def collection_key
129
+ nil
130
+ end
131
+
132
+ def permit_parameter?(initial_param, new_param)
133
+ initial_param != new_param
134
+ end
135
+
136
+ def omitted_from_state
137
+ []
138
+ end
139
+
140
+ def key
119
141
  # initialize session state
120
142
  if !stimulus_reflex? || session[@key].nil?
121
143
  new_state = {}
@@ -124,15 +146,19 @@ module ViewComponentReflex
124
146
  blacklist = [
125
147
  :@view_context, :@lookup_context, :@view_renderer, :@view_flow,
126
148
  :@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
127
- :@helpers, :@controller, :@request
149
+ :@helpers, :@controller, :@request, :@content
128
150
  ]
129
151
  instance_variables.reject { |k| blacklist.include?(k) }.each do |k|
130
- new_state[k] = instance_variable_get(k)
152
+ new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
131
153
  end
132
154
  ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
155
+ ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
133
156
  else
157
+ initial_state = ViewComponentReflex::Engine.state_adapter.state(request, "#{@key}_initial")
134
158
  ViewComponentReflex::Engine.state_adapter.state(request, @key).each do |k, v|
135
- instance_variable_set(k, v)
159
+ unless permit_parameter?(initial_state[k], instance_variable_get(k))
160
+ instance_variable_set(k, v)
161
+ end
136
162
  end
137
163
  end
138
164
  @key
@@ -5,12 +5,12 @@ module ViewComponentReflex
5
5
  request.session[key] ||= {}
6
6
  end
7
7
 
8
- def self.set_state(reflex, key, new_state)
8
+ def self.set_state(request, controller, key, new_state)
9
9
  new_state.each do |k, v|
10
- state(reflex.request, key)[k] = v
10
+ state(request, key)[k] = v
11
11
  end
12
- store = reflex.request.session.instance_variable_get("@by")
13
- store.commit_session reflex.request, reflex.controller.response
12
+ store = request.session.instance_variable_get("@by")
13
+ store.commit_session request, controller.response
14
14
  end
15
15
 
16
16
  def self.store_state(request, key, new_state = {})
@@ -1,3 +1,3 @@
1
1
  module ViewComponentReflex
2
- VERSION = '1.0.1'
2
+ VERSION = '1.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component_reflex
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua LeBlanc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-19 00:00:00.000000000 Z
11
+ date: 2020-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails