bootstrap4_form_builder 0.0.1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +35 -0
  4. data/lib/bootstrap4_form_builder.rb +13 -0
  5. data/lib/bootstrap4_form_builder/form_builder.rb +254 -0
  6. data/lib/bootstrap4_form_builder/helper.rb +31 -0
  7. data/lib/bootstrap4_form_builder/version.rb +3 -0
  8. data/lib/tasks/bootstrap4_form_builder_tasks.rake +4 -0
  9. data/test/bootstrap4_form_builder_helper_test.rb +20 -0
  10. data/test/bootstrap4_form_builder_radio_check_test.rb +53 -0
  11. data/test/bootstrap4_form_builder_test.rb +130 -0
  12. data/test/bootstrap4_form_error_test.rb +47 -0
  13. data/test/dummy/README.rdoc +28 -0
  14. data/test/dummy/Rakefile +6 -0
  15. data/test/dummy/app/assets/javascripts/application.js +13 -0
  16. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  17. data/test/dummy/app/controllers/application_controller.rb +5 -0
  18. data/test/dummy/app/helpers/application_helper.rb +2 -0
  19. data/test/dummy/app/models/user.rb +4 -0
  20. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/test/dummy/bin/bundle +3 -0
  22. data/test/dummy/bin/rails +4 -0
  23. data/test/dummy/bin/rake +4 -0
  24. data/test/dummy/bin/setup +29 -0
  25. data/test/dummy/config.ru +4 -0
  26. data/test/dummy/config/application.rb +26 -0
  27. data/test/dummy/config/boot.rb +5 -0
  28. data/test/dummy/config/database.yml +25 -0
  29. data/test/dummy/config/environment.rb +5 -0
  30. data/test/dummy/config/environments/development.rb +41 -0
  31. data/test/dummy/config/environments/production.rb +79 -0
  32. data/test/dummy/config/environments/test.rb +42 -0
  33. data/test/dummy/config/initializers/assets.rb +11 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  36. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  37. data/test/dummy/config/initializers/inflections.rb +16 -0
  38. data/test/dummy/config/initializers/mime_types.rb +4 -0
  39. data/test/dummy/config/initializers/session_store.rb +3 -0
  40. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  41. data/test/dummy/config/locales/en.yml +23 -0
  42. data/test/dummy/config/routes.rb +3 -0
  43. data/test/dummy/config/secrets.yml +22 -0
  44. data/test/dummy/db/development.sqlite3 +0 -0
  45. data/test/dummy/db/migrate/20151028005827_create_users.rb +11 -0
  46. data/test/dummy/db/schema.rb +24 -0
  47. data/test/dummy/db/test.sqlite3 +0 -0
  48. data/test/dummy/log/development.log +10 -0
  49. data/test/dummy/log/test.log +1408 -0
  50. data/test/dummy/public/404.html +67 -0
  51. data/test/dummy/public/422.html +67 -0
  52. data/test/dummy/public/500.html +66 -0
  53. data/test/dummy/public/favicon.ico +0 -0
  54. data/test/dummy/test/fixtures/users.yml +11 -0
  55. data/test/dummy/test/models/user_test.rb +7 -0
  56. data/test/test_helper.rb +20 -0
  57. metadata +177 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 974db139d9433498cc39cea61e94e6826ee75115
4
+ data.tar.gz: 1a2e42618302f022c07014728766d947fef4c923
5
+ SHA512:
6
+ metadata.gz: c5ccd4d4992daa7ba8ee9269b9106927fe7d3d83850600f5b785a14bfba0e09856e6d6e3be963ed352cd510b9047e9637c4fa7fa5ca02095a2c10ad94fcf9711
7
+ data.tar.gz: 079aca0f9a5fb7a914722bda45e63cc4295ba35e299a4759a334e8e78290e4e1086ba866bb815001441d3284fad0cdcb443731a2236dd2c85c9c4b3d0e93cfa1
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Christopher Slade
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ require 'rdoc/task'
9
+
10
+ RDoc::Task.new(:rdoc) do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = 'Bootstrap4FormBuilder'
13
+ rdoc.options << '--line-numbers'
14
+ rdoc.rdoc_files.include('README.rdoc')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+
18
+
19
+
20
+
21
+
22
+
23
+ Bundler::GemHelper.install_tasks
24
+
25
+ require 'rake/testtask'
26
+
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'lib'
29
+ t.libs << 'test'
30
+ t.pattern = 'test/**/*_test.rb'
31
+ t.verbose = false
32
+ end
33
+
34
+
35
+ task default: :test
@@ -0,0 +1,13 @@
1
+ require 'bootstrap4_form_builder/form_builder'
2
+ require 'bootstrap4_form_builder/helper'
3
+
4
+ module Bootstrap4FormBuilder
5
+ module Rails
6
+ class Engine < ::Rails::Engine
7
+ end
8
+ end
9
+ end
10
+
11
+ ActionView::Base.send :include, Bootstrap4FormBuilder::Helper
12
+ ActionView::Base.send :include, Bootstrap4FormBuilder::FormBuilder
13
+
@@ -0,0 +1,254 @@
1
+ module Bootstrap4FormBuilder
2
+ module FormBuilder
3
+ class BootstrapBuilder < ActionView::Helpers::FormBuilder
4
+
5
+ delegate :content_tag, :concat, :capture, to: :@template
6
+
7
+ attr_reader :layout, :label_col, :control_col
8
+
9
+ FIELD_HELPERS = %w{color_field date_field datetime_field datetime_local_field
10
+ email_field month_field number_field password_field phone_field
11
+ range_field search_field telephone_field text_area text_field time_field
12
+ url_field week_field}
13
+
14
+ def initialize(object_name, object, template, options)
15
+ @layout = options[:layout]
16
+ @label_col = options[:label_col]
17
+ @control_col = options[:control_col]
18
+ @inline_errors = options[:inline_errors].nil? ? true : options[:inline_errors]
19
+ @inline_error_class = options[:inline_error_class]
20
+ #puts "Inline Errors: #{@inline_errors}"
21
+ #Could be done in helper.
22
+ if inline_layout?
23
+ options.reverse_merge! html: {}
24
+ options[:html][:class] = [options[:html][:class], inline_class].compact.join(" ")
25
+ end
26
+
27
+ super
28
+ end
29
+
30
+ FIELD_HELPERS.each do |method_name|
31
+ define_method(method_name) do |method, *args|
32
+ options = args.extract_options!.symbolize_keys!
33
+ standard_html("#{__method__.to_s}", method, options)
34
+ end
35
+ end
36
+
37
+ def standard_html(type, method, options = {})
38
+ form_group_builder(method, options) do
39
+ content = []
40
+ options[:class] = [control_class, options[:class]].compact.join(" ")
41
+
42
+
43
+ temporarily_disable_field_error_proc do
44
+ content << generate_label(method, options)
45
+ if gridded_form?
46
+ content << content_tag(:div, class: @control_col) do
47
+ @template.send(type, object_name, method, options)
48
+ end
49
+ else
50
+ content << @template.send(type, object_name, method, options)
51
+ end
52
+ end
53
+ content << generate_error_help(method, options)
54
+ content.compact.join.html_safe
55
+ end
56
+ end
57
+
58
+ def check_box(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
59
+ options = options.symbolize_keys!
60
+ check_box_options = options.except(:label, :label_class, :inline)
61
+ label_class = [options[:label_class]]
62
+
63
+ temporarily_disable_field_error_proc do
64
+ html = super(name, check_box_options, checked_value, unchecked_value)
65
+ label_content = block_given? ? capture(&block) : options[:label]
66
+ html.concat(" ").concat(label_content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize)
67
+
68
+ label_name = name
69
+
70
+ label_class = options[:label_class]
71
+
72
+ if options[:inline]
73
+ label_class = ["checkbox-inline", label_class].compact.join(' ')
74
+ label(label_name, html, class: label_class)
75
+ else
76
+ content_tag(:div, class: "checkbox") do
77
+ label(label_name, html, class: label_class)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def radio_button(name, value, *args)
84
+ options = args.extract_options!.symbolize_keys!
85
+ args << options.except(:label, :label_class, :inline)
86
+ label_class = [options[:label_class]]
87
+
88
+ temporarily_disable_field_error_proc do
89
+ html = super(name, value, *args) + " " + value.humanize
90
+
91
+ if options[:inline]
92
+ label_class = ["radio-inline", label_class].compact.join(" ")
93
+ label(value, html, value: value, class: label_class)
94
+ else
95
+ content_tag(:div, class: "radio") do
96
+ label(value, html, value: value, class: label_class)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ def form_group(*args, &block)
103
+ options = args.extract_options!
104
+ name = args.first
105
+
106
+ options[:class] = ["form-group", options[:class]]
107
+ options[:class] << label_error_class if has_errors?(name)
108
+ options[:class] = options[:class].compact.join(" ")
109
+
110
+ content_tag(:div, options.except(:label, :label_class)) do
111
+ label_class = [@label_col, options[:label_class]].compact.join(' ')
112
+
113
+ label = @template.label_tag(nil, options[:label], class: label_class) if options[:label]
114
+ controls = capture(&block).to_s
115
+
116
+ error_help = generate_error_help(name)
117
+ controls = content_tag(:div, class: @control_col) { concat(controls) } if gridded_form?
118
+
119
+
120
+ concat(label).concat(controls).concat(error_help)
121
+ end
122
+ end
123
+
124
+ def submit(name = nil, options = {})
125
+ options[:class] = ["btn btn-default", options[:class]].compact.join(" ")
126
+ super(name, options)
127
+ end
128
+
129
+ def primary(name = nil, options = {})
130
+ options[:class] = ["btn btn-primary", options[:class]].compact.join(" ")
131
+ method(:submit).super_method.call(name, options)
132
+ end
133
+
134
+ def alert_message(title, options = {})
135
+ alert_class = options[:class] || 'alert alert-danger'
136
+ display_errors = options.delete(:error_summary)
137
+
138
+ if object.respond_to?(:errors) && object.errors.full_messages.any?
139
+ content_tag :div, class: alert_class do
140
+ content = [content_tag(:p, title)]
141
+ content << error_summary if display_errors
142
+ content.join.html_safe
143
+ end
144
+ end
145
+ end
146
+
147
+ def error_summary
148
+ content_tag :ul, class: 'bootstrap-form-error-summary' do
149
+ object.errors.full_messages.each do |error|
150
+ concat content_tag(:li, error)
151
+ end
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def objectify_options(options)
158
+ super.except(:layout, :inline_errors, :inline_error_class)
159
+ end
160
+
161
+ def temporarily_disable_field_error_proc
162
+ original_proc = ActionView::Base.field_error_proc
163
+ ActionView::Base.field_error_proc = proc { |input, instance| input }
164
+ yield
165
+ ensure
166
+ ActionView::Base.field_error_proc = original_proc
167
+ end
168
+
169
+ def form_group_builder(method, options)
170
+ container_class = [fieldset_class]
171
+ container_class << "row" if gridded_form?
172
+ container_class << fieldset_errors_class if has_errors?(method)
173
+ container_class << options.delete(:container_class)
174
+ container_class = container_class.compact.join(" ")
175
+
176
+ content_tag :div, class: container_class do
177
+ yield
178
+ end
179
+ end
180
+
181
+ def generate_label(name, *args)
182
+ options = args.extract_options!
183
+ label_class = options.delete(:label_class)
184
+ label_class = ["form-control-label", @label_col, label_class]
185
+ label_class << hide_label_class if hide_label?(options)
186
+ label_class << label_error_class if has_errors?(name)
187
+ label_class = label_class.compact.join(" ")
188
+
189
+ label_name = options.delete(:label)
190
+ label_name ||= name.to_s.humanize
191
+
192
+ label(name, label_name, class: label_class)
193
+ end
194
+
195
+ def generate_error_help(name, *args)
196
+ if has_errors?(name) && @inline_errors
197
+ error_class = ["text-muted", "error-text", @inline_error_class].compact.join(" ")
198
+ content_tag(:small, class: error_class) do
199
+ get_error_messages(name)
200
+ end
201
+ end
202
+ end
203
+
204
+ def gridded_form?
205
+ @label_col && @control_col
206
+ end
207
+
208
+ def inline_layout?
209
+ @layout == :inline
210
+ end
211
+
212
+ def hide_label?(options)
213
+ options.delete(:hide_label)
214
+ end
215
+
216
+ #Errors
217
+
218
+ def has_errors?(name)
219
+ object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
220
+ end
221
+
222
+ def get_error_messages(name)
223
+ object.errors[name].join(", ")
224
+ end
225
+
226
+ #Default classes
227
+
228
+ def hide_label_class
229
+ "sr-only"
230
+ end
231
+
232
+ def inline_class
233
+ "form-inline"
234
+ end
235
+
236
+ def control_class
237
+ "form-control"
238
+ end
239
+
240
+ def fieldset_class
241
+ "form-group"
242
+ end
243
+
244
+ def label_error_class
245
+ "label-error"
246
+ end
247
+
248
+ def fieldset_errors_class
249
+ "field-with-errors"
250
+ end
251
+
252
+ end
253
+ end
254
+ end
@@ -0,0 +1,31 @@
1
+ module Bootstrap4FormBuilder
2
+ module Helper
3
+
4
+ def bootstrap_form_for(object, options= {}, &block)
5
+ options.reverse_merge!({builder: Bootstrap4FormBuilder::FormBuilder::BootstrapBuilder})
6
+
7
+ options[:html] ||= {}
8
+ options[:html][:role] ||= "form"
9
+
10
+ #Done in Builder
11
+ # if options[:layout] == :inline
12
+ # options[:html][:class] = [options[:html][:class], "form-inline"].compact.join(" ")
13
+ # end
14
+
15
+ #Done in Builder
16
+ #temporarily_disable_field_error_proc do
17
+ form_for(object, options, &block)
18
+ #end
19
+ end
20
+
21
+
22
+ def temporarily_disable_field_error_proc
23
+ original_proc = ActionView::Base.field_error_proc
24
+ ActionView::Base.field_error_proc = proc { |input, instance| input }
25
+ yield
26
+ ensure
27
+ ActionView::Base.field_error_proc = original_proc
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Bootstrap4FormBuilder
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bootstrap4_form_builder do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class Bootstap4FormBuilderHelperTest < ActionView::TestCase
4
+ include Bootstrap4FormBuilder::Helper
5
+
6
+ test "default forms" do
7
+ expected = %{<form role="form" class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><div class="form-group"><label class="form-control-label" for="user_name">Name</label><input class="form-control" type="text" name="user[name]" id="user_name" /></div></form>}
8
+ assert_equal expected, bootstrap_form_for(User.new) { |f| f.text_field(:name)}
9
+ end
10
+
11
+ test "inline forms" do
12
+ expected = %{<form role="form" class="new_user form-inline" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><div class="form-group"><label class="form-control-label" for="user_name">Name</label><input class="form-control" type="text" name="user[name]" id="user_name" /></div></form>}
13
+ assert_equal expected, bootstrap_form_for(User.new, layout: :inline) { |f| f.text_field(:name)}
14
+ end
15
+
16
+ test "gridded forms" do
17
+ expected = %{<form role="form" class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><div class="form-group row"><label class="form-control-label col-sm-2" for="user_name">Name</label><div class="col-sm-10"><input class="form-control" type="text" name="user[name]" id="user_name" /></div></div></form>}
18
+ assert_equal expected, bootstrap_form_for(User.new, label_col: 'col-sm-2', control_col: 'col-sm-10') { |f| f.text_field(:name)}
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ class Bootstrap4FormBuilderRadioCheckTest < ActionView::TestCase
4
+
5
+ def setup
6
+ @builder = Bootstrap4FormBuilder::FormBuilder::BootstrapBuilder.new(:user, nil, self, {})
7
+ end
8
+
9
+ test "radio_button is wrapped correctly" do
10
+ expected = %{<div class="form-group"><div class="radio"><label class="" for="user_male_male"><input type="radio" value="male" name="user[gender]" id="user_gender_male" /> Male</label></div><div class="radio"><label class="" for="user_female_female"><input type="radio" value="female" name="user[gender]" id="user_gender_female" /> Female</label></div></div>}
11
+ output = @builder.form_group(:gender) do
12
+ @builder.radio_button(:gender, "male") + @builder.radio_button(:gender, "female")
13
+ end
14
+
15
+ assert_equal expected, output
16
+ end
17
+
18
+ test "check_box is wrapped correctly" do
19
+ expected = %{<div class="form-group"><div class="checkbox"><label for="user_agree"><input name="user[agree]" type="hidden" value="0" /><input type="checkbox" value="1" name="user[agree]" id="user_agree" /> Agree to Terms</label></div></div>}
20
+ output = @builder.form_group(:agree) do
21
+ @builder.check_box :agree, label: "Agree to Terms"
22
+ end
23
+
24
+ assert_equal expected, output
25
+ end
26
+
27
+ test "radio_button inline is wrapped correctly" do
28
+ expected = %{<div class="form-group"><label class="radio-inline " for="user_male_male"><input type="radio" value="male" name="user[gender]" id="user_gender_male" /> Male</label><label class="radio-inline " for="user_female_female"><input type="radio" value="female" name="user[gender]" id="user_gender_female" /> Female</label></div>}
29
+ output = @builder.form_group(:gender) do
30
+ @builder.radio_button(:gender, "male", inline: true)+@builder.radio_button(:gender, "female", inline: true)
31
+ end
32
+
33
+ assert_equal expected, output
34
+ end
35
+
36
+ test "check_box inline is wrapped correctly" do
37
+ expected = %{<div class="form-group"><label class="checkbox-inline" for="user_agree"><input name="user[agree]" type="hidden" value="0" /><input type="checkbox" value="1" name="user[agree]" id="user_agree" /> Agree to Terms</label></div>}
38
+ output = @builder.form_group(:agree) do
39
+ @builder.check_box :agree, label: "Agree to Terms", inline: true
40
+ end
41
+
42
+ assert_equal expected, output
43
+ end
44
+
45
+ test "form_group label and label_class are included" do
46
+ expected = %{<div class="form-group"><label class="terms-label">Terms</label><div class="checkbox"><label for="user_agree"><input name="user[agree]" type="hidden" value="0" /><input type="checkbox" value="1" name="user[agree]" id="user_agree" /> Agree to Terms</label></div></div>}
47
+ output = @builder.form_group(:agree, label: "Terms", label_class: "terms-label") do
48
+ @builder.check_box :agree, label: "Agree to Terms"
49
+ end
50
+
51
+ assert_equal expected, output
52
+ end
53
+ end