optimism 0.3.5 → 0.5.0
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 +4 -4
- data/Gemfile.lock +93 -85
- data/README.md +4 -0
- data/lib/optimism/rake.rb +1 -1
- data/lib/optimism/version.rb +1 -1
- data/lib/optimism.rb +52 -41
- data/optimism.gemspec +2 -2
- data/reference.md +1 -1
- data/typical-usage.md +17 -7
- metadata +5 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9519a511dec44dd176cdd2f1f13ba50b31846cc9f9247088b821d3117728c052
|
|
4
|
+
data.tar.gz: 26acc98ea3fbd2fafec358ecd007b7258518b2cc75e4c387b16e7106771a2e91
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7294ff7de16b9119b348af7db1e29747747cc968546ea5610e2463cbe8f72804412a36b3f73a4eafc4c49d72f38d59b4765e0c0e824867f786e7886884615728
|
|
7
|
+
data.tar.gz: ac8eef02349c7cea595bfa4235609ebe4e33ff6e0fcc28599a887667cc9daee584a76ef38b02e59eac16caab629ffe1f2474945252af6f3679d723076835369d
|
data/Gemfile.lock
CHANGED
|
@@ -1,97 +1,103 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
optimism (0.3.
|
|
5
|
-
cable_ready (>= 4)
|
|
4
|
+
optimism (0.3.5)
|
|
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.
|
|
13
|
-
actionpack (= 6.
|
|
12
|
+
actioncable (6.1.4.1)
|
|
13
|
+
actionpack (= 6.1.4.1)
|
|
14
|
+
activesupport (= 6.1.4.1)
|
|
14
15
|
nio4r (~> 2.0)
|
|
15
16
|
websocket-driver (>= 0.6.1)
|
|
16
|
-
actionmailbox (6.
|
|
17
|
-
actionpack (= 6.
|
|
18
|
-
activejob (= 6.
|
|
19
|
-
activerecord (= 6.
|
|
20
|
-
activestorage (= 6.
|
|
21
|
-
activesupport (= 6.
|
|
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)
|
|
22
23
|
mail (>= 2.7.1)
|
|
23
|
-
actionmailer (6.
|
|
24
|
-
actionpack (= 6.
|
|
25
|
-
actionview (= 6.
|
|
26
|
-
activejob (= 6.
|
|
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)
|
|
27
29
|
mail (~> 2.5, >= 2.5.4)
|
|
28
30
|
rails-dom-testing (~> 2.0)
|
|
29
|
-
actionpack (6.
|
|
30
|
-
actionview (= 6.
|
|
31
|
-
activesupport (= 6.
|
|
32
|
-
rack (~> 2.0, >= 2.0.
|
|
31
|
+
actionpack (6.1.4.1)
|
|
32
|
+
actionview (= 6.1.4.1)
|
|
33
|
+
activesupport (= 6.1.4.1)
|
|
34
|
+
rack (~> 2.0, >= 2.0.9)
|
|
33
35
|
rack-test (>= 0.6.3)
|
|
34
36
|
rails-dom-testing (~> 2.0)
|
|
35
37
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
36
|
-
actiontext (6.
|
|
37
|
-
actionpack (= 6.
|
|
38
|
-
activerecord (= 6.
|
|
39
|
-
activestorage (= 6.
|
|
40
|
-
activesupport (= 6.
|
|
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)
|
|
41
43
|
nokogiri (>= 1.8.5)
|
|
42
|
-
actionview (6.
|
|
43
|
-
activesupport (= 6.
|
|
44
|
+
actionview (6.1.4.1)
|
|
45
|
+
activesupport (= 6.1.4.1)
|
|
44
46
|
builder (~> 3.1)
|
|
45
47
|
erubi (~> 1.4)
|
|
46
48
|
rails-dom-testing (~> 2.0)
|
|
47
49
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
48
|
-
activejob (6.
|
|
49
|
-
activesupport (= 6.
|
|
50
|
+
activejob (6.1.4.1)
|
|
51
|
+
activesupport (= 6.1.4.1)
|
|
50
52
|
globalid (>= 0.3.6)
|
|
51
|
-
activemodel (6.
|
|
52
|
-
activesupport (= 6.
|
|
53
|
-
activerecord (6.
|
|
54
|
-
activemodel (= 6.
|
|
55
|
-
activesupport (= 6.
|
|
56
|
-
activestorage (6.
|
|
57
|
-
actionpack (= 6.
|
|
58
|
-
activejob (= 6.
|
|
59
|
-
activerecord (= 6.
|
|
60
|
-
|
|
61
|
-
|
|
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)
|
|
62
66
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
63
|
-
i18n (>=
|
|
64
|
-
minitest (
|
|
65
|
-
tzinfo (~>
|
|
66
|
-
zeitwerk (~> 2.
|
|
67
|
+
i18n (>= 1.6, < 2)
|
|
68
|
+
minitest (>= 5.1)
|
|
69
|
+
tzinfo (~> 2.0)
|
|
70
|
+
zeitwerk (~> 2.3)
|
|
67
71
|
ast (2.4.0)
|
|
68
72
|
builder (3.2.4)
|
|
69
|
-
cable_ready (4.
|
|
73
|
+
cable_ready (4.5.0)
|
|
70
74
|
rails (>= 5.2)
|
|
75
|
+
thread-local (>= 1.1.0)
|
|
71
76
|
coderay (1.1.2)
|
|
72
|
-
concurrent-ruby (1.1.
|
|
77
|
+
concurrent-ruby (1.1.9)
|
|
73
78
|
crass (1.0.6)
|
|
74
|
-
erubi (1.
|
|
75
|
-
globalid (0.
|
|
76
|
-
activesupport (>=
|
|
77
|
-
i18n (1.8.
|
|
79
|
+
erubi (1.10.0)
|
|
80
|
+
globalid (0.5.2)
|
|
81
|
+
activesupport (>= 5.0)
|
|
82
|
+
i18n (1.8.10)
|
|
78
83
|
concurrent-ruby (~> 1.0)
|
|
79
84
|
jaro_winkler (1.5.4)
|
|
80
|
-
loofah (2.
|
|
85
|
+
loofah (2.12.0)
|
|
81
86
|
crass (~> 1.0.2)
|
|
82
87
|
nokogiri (>= 1.5.9)
|
|
83
88
|
mail (2.7.1)
|
|
84
89
|
mini_mime (>= 0.1.1)
|
|
85
|
-
marcel (0.
|
|
86
|
-
mimemagic (~> 0.3.2)
|
|
90
|
+
marcel (1.0.1)
|
|
87
91
|
method_source (0.9.2)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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)
|
|
95
101
|
parallel (1.19.1)
|
|
96
102
|
parser (2.7.0.2)
|
|
97
103
|
ast (~> 2.4.0)
|
|
@@ -100,35 +106,36 @@ GEM
|
|
|
100
106
|
method_source (~> 0.9.0)
|
|
101
107
|
pry-nav (0.3.0)
|
|
102
108
|
pry (>= 0.9.10, < 0.13.0)
|
|
109
|
+
racc (1.5.2)
|
|
103
110
|
rack (2.2.3)
|
|
104
111
|
rack-test (1.1.0)
|
|
105
112
|
rack (>= 1.0, < 3)
|
|
106
|
-
rails (6.
|
|
107
|
-
actioncable (= 6.
|
|
108
|
-
actionmailbox (= 6.
|
|
109
|
-
actionmailer (= 6.
|
|
110
|
-
actionpack (= 6.
|
|
111
|
-
actiontext (= 6.
|
|
112
|
-
actionview (= 6.
|
|
113
|
-
activejob (= 6.
|
|
114
|
-
activemodel (= 6.
|
|
115
|
-
activerecord (= 6.
|
|
116
|
-
activestorage (= 6.
|
|
117
|
-
activesupport (= 6.
|
|
118
|
-
bundler (>= 1.
|
|
119
|
-
railties (= 6.
|
|
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)
|
|
125
|
+
bundler (>= 1.15.0)
|
|
126
|
+
railties (= 6.1.4.1)
|
|
120
127
|
sprockets-rails (>= 2.0.0)
|
|
121
128
|
rails-dom-testing (2.0.3)
|
|
122
129
|
activesupport (>= 4.2.0)
|
|
123
130
|
nokogiri (>= 1.6)
|
|
124
|
-
rails-html-sanitizer (1.
|
|
131
|
+
rails-html-sanitizer (1.4.2)
|
|
125
132
|
loofah (~> 2.3)
|
|
126
|
-
railties (6.
|
|
127
|
-
actionpack (= 6.
|
|
128
|
-
activesupport (= 6.
|
|
133
|
+
railties (6.1.4.1)
|
|
134
|
+
actionpack (= 6.1.4.1)
|
|
135
|
+
activesupport (= 6.1.4.1)
|
|
129
136
|
method_source
|
|
130
|
-
rake (>= 0.
|
|
131
|
-
thor (
|
|
137
|
+
rake (>= 0.13)
|
|
138
|
+
thor (~> 1.0)
|
|
132
139
|
rainbow (3.0.0)
|
|
133
140
|
rake (13.0.1)
|
|
134
141
|
rubocop (0.79.0)
|
|
@@ -144,7 +151,7 @@ GEM
|
|
|
144
151
|
sprockets (4.0.2)
|
|
145
152
|
concurrent-ruby (~> 1.0)
|
|
146
153
|
rack (> 1, < 3)
|
|
147
|
-
sprockets-rails (3.2.
|
|
154
|
+
sprockets-rails (3.2.2)
|
|
148
155
|
actionpack (>= 4.0)
|
|
149
156
|
activesupport (>= 4.0)
|
|
150
157
|
sprockets (>= 3.0.0)
|
|
@@ -153,18 +160,19 @@ GEM
|
|
|
153
160
|
rubocop-performance (~> 1.5.1)
|
|
154
161
|
standardrb (1.0.0)
|
|
155
162
|
standard
|
|
156
|
-
thor (1.0
|
|
157
|
-
|
|
158
|
-
tzinfo (
|
|
159
|
-
|
|
163
|
+
thor (1.1.0)
|
|
164
|
+
thread-local (1.1.0)
|
|
165
|
+
tzinfo (2.0.4)
|
|
166
|
+
concurrent-ruby (~> 1.0)
|
|
160
167
|
unicode-display_width (1.6.1)
|
|
161
|
-
websocket-driver (0.7.
|
|
168
|
+
websocket-driver (0.7.5)
|
|
162
169
|
websocket-extensions (>= 0.1.0)
|
|
163
170
|
websocket-extensions (0.1.5)
|
|
164
|
-
zeitwerk (2.
|
|
171
|
+
zeitwerk (2.4.2)
|
|
165
172
|
|
|
166
173
|
PLATFORMS
|
|
167
174
|
ruby
|
|
175
|
+
x64-mingw32
|
|
168
176
|
|
|
169
177
|
DEPENDENCIES
|
|
170
178
|
bundler (~> 2.0)
|
data/README.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
The missing drop-in solution for realtime remote form validation in Rails.
|
|
6
6
|
|
|
7
|
+
{% hint style="success" %}
|
|
8
|
+
Optimism v0.4.1 now supports Ruby 3.0.0, thanks to [Julian Rubisch](https://twitter.com/julian_rubisch) and Rails 6.1, thanks to [Josh LeBlanc](https://github.com/joshleblanc). 🎉
|
|
9
|
+
{% endhint %}
|
|
10
|
+
|
|
7
11
|
## Why have optimism?
|
|
8
12
|
|
|
9
13
|
[Optimism](https://github.com/leastbad/optimism) is an MIT-licensed [Ruby on Rails](https://rubyonrails.org/) gem that makes it easy to give your users instant constructive feedback if they enter invalid data into your application. Instead of dumping a list of errors at the top of your interface, Optimism provides specific instructions directly beside or below individual input elements.
|
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
|
-
$
|
|
19
|
+
$stdout.puts "=> #{channel[:app_path]} created"
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
data/lib/optimism/version.rb
CHANGED
data/lib/optimism.rb
CHANGED
|
@@ -3,28 +3,25 @@ require "optimism/version"
|
|
|
3
3
|
require "optimism/railtie" if defined?(Rails)
|
|
4
4
|
|
|
5
5
|
module Optimism
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
self.form_selector = "#RESOURCE_form"
|
|
20
|
-
self.submit_selector = "#RESOURCE_submit"
|
|
21
|
-
end
|
|
6
|
+
mattr_accessor :channel_proc, :form_class, :error_class, :disable_submit, :suffix, :emit_events, :add_css, :inject_inline, :container_selector, :error_selector, :form_selector, :submit_selector
|
|
7
|
+
self.channel_proc = ->(context) { "OptimismChannel" }
|
|
8
|
+
self.form_class = "invalid"
|
|
9
|
+
self.error_class = "error"
|
|
10
|
+
self.disable_submit = false
|
|
11
|
+
self.suffix = ""
|
|
12
|
+
self.emit_events = false
|
|
13
|
+
self.add_css = true
|
|
14
|
+
self.inject_inline = true
|
|
15
|
+
self.container_selector = "#RESOURCE_ATTRIBUTE_container"
|
|
16
|
+
self.error_selector = "#RESOURCE_ATTRIBUTE_error"
|
|
17
|
+
self.form_selector = "#RESOURCE_form"
|
|
18
|
+
self.submit_selector = "#RESOURCE_submit"
|
|
22
19
|
|
|
23
20
|
def self.configure(&block)
|
|
24
21
|
yield self
|
|
25
22
|
end
|
|
26
23
|
|
|
27
|
-
def broadcast_errors(model, attributes)
|
|
24
|
+
def broadcast_errors(model, attributes, reverse_attributes_for: [])
|
|
28
25
|
return unless model&.errors&.messages
|
|
29
26
|
resource = ActiveModel::Naming.param_key(model)
|
|
30
27
|
form_selector, submit_selector = Optimism.form_selector.sub("RESOURCE", resource), Optimism.submit_selector.sub("RESOURCE", resource)
|
|
@@ -39,25 +36,26 @@ module Optimism
|
|
|
39
36
|
raise Exception.new "attributes must be a Hash (Parameters, Indifferent or standard), Array, Symbol or String"
|
|
40
37
|
end
|
|
41
38
|
model.valid? if model.errors.empty?
|
|
42
|
-
process_resource(model, attributes, [resource])
|
|
39
|
+
process_resource(model, attributes, [resource], reverse_attributes_for: reverse_attributes_for)
|
|
43
40
|
if model.errors.any?
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:form:invalid", detail: {resource: resource}) if Optimism.emit_events
|
|
42
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].add_css_class(selector: form_selector, name: Optimism.form_class) if Optimism.form_class.present?
|
|
43
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].set_attribute(selector: submit_selector, name: "disabled") if Optimism.disable_submit
|
|
47
44
|
else
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].dispatch_event(name: "optimism:form:valid", detail: {resource: resource}) if Optimism.emit_events
|
|
46
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].remove_css_class(selector: form_selector, name: Optimism.form_class) if Optimism.form_class.present?
|
|
47
|
+
CableReady::Channels.instance[Optimism.channel_proc[self]].remove_attribute(selector: submit_selector, name: "disabled") if Optimism.disable_submit
|
|
51
48
|
end
|
|
52
|
-
|
|
49
|
+
CableReady::Channels.instance.broadcast
|
|
53
50
|
head :ok if defined?(head)
|
|
54
51
|
end
|
|
55
52
|
|
|
56
|
-
def process_resource(model, attributes, ancestry)
|
|
53
|
+
def process_resource(model, attributes, ancestry, reverse_attributes_for: [])
|
|
57
54
|
attributes.keys.each do |attribute|
|
|
58
55
|
if attribute.ends_with?("_attributes")
|
|
59
56
|
resource = attribute[0..-12]
|
|
60
57
|
association = model.send(resource.to_sym)
|
|
58
|
+
association = association.reverse if reverse_attributes_for.include?(resource.to_sym)
|
|
61
59
|
if association.respond_to? :each_with_index
|
|
62
60
|
association.each_with_index do |nested, index|
|
|
63
61
|
process_resource(nested, attributes[attribute][index.to_s], ancestry + [resource, index]) if attributes[attribute].key?(index.to_s)
|
|
@@ -79,23 +77,40 @@ module Optimism
|
|
|
79
77
|
resource += "_#{ancestry.shift}_attributes_#{ancestry.shift}" until ancestry.empty?
|
|
80
78
|
end
|
|
81
79
|
container_selector, error_selector = Optimism.container_selector.sub("RESOURCE", resource).sub("ATTRIBUTE", attribute), Optimism.error_selector.sub("RESOURCE", resource).sub("ATTRIBUTE", attribute)
|
|
82
|
-
if model.errors.any?
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
91
96
|
end
|
|
92
97
|
end
|
|
93
98
|
end
|
|
94
99
|
|
|
95
100
|
module ActionView::Helpers
|
|
101
|
+
module FormHelper
|
|
102
|
+
def error_for(object_name, attribute, **options)
|
|
103
|
+
tag.span **options.merge(id: error_id_for(object_name, attribute))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def error_id_for(object_name, attribute)
|
|
107
|
+
Optimism.error_selector.sub("RESOURCE", object_name.to_s.delete("]").tr("[", "_")).sub("ATTRIBUTE", attribute.to_s)[1..-1]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
96
111
|
class FormBuilder
|
|
97
112
|
def container_for(attribute, **options, &block)
|
|
98
|
-
@template.tag.div @template.capture(&block), options.merge
|
|
113
|
+
@template.tag.div @template.capture(&block), **options.merge(id: container_id_for(attribute)) if block_given?
|
|
99
114
|
end
|
|
100
115
|
|
|
101
116
|
def container_id_for(attribute)
|
|
@@ -103,11 +118,7 @@ module ActionView::Helpers
|
|
|
103
118
|
end
|
|
104
119
|
|
|
105
120
|
def error_for(attribute, **options)
|
|
106
|
-
@template.
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def error_id_for(attribute)
|
|
110
|
-
Optimism.error_selector.sub("RESOURCE", object_name.to_s.delete("]").tr("[", "_")).sub("ATTRIBUTE", attribute.to_s)[1..-1]
|
|
121
|
+
@template.error_for(object_name, attribute, **options)
|
|
111
122
|
end
|
|
112
123
|
end
|
|
113
124
|
end
|
data/optimism.gemspec
CHANGED
|
@@ -26,6 +26,6 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
spec.add_development_dependency "pry-nav", "~> 0.3.0"
|
|
27
27
|
spec.add_development_dependency "standardrb", "~> 1.0.0"
|
|
28
28
|
spec.add_dependency "rack", "~> 2.0"
|
|
29
|
-
spec.add_dependency "rails", [">= 5.2"
|
|
30
|
-
spec.add_dependency "cable_ready", ">= 4"
|
|
29
|
+
spec.add_dependency "rails", [">= 5.2"]
|
|
30
|
+
spec.add_dependency "cable_ready", ">= 4.4.6"
|
|
31
31
|
end
|
data/reference.md
CHANGED
|
@@ -93,7 +93,7 @@ Optimism is configurable via an optional initializer file. As with all initializ
|
|
|
93
93
|
{% code title="config/initializers/optimism.rb" %}
|
|
94
94
|
```ruby
|
|
95
95
|
Optimism.configure do |config|
|
|
96
|
-
config.
|
|
96
|
+
config.channel_proc = ->(context) { "OptimismChannel" }
|
|
97
97
|
config.form_class = "invalid"
|
|
98
98
|
config.error_class = "error"
|
|
99
99
|
config.disable_submit = false
|
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
|
|
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: "
|
|
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: "
|
|
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
|
|
79
|
+
{% tab title="Bootstrap" %}
|
|
80
80
|
```css
|
|
81
|
-
.
|
|
81
|
+
.input-group.error > .d-none {
|
|
82
82
|
display: inline !important;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
.
|
|
86
|
-
.
|
|
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
|

|
|
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
|
+
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:
|
|
11
|
+
date: 2021-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -101,9 +101,6 @@ dependencies:
|
|
|
101
101
|
- - ">="
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
103
|
version: '5.2'
|
|
104
|
-
- - ">="
|
|
105
|
-
- !ruby/object:Gem::Version
|
|
106
|
-
version: '6'
|
|
107
104
|
type: :runtime
|
|
108
105
|
prerelease: false
|
|
109
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -111,23 +108,20 @@ dependencies:
|
|
|
111
108
|
- - ">="
|
|
112
109
|
- !ruby/object:Gem::Version
|
|
113
110
|
version: '5.2'
|
|
114
|
-
- - ">="
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: '6'
|
|
117
111
|
- !ruby/object:Gem::Dependency
|
|
118
112
|
name: cable_ready
|
|
119
113
|
requirement: !ruby/object:Gem::Requirement
|
|
120
114
|
requirements:
|
|
121
115
|
- - ">="
|
|
122
116
|
- !ruby/object:Gem::Version
|
|
123
|
-
version:
|
|
117
|
+
version: 4.4.6
|
|
124
118
|
type: :runtime
|
|
125
119
|
prerelease: false
|
|
126
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
127
121
|
requirements:
|
|
128
122
|
- - ">="
|
|
129
123
|
- !ruby/object:Gem::Version
|
|
130
|
-
version:
|
|
124
|
+
version: 4.4.6
|
|
131
125
|
description: Realtime remote form input validations delivered via websockets
|
|
132
126
|
email:
|
|
133
127
|
- hello@leastbad.com
|
|
@@ -189,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
189
183
|
- !ruby/object:Gem::Version
|
|
190
184
|
version: '0'
|
|
191
185
|
requirements: []
|
|
192
|
-
rubygems_version: 3.
|
|
186
|
+
rubygems_version: 3.1.6
|
|
193
187
|
signing_key:
|
|
194
188
|
specification_version: 4
|
|
195
189
|
summary: Drop-in Rails form validations
|