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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4243758152d4a7299eecfe0104b01187a272be5f1da3873b618441b532289f01
4
- data.tar.gz: fcdf8b15dacfa3e211e0f3ffd2bba7ba0dd9f095a93152315795bba37430e896
3
+ metadata.gz: 9519a511dec44dd176cdd2f1f13ba50b31846cc9f9247088b821d3117728c052
4
+ data.tar.gz: 26acc98ea3fbd2fafec358ecd007b7258518b2cc75e4c387b16e7106771a2e91
5
5
  SHA512:
6
- metadata.gz: 0ae487f731194a11c364aea1fc5baefbdef1496dc536c5d3723be3d304d73a4fab36d6179ff2b86ddc5949a39129fe1a1edb284742ae88d7f68c7b99f78f1398
7
- data.tar.gz: ae7cb3a35fcbe92e3a03ce5698c7dc0e8029b2bbd80ec038762066295803f64692196a04505b5ce5851ed012734e48f56b5685ed79dc537fa535423213a40733
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.1)
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.0.3.2)
13
- actionpack (= 6.0.3.2)
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.0.3.2)
17
- actionpack (= 6.0.3.2)
18
- activejob (= 6.0.3.2)
19
- activerecord (= 6.0.3.2)
20
- activestorage (= 6.0.3.2)
21
- activesupport (= 6.0.3.2)
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.0.3.2)
24
- actionpack (= 6.0.3.2)
25
- actionview (= 6.0.3.2)
26
- activejob (= 6.0.3.2)
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.0.3.2)
30
- actionview (= 6.0.3.2)
31
- activesupport (= 6.0.3.2)
32
- rack (~> 2.0, >= 2.0.8)
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.0.3.2)
37
- actionpack (= 6.0.3.2)
38
- activerecord (= 6.0.3.2)
39
- activestorage (= 6.0.3.2)
40
- activesupport (= 6.0.3.2)
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.0.3.2)
43
- activesupport (= 6.0.3.2)
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.0.3.2)
49
- activesupport (= 6.0.3.2)
50
+ activejob (6.1.4.1)
51
+ activesupport (= 6.1.4.1)
50
52
  globalid (>= 0.3.6)
51
- activemodel (6.0.3.2)
52
- activesupport (= 6.0.3.2)
53
- activerecord (6.0.3.2)
54
- activemodel (= 6.0.3.2)
55
- activesupport (= 6.0.3.2)
56
- activestorage (6.0.3.2)
57
- actionpack (= 6.0.3.2)
58
- activejob (= 6.0.3.2)
59
- activerecord (= 6.0.3.2)
60
- marcel (~> 0.3.1)
61
- activesupport (6.0.3.2)
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 (>= 0.7, < 2)
64
- minitest (~> 5.1)
65
- tzinfo (~> 1.1)
66
- zeitwerk (~> 2.2, >= 2.2.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.1.2)
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.6)
77
+ concurrent-ruby (1.1.9)
73
78
  crass (1.0.6)
74
- erubi (1.9.0)
75
- globalid (0.4.2)
76
- activesupport (>= 4.2.0)
77
- i18n (1.8.3)
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.6.0)
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.3.3)
86
- mimemagic (~> 0.3.2)
90
+ marcel (1.0.1)
87
91
  method_source (0.9.2)
88
- mimemagic (0.3.5)
89
- mini_mime (1.0.2)
90
- mini_portile2 (2.4.0)
91
- minitest (5.14.1)
92
- nio4r (2.5.2)
93
- nokogiri (1.10.9)
94
- 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)
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.0.3.2)
107
- actioncable (= 6.0.3.2)
108
- actionmailbox (= 6.0.3.2)
109
- actionmailer (= 6.0.3.2)
110
- actionpack (= 6.0.3.2)
111
- actiontext (= 6.0.3.2)
112
- actionview (= 6.0.3.2)
113
- activejob (= 6.0.3.2)
114
- activemodel (= 6.0.3.2)
115
- activerecord (= 6.0.3.2)
116
- activestorage (= 6.0.3.2)
117
- activesupport (= 6.0.3.2)
118
- bundler (>= 1.3.0)
119
- railties (= 6.0.3.2)
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.3.0)
131
+ rails-html-sanitizer (1.4.2)
125
132
  loofah (~> 2.3)
126
- railties (6.0.3.2)
127
- actionpack (= 6.0.3.2)
128
- activesupport (= 6.0.3.2)
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.8.7)
131
- thor (>= 0.20.3, < 2.0)
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.1)
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.1)
157
- thread_safe (0.3.6)
158
- tzinfo (1.2.7)
159
- thread_safe (~> 0.1)
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.2)
168
+ websocket-driver (0.7.5)
162
169
  websocket-extensions (>= 0.1.0)
163
170
  websocket-extensions (0.1.5)
164
- zeitwerk (2.3.0)
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
- $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.3.5"
2
+ VERSION = "0.5.0"
3
3
  end
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
- include CableReady::Broadcaster
7
- class << self
8
- mattr_accessor :channel, :form_class, :error_class, :disable_submit, :suffix, :emit_events, :add_css, :inject_inline, :container_selector, :error_selector, :form_selector, :submit_selector
9
- self.channel = ->(context) { "OptimismChannel" }
10
- self.form_class = "invalid"
11
- self.error_class = "error"
12
- self.disable_submit = false
13
- self.suffix = ""
14
- self.emit_events = false
15
- self.add_css = true
16
- self.inject_inline = true
17
- self.container_selector = "#RESOURCE_ATTRIBUTE_container"
18
- self.error_selector = "#RESOURCE_ATTRIBUTE_error"
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
- cable_ready[Optimism.channel[self]].dispatch_event(name: "optimism:form:invalid", detail: {resource: resource}) if Optimism.emit_events
45
- cable_ready[Optimism.channel[self]].add_css_class(selector: form_selector, name: Optimism.form_class) if Optimism.form_class.present?
46
- cable_ready[Optimism.channel[self]].set_attribute(selector: submit_selector, name: "disabled") if Optimism.disable_submit
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
- cable_ready[Optimism.channel[self]].dispatch_event(name: "optimism:form:valid", detail: {resource: resource}) if Optimism.emit_events
49
- cable_ready[Optimism.channel[self]].remove_css_class(selector: form_selector, name: Optimism.form_class) if Optimism.form_class.present?
50
- cable_ready[Optimism.channel[self]].remove_attribute(selector: submit_selector, name: "disabled") if Optimism.disable_submit
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
- cable_ready.broadcast
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? && model.errors.messages.map(&:first).include?(attribute.to_sym)
83
- message = "#{model.errors.full_message(attribute.to_sym, model.errors.messages[attribute.to_sym].first)}#{Optimism.suffix}"
84
- cable_ready[Optimism.channel[self]].dispatch_event(name: "optimism:attribute:invalid", detail: {resource: resource, attribute: attribute, text: message}) if Optimism.emit_events
85
- cable_ready[Optimism.channel[self]].add_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
86
- cable_ready[Optimism.channel[self]].text_content(selector: error_selector, text: message) if Optimism.inject_inline
87
- else
88
- cable_ready[Optimism.channel[self]].dispatch_event(name: "optimism:attribute:valid", detail: {resource: resource, attribute: attribute}) if Optimism.emit_events
89
- cable_ready[Optimism.channel[self]].remove_css_class(selector: container_selector, name: Optimism.error_class) if Optimism.add_css
90
- cable_ready[Optimism.channel[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
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!(id: container_id_for(attribute)) if block_given?
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.tag.span options.merge! id: error_id_for(attribute)
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", ">= 6"]
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.channel = ->(context) { "OptimismChannel" }
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 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.3.5
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: 2020-07-22 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
@@ -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: '4'
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: '4'
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.0.6
186
+ rubygems_version: 3.1.6
193
187
  signing_key:
194
188
  specification_version: 4
195
189
  summary: Drop-in Rails form validations