optimism 0.4.2 → 0.5.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: 8966741ac69e6f62196d1ea78a71a30dda97fa56e6618fb844a829a5d8d93008
4
- data.tar.gz: 5f7e64c28e697af5dd3a782549abf6a4872870f7bab9833868ed196a251bc806
3
+ metadata.gz: 9519a511dec44dd176cdd2f1f13ba50b31846cc9f9247088b821d3117728c052
4
+ data.tar.gz: 26acc98ea3fbd2fafec358ecd007b7258518b2cc75e4c387b16e7106771a2e91
5
5
  SHA512:
6
- metadata.gz: 936c07c2d033fc9d0f932cb31ef073a62a919cc53c635b14b896520d387c4ba8beaa94348e3b67a42786aca948fd0f3760a80530d90f874099db7d177d61bd47
7
- data.tar.gz: 8526dc93dd499644f9ebcf63ea3bb3fd24ff672a8ea7579518900800a2738b40cfefb3b96e9de228cb5e97ed718f05c6064871579487c49229e9288309d63a1a
6
+ metadata.gz: 7294ff7de16b9119b348af7db1e29747747cc968546ea5610e2463cbe8f72804412a36b3f73a4eafc4c49d72f38d59b4765e0c0e824867f786e7886884615728
7
+ data.tar.gz: ac8eef02349c7cea595bfa4235609ebe4e33ff6e0fcc28599a887667cc9daee584a76ef38b02e59eac16caab629ffe1f2474945252af6f3679d723076835369d
data/Gemfile.lock CHANGED
@@ -2,67 +2,67 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  optimism (0.3.5)
5
- cable_ready (>= 4)
5
+ cable_ready (>= 4.4.6)
6
6
  rack (~> 2.0)
7
7
  rails (>= 6, >= 5.2)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (6.1.0)
13
- actionpack (= 6.1.0)
14
- activesupport (= 6.1.0)
12
+ actioncable (6.1.4.1)
13
+ actionpack (= 6.1.4.1)
14
+ activesupport (= 6.1.4.1)
15
15
  nio4r (~> 2.0)
16
16
  websocket-driver (>= 0.6.1)
17
- actionmailbox (6.1.0)
18
- actionpack (= 6.1.0)
19
- activejob (= 6.1.0)
20
- activerecord (= 6.1.0)
21
- activestorage (= 6.1.0)
22
- activesupport (= 6.1.0)
17
+ actionmailbox (6.1.4.1)
18
+ actionpack (= 6.1.4.1)
19
+ activejob (= 6.1.4.1)
20
+ activerecord (= 6.1.4.1)
21
+ activestorage (= 6.1.4.1)
22
+ activesupport (= 6.1.4.1)
23
23
  mail (>= 2.7.1)
24
- actionmailer (6.1.0)
25
- actionpack (= 6.1.0)
26
- actionview (= 6.1.0)
27
- activejob (= 6.1.0)
28
- activesupport (= 6.1.0)
24
+ actionmailer (6.1.4.1)
25
+ actionpack (= 6.1.4.1)
26
+ actionview (= 6.1.4.1)
27
+ activejob (= 6.1.4.1)
28
+ activesupport (= 6.1.4.1)
29
29
  mail (~> 2.5, >= 2.5.4)
30
30
  rails-dom-testing (~> 2.0)
31
- actionpack (6.1.0)
32
- actionview (= 6.1.0)
33
- activesupport (= 6.1.0)
31
+ actionpack (6.1.4.1)
32
+ actionview (= 6.1.4.1)
33
+ activesupport (= 6.1.4.1)
34
34
  rack (~> 2.0, >= 2.0.9)
35
35
  rack-test (>= 0.6.3)
36
36
  rails-dom-testing (~> 2.0)
37
37
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
38
- actiontext (6.1.0)
39
- actionpack (= 6.1.0)
40
- activerecord (= 6.1.0)
41
- activestorage (= 6.1.0)
42
- activesupport (= 6.1.0)
38
+ actiontext (6.1.4.1)
39
+ actionpack (= 6.1.4.1)
40
+ activerecord (= 6.1.4.1)
41
+ activestorage (= 6.1.4.1)
42
+ activesupport (= 6.1.4.1)
43
43
  nokogiri (>= 1.8.5)
44
- actionview (6.1.0)
45
- activesupport (= 6.1.0)
44
+ actionview (6.1.4.1)
45
+ activesupport (= 6.1.4.1)
46
46
  builder (~> 3.1)
47
47
  erubi (~> 1.4)
48
48
  rails-dom-testing (~> 2.0)
49
49
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
50
- activejob (6.1.0)
51
- activesupport (= 6.1.0)
50
+ activejob (6.1.4.1)
51
+ activesupport (= 6.1.4.1)
52
52
  globalid (>= 0.3.6)
53
- activemodel (6.1.0)
54
- activesupport (= 6.1.0)
55
- activerecord (6.1.0)
56
- activemodel (= 6.1.0)
57
- activesupport (= 6.1.0)
58
- activestorage (6.1.0)
59
- actionpack (= 6.1.0)
60
- activejob (= 6.1.0)
61
- activerecord (= 6.1.0)
62
- activesupport (= 6.1.0)
63
- marcel (~> 0.3.1)
64
- mimemagic (~> 0.3.2)
65
- activesupport (6.1.0)
53
+ activemodel (6.1.4.1)
54
+ activesupport (= 6.1.4.1)
55
+ activerecord (6.1.4.1)
56
+ activemodel (= 6.1.4.1)
57
+ activesupport (= 6.1.4.1)
58
+ activestorage (6.1.4.1)
59
+ actionpack (= 6.1.4.1)
60
+ activejob (= 6.1.4.1)
61
+ activerecord (= 6.1.4.1)
62
+ activesupport (= 6.1.4.1)
63
+ marcel (~> 1.0.0)
64
+ mini_mime (>= 1.1.0)
65
+ activesupport (6.1.4.1)
66
66
  concurrent-ruby (~> 1.0, >= 1.0.2)
67
67
  i18n (>= 1.6, < 2)
68
68
  minitest (>= 5.1)
@@ -70,32 +70,34 @@ GEM
70
70
  zeitwerk (~> 2.3)
71
71
  ast (2.4.0)
72
72
  builder (3.2.4)
73
- cable_ready (4.4.5)
73
+ cable_ready (4.5.0)
74
74
  rails (>= 5.2)
75
+ thread-local (>= 1.1.0)
75
76
  coderay (1.1.2)
76
- concurrent-ruby (1.1.7)
77
+ concurrent-ruby (1.1.9)
77
78
  crass (1.0.6)
78
79
  erubi (1.10.0)
79
- globalid (0.4.2)
80
- activesupport (>= 4.2.0)
81
- i18n (1.8.5)
80
+ globalid (0.5.2)
81
+ activesupport (>= 5.0)
82
+ i18n (1.8.10)
82
83
  concurrent-ruby (~> 1.0)
83
84
  jaro_winkler (1.5.4)
84
- loofah (2.8.0)
85
+ loofah (2.12.0)
85
86
  crass (~> 1.0.2)
86
87
  nokogiri (>= 1.5.9)
87
88
  mail (2.7.1)
88
89
  mini_mime (>= 0.1.1)
89
- marcel (0.3.3)
90
- mimemagic (~> 0.3.2)
90
+ marcel (1.0.1)
91
91
  method_source (0.9.2)
92
- mimemagic (0.3.5)
93
- mini_mime (1.0.2)
94
- mini_portile2 (2.4.0)
95
- minitest (5.14.2)
96
- nio4r (2.5.4)
97
- nokogiri (1.10.10-x64-mingw32)
98
- mini_portile2 (~> 2.4.0)
92
+ mini_mime (1.1.1)
93
+ mini_portile2 (2.6.1)
94
+ minitest (5.14.4)
95
+ nio4r (2.5.8)
96
+ nokogiri (1.12.3)
97
+ mini_portile2 (~> 2.6.1)
98
+ racc (~> 1.4)
99
+ nokogiri (1.12.3-x64-mingw32)
100
+ racc (~> 1.4)
99
101
  parallel (1.19.1)
100
102
  parser (2.7.0.2)
101
103
  ast (~> 2.4.0)
@@ -104,34 +106,35 @@ GEM
104
106
  method_source (~> 0.9.0)
105
107
  pry-nav (0.3.0)
106
108
  pry (>= 0.9.10, < 0.13.0)
109
+ racc (1.5.2)
107
110
  rack (2.2.3)
108
111
  rack-test (1.1.0)
109
112
  rack (>= 1.0, < 3)
110
- rails (6.1.0)
111
- actioncable (= 6.1.0)
112
- actionmailbox (= 6.1.0)
113
- actionmailer (= 6.1.0)
114
- actionpack (= 6.1.0)
115
- actiontext (= 6.1.0)
116
- actionview (= 6.1.0)
117
- activejob (= 6.1.0)
118
- activemodel (= 6.1.0)
119
- activerecord (= 6.1.0)
120
- activestorage (= 6.1.0)
121
- activesupport (= 6.1.0)
113
+ rails (6.1.4.1)
114
+ actioncable (= 6.1.4.1)
115
+ actionmailbox (= 6.1.4.1)
116
+ actionmailer (= 6.1.4.1)
117
+ actionpack (= 6.1.4.1)
118
+ actiontext (= 6.1.4.1)
119
+ actionview (= 6.1.4.1)
120
+ activejob (= 6.1.4.1)
121
+ activemodel (= 6.1.4.1)
122
+ activerecord (= 6.1.4.1)
123
+ activestorage (= 6.1.4.1)
124
+ activesupport (= 6.1.4.1)
122
125
  bundler (>= 1.15.0)
123
- railties (= 6.1.0)
126
+ railties (= 6.1.4.1)
124
127
  sprockets-rails (>= 2.0.0)
125
128
  rails-dom-testing (2.0.3)
126
129
  activesupport (>= 4.2.0)
127
130
  nokogiri (>= 1.6)
128
- rails-html-sanitizer (1.3.0)
131
+ rails-html-sanitizer (1.4.2)
129
132
  loofah (~> 2.3)
130
- railties (6.1.0)
131
- actionpack (= 6.1.0)
132
- activesupport (= 6.1.0)
133
+ railties (6.1.4.1)
134
+ actionpack (= 6.1.4.1)
135
+ activesupport (= 6.1.4.1)
133
136
  method_source
134
- rake (>= 0.8.7)
137
+ rake (>= 0.13)
135
138
  thor (~> 1.0)
136
139
  rainbow (3.0.0)
137
140
  rake (13.0.1)
@@ -157,11 +160,12 @@ GEM
157
160
  rubocop-performance (~> 1.5.1)
158
161
  standardrb (1.0.0)
159
162
  standard
160
- thor (1.0.1)
163
+ thor (1.1.0)
164
+ thread-local (1.1.0)
161
165
  tzinfo (2.0.4)
162
166
  concurrent-ruby (~> 1.0)
163
167
  unicode-display_width (1.6.1)
164
- websocket-driver (0.7.3)
168
+ websocket-driver (0.7.5)
165
169
  websocket-extensions (>= 0.1.0)
166
170
  websocket-extensions (0.1.5)
167
171
  zeitwerk (2.4.2)
data/lib/optimism/rake.rb CHANGED
@@ -16,7 +16,7 @@ task :"optimism:install" do
16
16
  $stderr.puts "=> [ skipping ] #{channel[:app_path]} already exists"
17
17
  else
18
18
  FileUtils.cp(File.expand_path(channel[:template_path], __dir__), "./#{channel[:app_path]}")
19
- $stderr.puts "=> #{channel[:app_path]} created"
19
+ $stdout.puts "=> #{channel[:app_path]} created"
20
20
  end
21
21
  end
22
22
  end
@@ -1,3 +1,3 @@
1
1
  module Optimism
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/optimism.rb CHANGED
@@ -21,7 +21,7 @@ module Optimism
21
21
  yield self
22
22
  end
23
23
 
24
- def broadcast_errors(model, attributes)
24
+ def broadcast_errors(model, attributes, reverse_attributes_for: [])
25
25
  return unless model&.errors&.messages
26
26
  resource = ActiveModel::Naming.param_key(model)
27
27
  form_selector, submit_selector = Optimism.form_selector.sub("RESOURCE", resource), Optimism.submit_selector.sub("RESOURCE", resource)
@@ -36,7 +36,7 @@ module Optimism
36
36
  raise Exception.new "attributes must be a Hash (Parameters, Indifferent or standard), Array, Symbol or String"
37
37
  end
38
38
  model.valid? if model.errors.empty?
39
- process_resource(model, attributes, [resource])
39
+ process_resource(model, attributes, [resource], reverse_attributes_for: reverse_attributes_for)
40
40
  if model.errors.any?
41
41
  CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:form:invalid", detail: {resource: resource}) if Optimism.emit_events
42
42
  CableReady::Channels.instance[Optimism.channel_proc[self]].add_css_class(selector: form_selector, name: Optimism.form_class) if Optimism.form_class.present?
@@ -50,11 +50,12 @@ module Optimism
50
50
  head :ok if defined?(head)
51
51
  end
52
52
 
53
- def process_resource(model, attributes, ancestry)
53
+ def process_resource(model, attributes, ancestry, reverse_attributes_for: [])
54
54
  attributes.keys.each do |attribute|
55
55
  if attribute.ends_with?("_attributes")
56
56
  resource = attribute[0..-12]
57
57
  association = model.send(resource.to_sym)
58
+ association = association.reverse if reverse_attributes_for.include?(resource.to_sym)
58
59
  if association.respond_to? :each_with_index
59
60
  association.each_with_index do |nested, index|
60
61
  process_resource(nested, attributes[attribute][index.to_s], ancestry + [resource, index]) if attributes[attribute].key?(index.to_s)
@@ -76,15 +77,22 @@ module Optimism
76
77
  resource += "_#{ancestry.shift}_attributes_#{ancestry.shift}" until ancestry.empty?
77
78
  end
78
79
  container_selector, error_selector = Optimism.container_selector.sub("RESOURCE", resource).sub("ATTRIBUTE", attribute), Optimism.error_selector.sub("RESOURCE", resource).sub("ATTRIBUTE", attribute)
79
- if model.errors.any? && model.errors.messages.map(&:first).include?(attribute.to_sym)
80
- message = "#{model.errors.full_message(attribute.to_sym, model.errors.messages[attribute.to_sym].first)}#{Optimism.suffix}"
81
- CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:attribute:invalid", detail: {resource: resource, attribute: attribute, text: message}) if Optimism.emit_events
82
- CableReady::Channels.instance[Optimism.channel_proc[self]].add_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
83
- CableReady::Channels.instance[Optimism.channel_proc[self]].text_content(selector: error_selector, text: message) if Optimism.inject_inline
84
- else
85
- CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:attribute:valid", detail: {resource: resource, attribute: attribute}) if Optimism.emit_events
86
- CableReady::Channels.instance[Optimism.channel_proc[self]].remove_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
87
- CableReady::Channels.instance[Optimism.channel_proc[self]].text_content(selector: error_selector, text: "") if Optimism.inject_inline
80
+ if model.errors.any?
81
+ if attribute.ends_with?("_id") && model.errors.messages.include?(attribute.delete_suffix("_id").to_sym)
82
+ model.errors.messages[attribute.delete_suffix("_id").to_sym].each do |msg|
83
+ model.errors.add(attribute.to_sym, msg)
84
+ end
85
+ end
86
+ if model.errors.messages.map(&:first).include?(attribute.to_sym)
87
+ message = "#{model.errors.full_message(attribute.to_sym, model.errors.messages[attribute.to_sym].first)}#{Optimism.suffix}"
88
+ CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:attribute:invalid", detail: {resource: resource, attribute: attribute, text: message}) if Optimism.emit_events
89
+ CableReady::Channels.instance[Optimism.channel_proc[self]].add_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
90
+ CableReady::Channels.instance[Optimism.channel_proc[self]].text_content(selector: error_selector, text: message) if Optimism.inject_inline
91
+ else
92
+ CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:attribute:valid", detail: {resource: resource, attribute: attribute}) if Optimism.emit_events
93
+ CableReady::Channels.instance[Optimism.channel_proc[self]].remove_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
94
+ CableReady::Channels.instance[Optimism.channel_proc[self]].text_content(selector: error_selector, text: "") if Optimism.inject_inline
95
+ end
88
96
  end
89
97
  end
90
98
  end
data/typical-usage.md CHANGED
@@ -27,17 +27,17 @@ Now that you have seen what Optimism can do, let's flex our muscles a bit and se
27
27
  {% endcode %}
28
28
  {% endtab %}
29
29
 
30
- {% tab title="Bootstrap 4" %}
30
+ {% tab title="Bootstrap" %}
31
31
  {% code title="app/views/posts/\_form.html.erb" %}
32
32
  ```rust
33
33
  <%= form_with(model: post, id: "posts_form") do |form| %>
34
- <%= form.container_for :name, class: "form-group" do %>
34
+ <%= form.container_for :name, class: "input-group" do %>
35
35
  <%= form.label :name %>
36
36
  <%= form.text_field :name, class: "form-control" %>
37
37
  <%= form.error_for :name, class: "small align-bottom text-danger d-none" %>
38
38
  <% end %>
39
39
 
40
- <%= form.container_for :body, class: "form-group" do %>
40
+ <%= form.container_for :body, class: "input-group" do %>
41
41
  <%= form.label :body %>
42
42
  <%= form.text_area :body, class: "form-control" %>
43
43
  <%= form.error_for :body, class: "small align-bottom text-danger d-none" %>
@@ -76,14 +76,14 @@ Here we introduce the `container_for` helper, which wraps a form element in a `d
76
76
  ```
77
77
  {% endtab %}
78
78
 
79
- {% tab title="Bootstrap 4" %}
79
+ {% tab title="Bootstrap" %}
80
80
  ```css
81
- .form-group.error > .d-none {
81
+ .input-group.error > .d-none {
82
82
  display: inline !important;
83
83
  }
84
84
 
85
- .form-group.error > input,
86
- .form-group.error > textarea {
85
+ .input-group.error > input,
86
+ .input-group.error > textarea {
87
87
  background-color: rgba(255, 239, 213, 0.7);
88
88
  }
89
89
  ```
@@ -98,5 +98,15 @@ If you assign an id to the form itself that matches the expected format - in thi
98
98
  Unfortunately, we can't automatically generate the id for the form during its own declaration. Luckily, the format is pretty easy: **resources\_form**.
99
99
  {% endhint %}
100
100
 
101
+ ## Gotchas
102
+
103
+ Optimism is a fundamentally simple library, which means that inevitably, there's going to be scenarios that require some extra consideration.
104
+
105
+ #### Radio buttons and checkboxes
106
+
107
+ Thanks to a quirk of the way certain OG form input elements work, it's possible for an unchecked element to not be included in a form's parameters. For example, if you have a set of radio buttons with no default selection, your `params` hash will not include data for it.
108
+
109
+ Make sure to use the `checkbox` helpers that Rails provides, which implement a clever hack to make sure that unchecked checkboxes produce a `false` value in your `params`.
110
+
101
111
  ![](.gitbook/assets/web_developer.svg)
102
112
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optimism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - leastbad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -183,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
183
  - !ruby/object:Gem::Version
184
184
  version: '0'
185
185
  requirements: []
186
- rubygems_version: 3.1.4
186
+ rubygems_version: 3.1.6
187
187
  signing_key:
188
188
  specification_version: 4
189
189
  summary: Drop-in Rails form validations