foundation_rails_helper 2.0.0 → 3.0.0.beta3
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/.rubocop.yml +3 -6
- data/.rubocop_todo.yml +6 -48
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/README.md +23 -26
- data/Rakefile +1 -0
- data/foundation_rails_helper.gemspec +36 -32
- data/lib/foundation_rails_helper.rb +2 -0
- data/lib/foundation_rails_helper/action_view_extension.rb +1 -0
- data/lib/foundation_rails_helper/configuration.rb +4 -1
- data/lib/foundation_rails_helper/flash_helper.rb +43 -16
- data/lib/foundation_rails_helper/form_builder.rb +61 -83
- data/lib/foundation_rails_helper/size_class_calculator.rb +32 -0
- data/lib/foundation_rails_helper/version.rb +2 -1
- data/lib/railtie.rb +1 -0
- data/spec/.rubocop.yml +3 -0
- data/spec/foundation_rails_helper/configuration_spec.rb +30 -3
- data/spec/foundation_rails_helper/flash_helper_spec.rb +37 -23
- data/spec/foundation_rails_helper/form_builder_spec.rb +448 -176
- data/spec/spec_helper.rb +1 -0
- data/spec/support/classes/author.rb +13 -0
- data/spec/support/classes/book.rb +13 -0
- data/spec/support/classes/genre.rb +13 -0
- data/spec/support/mock_rails.rb +56 -100
- metadata +50 -20
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'action_view/helpers'
|
2
3
|
|
3
4
|
module FoundationRailsHelper
|
4
5
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
5
6
|
include ActionView::Helpers::TagHelper
|
7
|
+
include ActionView::Helpers::OutputSafetyHelper
|
6
8
|
%w(file_field email_field text_field text_area telephone_field phone_field
|
7
9
|
url_field number_field date_field datetime_field datetime_local_field
|
8
10
|
month_field week_field time_field range_field search_field color_field)
|
@@ -17,21 +19,23 @@ module FoundationRailsHelper
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def label(attribute, text = nil, options = {})
|
20
|
-
if
|
22
|
+
if error?(attribute)
|
21
23
|
options[:class] ||= ''
|
22
|
-
options[:class] += '
|
24
|
+
options[:class] += ' is-invalid-label'
|
23
25
|
end
|
24
26
|
|
25
27
|
super(attribute, (text || '').html_safe, options)
|
26
28
|
end
|
27
29
|
|
30
|
+
# rubocop:disable LineLength
|
28
31
|
def check_box(attribute, options = {}, checked_value = '1', unchecked_value = '0')
|
29
32
|
custom_label(attribute, options[:label], options[:label_options]) do
|
30
33
|
options.delete(:label)
|
31
34
|
options.delete(:label_options)
|
32
35
|
super(attribute, options, checked_value, unchecked_value)
|
33
|
-
end +
|
36
|
+
end + error_and_help_text(attribute, options)
|
34
37
|
end
|
38
|
+
# rubocop:enable LineLength
|
35
39
|
|
36
40
|
def radio_button(attribute, tag_value, options = {})
|
37
41
|
options[:label_options] ||= {}
|
@@ -62,12 +66,14 @@ module FoundationRailsHelper
|
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
69
|
+
# rubocop:disable LineLength
|
65
70
|
def time_zone_select(attribute, priorities = nil, options = {}, html_options = {})
|
66
71
|
field attribute, options, html_options do |html_opts|
|
67
72
|
super(attribute, priorities, options,
|
68
73
|
html_opts.merge(autocomplete: :off))
|
69
74
|
end
|
70
75
|
end
|
76
|
+
# rubocop:enable LineLength
|
71
77
|
|
72
78
|
def select(attribute, choices, options = {}, html_options = {})
|
73
79
|
field attribute, options, html_options do |html_opts|
|
@@ -76,6 +82,7 @@ module FoundationRailsHelper
|
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
85
|
+
# rubocop:disable LineLength, ParameterLists
|
79
86
|
def collection_select(attribute, collection, value_method, text_method, options = {}, html_options = {})
|
80
87
|
field attribute, options, html_options do |html_opts|
|
81
88
|
html_options[:autocomplete] ||= :off
|
@@ -91,6 +98,7 @@ module FoundationRailsHelper
|
|
91
98
|
option_key_method, option_value_method, options, html_opts)
|
92
99
|
end
|
93
100
|
end
|
101
|
+
# rubocop:enable LineLength, ParameterLists
|
94
102
|
|
95
103
|
def autocomplete(attribute, url, options = {})
|
96
104
|
field attribute, options do |opts|
|
@@ -105,71 +113,43 @@ module FoundationRailsHelper
|
|
105
113
|
super(value, options)
|
106
114
|
end
|
107
115
|
|
108
|
-
private
|
109
|
-
|
110
|
-
def has_error?(attribute)
|
111
|
-
object.respond_to?(:errors) && !object.errors[attribute].blank?
|
112
|
-
end
|
113
|
-
|
114
116
|
def error_for(attribute, options = {})
|
115
|
-
|
116
|
-
class_name += " #{options[:class]}" if options[:class]
|
117
|
+
return unless error?(attribute)
|
117
118
|
|
118
|
-
|
119
|
+
class_name = 'form-error is-visible'
|
120
|
+
class_name += " #{options[:class]}" if options[:class]
|
119
121
|
|
120
122
|
error_messages = object.errors[attribute].join(', ')
|
121
123
|
error_messages = error_messages.html_safe if options[:html_safe_errors]
|
122
|
-
content_tag(:small, error_messages,
|
124
|
+
content_tag(:small, error_messages,
|
125
|
+
class: class_name.sub('is-invalid-input', ''))
|
123
126
|
end
|
124
127
|
|
125
|
-
|
126
|
-
return block_given? ? yield.html_safe : ''.html_safe if text == false
|
127
|
-
if text.nil? || text == true
|
128
|
-
text =
|
129
|
-
if object.class.respond_to?(:human_attribute_name)
|
130
|
-
object.class.human_attribute_name(attribute)
|
131
|
-
else
|
132
|
-
attribute.to_s.humanize
|
133
|
-
end
|
134
|
-
end
|
135
|
-
text = yield.html_safe + " #{text}" if block_given?
|
136
|
-
options ||= {}
|
137
|
-
label(attribute, text, options)
|
138
|
-
end
|
128
|
+
private
|
139
129
|
|
140
|
-
def
|
141
|
-
|
142
|
-
classes + ' columns'
|
130
|
+
def error?(attribute)
|
131
|
+
object.respond_to?(:errors) && !object.errors[attribute].blank?
|
143
132
|
end
|
144
133
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
@medium = size_options[:medium]
|
149
|
-
@large = size_options[:large]
|
134
|
+
def default_label_text(object, attribute)
|
135
|
+
if object.class.respond_to?(:human_attribute_name)
|
136
|
+
return object.class.human_attribute_name(attribute)
|
150
137
|
end
|
151
138
|
|
152
|
-
|
153
|
-
|
154
|
-
end
|
155
|
-
|
156
|
-
private
|
157
|
-
|
158
|
-
def small_class
|
159
|
-
"small-#{@small}" if valid_size(@small)
|
160
|
-
end
|
139
|
+
attribute.to_s.humanize
|
140
|
+
end
|
161
141
|
|
162
|
-
|
163
|
-
|
164
|
-
end
|
142
|
+
def custom_label(attribute, text, options)
|
143
|
+
return block_given? ? yield.html_safe : ''.html_safe if text == false
|
165
144
|
|
166
|
-
|
167
|
-
|
168
|
-
|
145
|
+
text = default_label_text(object, attribute) if text.nil? || text == true
|
146
|
+
text = safe_join([yield, text.html_safe]) if block_given?
|
147
|
+
label(attribute, text, options || {})
|
148
|
+
end
|
169
149
|
|
170
|
-
|
171
|
-
|
172
|
-
|
150
|
+
def column_classes(options)
|
151
|
+
classes = SizeClassCalculator.new(options).classes
|
152
|
+
classes + ' columns'
|
173
153
|
end
|
174
154
|
|
175
155
|
def tag_from_options(name, options)
|
@@ -181,7 +161,7 @@ module FoundationRailsHelper
|
|
181
161
|
end
|
182
162
|
|
183
163
|
def decrement_input_size(input, column, options)
|
184
|
-
return unless options.key?(column)
|
164
|
+
return unless options.present? && options.key?(column)
|
185
165
|
|
186
166
|
input.send("#{column}=",
|
187
167
|
(input.send(column) - options.fetch(column).to_i))
|
@@ -191,15 +171,9 @@ module FoundationRailsHelper
|
|
191
171
|
def calculate_input_size(prefix_options, postfix_options)
|
192
172
|
input_size =
|
193
173
|
OpenStruct.new(changed?: false, small: 12, medium: 12, large: 12)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
end
|
198
|
-
end
|
199
|
-
if postfix_options.present?
|
200
|
-
%w(small medium large).each do |size|
|
201
|
-
decrement_input_size(input_size, size.to_sym, postfix_options)
|
202
|
-
end
|
174
|
+
%w(small medium large).each do |size|
|
175
|
+
decrement_input_size(input_size, size.to_sym, prefix_options)
|
176
|
+
decrement_input_size(input_size, size.to_sym, postfix_options)
|
203
177
|
end
|
204
178
|
|
205
179
|
input_size
|
@@ -213,45 +187,49 @@ module FoundationRailsHelper
|
|
213
187
|
klass = column_classes(input_size.marshal_dump).to_s
|
214
188
|
input = content_tag(:div, block, class: klass)
|
215
189
|
|
216
|
-
|
217
|
-
|
218
|
-
content_tag(:div, prefix + input + postfix, class: 'row collapse')
|
219
|
-
else
|
220
|
-
block
|
221
|
-
end
|
222
|
-
|
223
|
-
html.html_safe
|
190
|
+
return block unless input_size.changed?
|
191
|
+
content_tag(:div, prefix + input + postfix, class: 'row collapse')
|
224
192
|
end
|
225
193
|
|
226
|
-
def
|
194
|
+
def error_and_help_text(attribute, options = {})
|
227
195
|
html = ''
|
228
|
-
|
196
|
+
if options[:help_text]
|
197
|
+
html += content_tag(:p, options[:help_text], class: 'help-text')
|
198
|
+
end
|
229
199
|
html += error_for(attribute, options) || ''
|
230
200
|
html.html_safe
|
231
201
|
end
|
232
202
|
|
203
|
+
def field_label(attribute, options)
|
204
|
+
return ''.html_safe unless auto_labels || options[:label]
|
205
|
+
custom_label(attribute, options[:label], options[:label_options])
|
206
|
+
end
|
207
|
+
|
233
208
|
def field(attribute, options, html_options = nil)
|
234
|
-
|
235
|
-
html = if auto_labels || options[:label]
|
236
|
-
custom_label(attribute, options[:label], options[:label_options])
|
237
|
-
else
|
238
|
-
''.html_safe
|
239
|
-
end
|
209
|
+
html = field_label(attribute, options)
|
240
210
|
class_options = html_options || options
|
241
211
|
|
242
|
-
if
|
212
|
+
if error?(attribute)
|
243
213
|
class_options[:class] = class_options[:class].to_s
|
244
|
-
class_options[:class] += '
|
214
|
+
class_options[:class] += ' is-invalid-input'
|
245
215
|
end
|
246
216
|
|
247
217
|
options.delete(:label)
|
248
218
|
options.delete(:label_options)
|
249
|
-
|
219
|
+
help_text = options.delete(:help_text)
|
250
220
|
prefix = options.delete(:prefix)
|
251
221
|
postfix = options.delete(:postfix)
|
252
222
|
|
253
223
|
html += wrap_prefix_and_postfix(yield(class_options), prefix, postfix)
|
254
|
-
html +
|
224
|
+
html + error_and_help_text(attribute, options.merge(help_text: help_text))
|
225
|
+
end
|
226
|
+
|
227
|
+
def auto_labels
|
228
|
+
if @options[:auto_labels].nil?
|
229
|
+
FoundationRailsHelper.configuration.auto_labels
|
230
|
+
else
|
231
|
+
@options[:auto_labels]
|
232
|
+
end
|
255
233
|
end
|
256
234
|
end
|
257
235
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module FoundationRailsHelper
|
3
|
+
class SizeClassCalculator
|
4
|
+
def initialize(size_options)
|
5
|
+
@small = size_options[:small]
|
6
|
+
@medium = size_options[:medium]
|
7
|
+
@large = size_options[:large]
|
8
|
+
end
|
9
|
+
|
10
|
+
def classes
|
11
|
+
[small_class, medium_class, large_class].compact.join(' ')
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def small_class
|
17
|
+
"small-#{@small}" if valid_size(@small)
|
18
|
+
end
|
19
|
+
|
20
|
+
def medium_class
|
21
|
+
"medium-#{@medium}" if valid_size(@medium)
|
22
|
+
end
|
23
|
+
|
24
|
+
def large_class
|
25
|
+
"large-#{@large}" if valid_size(@large)
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_size(value)
|
29
|
+
value.present? && value.to_i < 12
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/railtie.rb
CHANGED
data/spec/.rubocop.yml
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "spec_helper"
|
2
3
|
|
3
4
|
describe FoundationRailsHelper do
|
4
5
|
describe FoundationRailsHelper::Configuration do
|
5
6
|
describe "#button_class" do
|
6
|
-
it "default value is '
|
7
|
+
it "default value is 'success button'" do
|
7
8
|
config = FoundationRailsHelper::Configuration.new
|
8
|
-
expect(config.button_class).to eq("
|
9
|
+
expect(config.button_class).to eq("success button")
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -32,6 +33,21 @@ describe FoundationRailsHelper do
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
36
|
+
describe "#auto_labels" do
|
37
|
+
it "default value is 'true'" do
|
38
|
+
config = FoundationRailsHelper::Configuration.new
|
39
|
+
expect(config.auto_labels).to be(true)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#auto_labels=" do
|
44
|
+
it "can set the value" do
|
45
|
+
config = FoundationRailsHelper::Configuration.new
|
46
|
+
config.auto_labels = false
|
47
|
+
expect(config.auto_labels).to be(false)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
35
51
|
describe ".reset" do
|
36
52
|
it "resets the configured button class" do
|
37
53
|
FoundationRailsHelper.configure do |config|
|
@@ -41,7 +57,7 @@ describe FoundationRailsHelper do
|
|
41
57
|
FoundationRailsHelper.reset
|
42
58
|
|
43
59
|
config = FoundationRailsHelper.configuration
|
44
|
-
expect(config.button_class).to eq("
|
60
|
+
expect(config.button_class).to eq("success button")
|
45
61
|
end
|
46
62
|
|
47
63
|
it "resets the configured ignored flash keys" do
|
@@ -54,6 +70,17 @@ describe FoundationRailsHelper do
|
|
54
70
|
config = FoundationRailsHelper.configuration
|
55
71
|
expect(config.ignored_flash_keys).to eq([])
|
56
72
|
end
|
73
|
+
|
74
|
+
it "resets the configured auto labels" do
|
75
|
+
FoundationRailsHelper.configure do |config|
|
76
|
+
config.auto_labels = false
|
77
|
+
end
|
78
|
+
|
79
|
+
FoundationRailsHelper.reset
|
80
|
+
|
81
|
+
config = FoundationRailsHelper.configuration
|
82
|
+
expect(config.auto_labels).to be(true)
|
83
|
+
end
|
57
84
|
end
|
58
85
|
end
|
59
86
|
end
|
@@ -1,60 +1,64 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
3
2
|
require "spec_helper"
|
4
3
|
|
5
4
|
describe FoundationRailsHelper::FlashHelper do
|
6
5
|
include ActionView::Context if defined?(ActionView::Context)
|
7
|
-
include ActionView::Helpers::
|
8
|
-
include ActionView::Helpers::TagHelper
|
9
|
-
include ActionView::Helpers::TextHelper
|
6
|
+
include ActionView::Helpers::FormTagHelper
|
10
7
|
include FoundationRailsHelper::FlashHelper
|
11
8
|
|
12
|
-
FoundationRailsHelper::FlashHelper::DEFAULT_KEY_MATCHING.
|
13
|
-
|
14
|
-
|
9
|
+
KEY_MATCHING = FoundationRailsHelper::FlashHelper::DEFAULT_KEY_MATCHING.freeze
|
10
|
+
|
11
|
+
KEY_MATCHING.each do |type, klass|
|
12
|
+
it "displays flash message with #{klass} class for #{type} message" do
|
13
|
+
allow(self).to receive(:flash).and_return(type.to_s => "Flash message")
|
15
14
|
node = Capybara.string display_flash_messages
|
16
15
|
expect(node)
|
17
|
-
.to have_css("div.
|
18
|
-
.and have_css("
|
16
|
+
.to have_css("div.flash.callout.#{klass}", text: "Flash message")
|
17
|
+
.and have_css("[data-close]", text: "×")
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
21
|
it "handles symbol keys" do
|
23
22
|
allow(self).to receive(:flash).and_return(success: "Flash message")
|
24
23
|
node = Capybara.string display_flash_messages
|
25
|
-
expect(node).to have_css("div.
|
24
|
+
expect(node).to have_css("div.callout.success", text: "Flash message")
|
26
25
|
end
|
27
26
|
|
28
27
|
it "handles string keys" do
|
29
28
|
allow(self).to receive(:flash).and_return("success" => "Flash message")
|
30
29
|
node = Capybara.string display_flash_messages
|
31
|
-
expect(node).to have_css("div.
|
30
|
+
expect(node).to have_css("div.callout.success", text: "Flash message")
|
32
31
|
end
|
33
32
|
|
34
33
|
it "displays multiple flash messages" do
|
35
|
-
allow(self).to receive(:flash)
|
34
|
+
allow(self).to receive(:flash)
|
35
|
+
.and_return("success" => "Yay it worked",
|
36
|
+
"error" => "But this other thing failed")
|
36
37
|
node = Capybara.string display_flash_messages
|
37
38
|
expect(node)
|
38
|
-
.to have_css("div.
|
39
|
-
.and have_css("div.
|
39
|
+
.to have_css("div.callout.success", text: "Yay it worked")
|
40
|
+
.and have_css("div.callout.alert", text: "But this other thing failed")
|
40
41
|
end
|
41
42
|
|
42
43
|
it "displays flash message with overridden key matching" do
|
43
44
|
allow(self).to receive(:flash).and_return("notice" => "Flash message")
|
44
|
-
node =
|
45
|
-
|
45
|
+
node =
|
46
|
+
Capybara.string display_flash_messages(key_matching: { notice: :alert })
|
47
|
+
expect(node).to have_css("div.callout.alert", text: "Flash message")
|
46
48
|
end
|
47
49
|
|
48
50
|
it "displays flash message with custom key matching" do
|
49
51
|
allow(self).to receive(:flash).and_return("custom_type" => "Flash message")
|
50
|
-
node = Capybara.string
|
51
|
-
|
52
|
+
node = Capybara.string(
|
53
|
+
display_flash_messages(key_matching: { custom_type: :custom_class })
|
54
|
+
)
|
55
|
+
expect(node).to have_css("div.callout.custom_class", text: "Flash message")
|
52
56
|
end
|
53
57
|
|
54
58
|
it "displays flash message with standard class if key doesn't match" do
|
55
59
|
allow(self).to receive(:flash).and_return("custom_type" => "Flash message")
|
56
60
|
node = Capybara.string display_flash_messages
|
57
|
-
expect(node).to have_css("div.
|
61
|
+
expect(node).to have_css("div.callout.primary", text: "Flash message")
|
58
62
|
end
|
59
63
|
|
60
64
|
context "when the flash hash contains devise internal data" do
|
@@ -73,13 +77,23 @@ describe FoundationRailsHelper::FlashHelper do
|
|
73
77
|
allow(self).to receive(:flash).and_return("timedout" => true)
|
74
78
|
expect(display_flash_messages).to be_nil
|
75
79
|
|
76
|
-
# Ideally we'd create a node using Capybara.string, as in the other
|
77
|
-
# and set the following expectation:
|
78
|
-
# expect(node).to_not have_css("div.
|
80
|
+
# Ideally we'd create a node using Capybara.string, as in the other
|
81
|
+
# examples and set the following expectation:
|
82
|
+
# expect(node).to_not have_css("div.callout")
|
79
83
|
# but Capybara.string doesn't behave nicely with nil input:
|
80
84
|
# the input gets assigned to the @native instance variable,
|
81
85
|
# which is used by the css matcher, so we get the following error:
|
82
86
|
# undefined method `css' for nil:NilClass
|
83
87
|
end
|
84
88
|
end
|
89
|
+
|
90
|
+
context "with (closable: false) option" do
|
91
|
+
it "doesn't display the close button" do
|
92
|
+
allow(self).to receive(:flash).and_return(success: "Flash message")
|
93
|
+
node = Capybara.string display_flash_messages(closable: false)
|
94
|
+
expect(node)
|
95
|
+
.to have_css("div.flash.callout.success", text: "Flash message")
|
96
|
+
.and have_no_css("[data-close]", text: "×")
|
97
|
+
end
|
98
|
+
end
|
85
99
|
end
|