simple_bootstrap_form 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile +9 -0
- data/Guardfile +9 -0
- data/README.md +84 -1
- data/Rakefile +9 -0
- data/circle.yml +5 -0
- data/lib/simple_bootstrap_form/action_view_extensions.rb +5 -5
- data/lib/simple_bootstrap_form/css_class_list.rb +1 -1
- data/lib/simple_bootstrap_form/field_factory.rb +58 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/base_field.rb +118 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/boolean_field.rb +16 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/datetime_field.rb +55 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/email_field.rb +10 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/password_field.rb +10 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/text_field.rb +10 -0
- data/lib/simple_bootstrap_form/horizontal_form/fields/textarea_field.rb +14 -0
- data/lib/simple_bootstrap_form/horizontal_form/form_builder.rb +59 -0
- data/lib/simple_bootstrap_form/version.rb +1 -1
- data/lib/simple_bootstrap_form.rb +9 -8
- data/simple_bootstrap_form.gemspec +1 -1
- data/spec/field_factory_spec.rb +65 -0
- data/spec/simple_bootstrap_form_spec.rb +360 -83
- data/spec/spec_helper.rb +3 -0
- data/spec/support/have_element.rb +109 -0
- metadata +19 -13
- data/lib/simple_bootstrap_form/fields/base_field.rb +0 -103
- data/lib/simple_bootstrap_form/fields/boolean_field.rb +0 -14
- data/lib/simple_bootstrap_form/fields/datetime_field.rb +0 -53
- data/lib/simple_bootstrap_form/fields/email_field.rb +0 -8
- data/lib/simple_bootstrap_form/fields/password_field.rb +0 -8
- data/lib/simple_bootstrap_form/fields/text_field.rb +0 -8
- data/lib/simple_bootstrap_form/fields/textarea_field.rb +0 -12
- data/lib/simple_bootstrap_form/form_builder.rb +0 -51
- data/spec/support/input_matchers.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49612ff415db9c67ef7d7fddec5ce1628a89bd56
|
4
|
+
data.tar.gz: f44b2d057f9fb6c315271314a119245dab29f9d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d98ef3d428ad7ced926485824bc37ba490d531d2d7adbae27ea7b3b7a065566155fa1aff84a68dc366e0129e8f203a13541f97c8a74030ad26ae9f4d47bf402
|
7
|
+
data.tar.gz: 70730348cf4eb5997e8de562623fc2cb76e44d48de10d412cbac84e77ec06ca38e7cc86be8785fa6dfffddbee28b8cdcb477e149d486f79a86951036c2469e42
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
CHANGED
@@ -2,3 +2,12 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in my_gem.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
# Gems required to run guard-rspec and send notifications to OS Notification
|
8
|
+
# System
|
9
|
+
gem 'guard-rspec', require: false
|
10
|
+
gem 'terminal-notifier-guard'
|
11
|
+
|
12
|
+
gem 'byebug'
|
13
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', all_on_start: false, all_after_pass: false , failed_mode: :keep do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
#watch(%r{^lib/(.+)\.rb$}) { |m| "spec#{m[1]}_spec.rb" }
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/simple_bootstrap_form_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { "spec" }
|
9
|
+
end
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Bootstrap 3 Form Builder
|
2
2
|
|
3
|
+
![CiecleCI Build Status](https://circleci.com/gh/Piersonally/simple_bootstrap_form.png?circle-token=1adabd4d96f92f6566f705581fb108ed59b31150)
|
4
|
+
|
3
5
|
* I'm a fan of [Boootstrap](http://getbootstrap.com/)
|
4
6
|
* I'm a fan of [Simple Form](https://github.com/plataformatec/simple_form)
|
5
7
|
* Bootstrap 3 was released in August 2013, but as of February 2014 Simple Form
|
@@ -18,7 +20,7 @@ is going to require a new feature in the base Simple Form framework.
|
|
18
20
|
SimpleForm is a featurefull generic framework that will layout forms for
|
19
21
|
multiple different CSS frameworks (right now Bootstrap 2.3 and Zurb Foundation).
|
20
22
|
The challenge with this is that greater flexibility incurs greater complexity in
|
21
|
-
|
23
|
+
implementation. I believe the continued non-appearance of Simple Form Bootstrap
|
22
24
|
3 support reflects the difficulty people have in working in this more complex
|
23
25
|
framework, and getting the results integrated and released.
|
24
26
|
|
@@ -52,6 +54,87 @@ with
|
|
52
54
|
|
53
55
|
bootstrap_form_for ...
|
54
56
|
|
57
|
+
For example:
|
58
|
+
|
59
|
+
```haml
|
60
|
+
= bootstrap_form_for @article_form do |f|
|
61
|
+
= f.input :title
|
62
|
+
= f.input :published_at
|
63
|
+
= f.input :visible
|
64
|
+
= f.input :body, rows: 20
|
65
|
+
= f.input :topic_names, label: 'Tags'
|
66
|
+
```
|
67
|
+
|
68
|
+
Generates (spaces added for clarity):
|
69
|
+
|
70
|
+
```html
|
71
|
+
<form accept-charset="UTF-8" action="/articles" class="form-horizontal"
|
72
|
+
id="new_article" method="post" role="form">
|
73
|
+
<div style="display:none"><input name="utf8" type="hidden" value="✓"><input
|
74
|
+
name="authenticity_token" type="hidden"
|
75
|
+
value="NYiknMBfTGqphSHozhG8NMCGQeWbRY6hzs2a0+gaxJw="></div>
|
76
|
+
|
77
|
+
<div class="form-group article_title_group"><label
|
78
|
+
class="control-label col-sm-3" for="article_title"><abbr
|
79
|
+
title="required">*</abbr> Title</label>
|
80
|
+
|
81
|
+
<div class="col-sm-6"><input class="form-control" id="article_title"
|
82
|
+
name="article[title]" placeholder="Title"
|
83
|
+
required="required" type="text"></div>
|
84
|
+
</div>
|
85
|
+
|
86
|
+
<div class="form-group article_published_at_group"><label
|
87
|
+
class="control-label col-sm-3" for="article_published_at">Published
|
88
|
+
at</label>
|
89
|
+
<div class="col-sm-6">
|
90
|
+
<div class="input-group"><input class="form-control"
|
91
|
+
id="article_published_at"
|
92
|
+
name="article[published_at]"
|
93
|
+
placeholder="Published at"
|
94
|
+
type="datetime">
|
95
|
+
|
96
|
+
<div class="input-group-addon"><span
|
97
|
+
class="glyphicon glyphicon-calendar"
|
98
|
+
data-activate-datepicker="#article_published_at"></span></div>
|
99
|
+
</div>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
|
103
|
+
<div class="form-group article_visible_group"><label
|
104
|
+
class="control-label col-sm-3" for="article_visible">Visible</label>
|
105
|
+
|
106
|
+
<div class="col-sm-6"><input name="article[visible]" type="hidden"
|
107
|
+
value="0"><input id="article_visible"
|
108
|
+
name="article[visible]"
|
109
|
+
type="checkbox" value="1">
|
110
|
+
</div>
|
111
|
+
</div>
|
112
|
+
|
113
|
+
<div class="form-group article_body_group"><label
|
114
|
+
class="control-label col-sm-3" for="article_body">Body</label>
|
115
|
+
|
116
|
+
<div class="col-sm-6"><textarea class="form-control" id="article_body"
|
117
|
+
name="article[body]" placeholder="Body"
|
118
|
+
rows="20"></textarea></div>
|
119
|
+
</div>
|
120
|
+
|
121
|
+
<div class="form-group article_topic_names_group"><label
|
122
|
+
class="control-label col-sm-3" for="article_topic_names">Tags</label>
|
123
|
+
|
124
|
+
<div class="col-sm-6"><input class="form-control" id="article_topic_names"
|
125
|
+
label="Tags" name="article[topic_names]"
|
126
|
+
placeholder="Topic names" type="text" value="">
|
127
|
+
</div>
|
128
|
+
</div>
|
129
|
+
|
130
|
+
<div class="form-group">
|
131
|
+
<div class="col-sm-offset-3 col-sm-2">
|
132
|
+
<input class="btn btn-primary" name="commit" type="submit" value="Save">
|
133
|
+
</div>
|
134
|
+
</div>
|
135
|
+
</form>
|
136
|
+
```
|
137
|
+
|
55
138
|
## Support
|
56
139
|
|
57
140
|
#### Bootstrap Support
|
data/Rakefile
CHANGED
data/circle.yml
ADDED
@@ -2,11 +2,7 @@ module SimpleBootstrapForm
|
|
2
2
|
module ActionViewExtensions
|
3
3
|
|
4
4
|
def bootstrap_form_for(record, options={}, &block)
|
5
|
-
options[:builder] ||=
|
6
|
-
options[:html] ||= {}
|
7
|
-
options[:html][:class] = CssClassList.new options[:html][:class]
|
8
|
-
options[:html][:class] << 'form-horizontal'
|
9
|
-
options[:html][:role] ||= 'form'
|
5
|
+
options[:builder] ||= form_builder_class options
|
10
6
|
prevent_action_view_putting_a_div_around_all_fields_with_errors do
|
11
7
|
form_for record, options, &block
|
12
8
|
end
|
@@ -14,6 +10,10 @@ module SimpleBootstrapForm
|
|
14
10
|
|
15
11
|
private
|
16
12
|
|
13
|
+
def form_builder_class(options)
|
14
|
+
SimpleBootstrapForm::HorizontalForm::FormBuilder
|
15
|
+
end
|
16
|
+
|
17
17
|
def prevent_action_view_putting_a_div_around_all_fields_with_errors(&block)
|
18
18
|
orig_field_error_proc = ::ActionView::Base.field_error_proc
|
19
19
|
begin
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
class FieldFactory
|
3
|
+
|
4
|
+
def initialize(builder, template)
|
5
|
+
@builder = builder
|
6
|
+
@template = template
|
7
|
+
end
|
8
|
+
|
9
|
+
def for_attribute(attr, options)
|
10
|
+
field_class(attr, options).new(@builder, @template, attr, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def field_class(attr, options)
|
16
|
+
field_class_name(attr, options).constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
def field_class_name(attr, options)
|
20
|
+
type_prefix = field_class_type_prefix attr, options
|
21
|
+
class_name = "#{type_prefix}Field"
|
22
|
+
@builder.class.fully_qualified_class_name_for_field class_name
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return first half of a field class name, based on the type of the
|
26
|
+
# field: 'Text', 'Email', 'Password', 'Textarea', 'Boolean', etc.
|
27
|
+
# Appending 'Field' to this gets you a real class, e.g. TextField
|
28
|
+
def field_class_type_prefix(attr, options)
|
29
|
+
if options[:as]
|
30
|
+
options[:as].to_s.capitalize
|
31
|
+
else
|
32
|
+
derive_field_class_prefix attr
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def derive_field_class_prefix(attr)
|
37
|
+
case attr_column_type(attr)
|
38
|
+
when :boolean; 'Boolean'
|
39
|
+
when :datetime; 'Datetime'
|
40
|
+
when :string; string_field_class_prefix_based_on_column_name(attr)
|
41
|
+
when :text ; 'Textarea'
|
42
|
+
else 'Text'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def attr_column_type(attr)
|
47
|
+
@builder.object.try(:column_for_attribute, attr).try(:type) || :string
|
48
|
+
end
|
49
|
+
|
50
|
+
def string_field_class_prefix_based_on_column_name(attr)
|
51
|
+
case
|
52
|
+
when attr.to_s =~ /email/i ; 'Email'
|
53
|
+
when attr.to_s =~ /password/i ; 'Password'
|
54
|
+
else 'Text'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
module HorizontalForm
|
3
|
+
module Fields
|
4
|
+
class BaseField
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :type
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(form_builder, template, name, options)
|
11
|
+
@form_builder = form_builder
|
12
|
+
@template = template
|
13
|
+
@name = name
|
14
|
+
process_options(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@template.content_tag :div, group_options do
|
19
|
+
field_label +
|
20
|
+
input_tag +
|
21
|
+
errors_block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def process_options(options)
|
28
|
+
@options = options.dup
|
29
|
+
@label_size = @options.delete :label_size
|
30
|
+
@input_size = @options.delete :input_size
|
31
|
+
@label_text = @options.delete :label
|
32
|
+
@group_class = @options.delete :group_class
|
33
|
+
end
|
34
|
+
|
35
|
+
def group_options
|
36
|
+
css_classes = CssClassList.new 'form-group', group_class
|
37
|
+
css_classes << 'has-error' if has_error?
|
38
|
+
{ class: css_classes }
|
39
|
+
end
|
40
|
+
|
41
|
+
def group_class # a class for the form group to make it more testable
|
42
|
+
case @group_class
|
43
|
+
when false; nil
|
44
|
+
when nil; "#{@form_builder.object_name.to_s.underscore}_#{@name}_group"
|
45
|
+
else @group_class
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def field_label
|
50
|
+
@form_builder.label @name, @label_text, label_options
|
51
|
+
end
|
52
|
+
|
53
|
+
def label_text
|
54
|
+
text = @options[:label] || @name.to_s.humanize.capitalize
|
55
|
+
required_asterisk + text
|
56
|
+
end
|
57
|
+
|
58
|
+
def required_asterisk
|
59
|
+
if required?
|
60
|
+
@template.content_tag(:abbr, '*', title: 'required') + ' '
|
61
|
+
else
|
62
|
+
''
|
63
|
+
end.html_safe
|
64
|
+
end
|
65
|
+
|
66
|
+
def label_options
|
67
|
+
css_classes = CssClassList.new 'control-label'
|
68
|
+
css_classes << @label_size
|
69
|
+
{ class: css_classes.to_s }
|
70
|
+
end
|
71
|
+
|
72
|
+
def input_tag
|
73
|
+
@template.content_tag(:div, class: @input_size) do
|
74
|
+
@form_builder.text_field @name, input_options
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def input_options
|
79
|
+
@options.merge! class: 'form-control',
|
80
|
+
placeholder: placeholder,
|
81
|
+
type: self.class.type
|
82
|
+
@options.merge! required: 'required' if required?
|
83
|
+
@options
|
84
|
+
end
|
85
|
+
|
86
|
+
def placeholder
|
87
|
+
@options[:placeholder] || @name.to_s.humanize
|
88
|
+
end
|
89
|
+
|
90
|
+
def errors_block
|
91
|
+
return '' unless errors.any?
|
92
|
+
@template.content_tag :span, errors.join(', '),
|
93
|
+
class: 'help-block col-sm-3'
|
94
|
+
end
|
95
|
+
|
96
|
+
def model
|
97
|
+
@form_builder.object
|
98
|
+
end
|
99
|
+
|
100
|
+
def errors
|
101
|
+
return [] unless model
|
102
|
+
@cached_errors ||= model.errors[@name.to_sym]
|
103
|
+
end
|
104
|
+
|
105
|
+
def required?
|
106
|
+
return false unless model
|
107
|
+
model.class.validators_on(@name).any? do |validator|
|
108
|
+
validator.kind_of? ActiveModel::Validations::PresenceValidator
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def has_error?
|
113
|
+
errors.any?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
module HorizontalForm
|
3
|
+
module Fields
|
4
|
+
class BooleanField < BaseField
|
5
|
+
|
6
|
+
self.type = 'checkbox'
|
7
|
+
|
8
|
+
def input_tag
|
9
|
+
@template.content_tag(:div, class: 'col-sm-6') do
|
10
|
+
@form_builder.check_box @name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
module HorizontalForm
|
3
|
+
module Fields
|
4
|
+
class DatetimeField < BaseField
|
5
|
+
|
6
|
+
self.type = 'datetime'
|
7
|
+
|
8
|
+
def input_tag
|
9
|
+
@template.content_tag(:div, class: 'col-sm-6') do
|
10
|
+
@template.content_tag :div, class: 'input-group' do
|
11
|
+
@form_builder.text_field(@name, input_options) +
|
12
|
+
calendar_icon
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def calendar_icon
|
20
|
+
@template.content_tag(:div, class: 'input-group-addon') do
|
21
|
+
@template.content_tag(:span, '',
|
22
|
+
class: 'glyphicon glyphicon-calendar',
|
23
|
+
data: { 'activate-datepicker' => "##{tag_id}" }
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def input_options
|
29
|
+
super
|
30
|
+
@options.merge! value: value_suitable_for_use_by_jquery_datetimepicker
|
31
|
+
@options
|
32
|
+
end
|
33
|
+
|
34
|
+
def value_suitable_for_use_by_jquery_datetimepicker
|
35
|
+
@form_builder.object.send(@name).try(:strftime, '%Y/%m/%d %H:%M')
|
36
|
+
end
|
37
|
+
|
38
|
+
# Adapted from module ActionView::Helpers::Tags::Base
|
39
|
+
def tag_id
|
40
|
+
"#{sanitized_object_name}_#{sanitized_method_name}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Adapted from module ActionView::Helpers::Tags::Base
|
44
|
+
def sanitized_object_name
|
45
|
+
@form_builder.object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Adapted from module ActionView::Helpers::Tags::Base
|
49
|
+
def sanitized_method_name
|
50
|
+
@name.to_s.sub(/\?$/,"")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
module HorizontalForm
|
3
|
+
module Fields
|
4
|
+
class TextareaField < BaseField
|
5
|
+
|
6
|
+
def input_tag
|
7
|
+
@template.content_tag(:div, class: 'col-sm-6') do
|
8
|
+
@form_builder.text_area @name, input_options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module SimpleBootstrapForm
|
2
|
+
module HorizontalForm
|
3
|
+
class FormBuilder < ActionView::Helpers::FormBuilder
|
4
|
+
|
5
|
+
def initialize(object_name, object, template, options={}, block=nil)
|
6
|
+
@field_factory = FieldFactory.new self, template
|
7
|
+
process_options options
|
8
|
+
super object_name, object, template, options_for_rails_form_builder, block
|
9
|
+
end
|
10
|
+
|
11
|
+
def input(name, supplied_options = {})
|
12
|
+
options = field_options(supplied_options)
|
13
|
+
@field_factory.for_attribute(name, options).to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.fully_qualified_class_name_for_field(field_class_name)
|
17
|
+
# Better to do this manually than using introspection
|
18
|
+
"SimpleBootstrapForm::HorizontalForm::Fields::#{field_class_name}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def process_options(options)
|
24
|
+
@options = options.dup
|
25
|
+
@options.delete :layout
|
26
|
+
@group_class = @options.delete :group_class
|
27
|
+
end
|
28
|
+
|
29
|
+
def options_for_rails_form_builder
|
30
|
+
@options[:html] ||= {}
|
31
|
+
@options[:html][:role] ||= 'form'
|
32
|
+
@options[:html][:class] = form_css_classes
|
33
|
+
@options
|
34
|
+
end
|
35
|
+
|
36
|
+
def form_css_classes
|
37
|
+
css_classes = CssClassList.new options[:html][:class]
|
38
|
+
css_classes << 'form-horizontal'
|
39
|
+
css_classes
|
40
|
+
end
|
41
|
+
|
42
|
+
def field_options(supplied_options)
|
43
|
+
options = supplied_options.dup
|
44
|
+
options[:label_size] ||= field_label_size
|
45
|
+
options[:input_size] ||= field_input_size
|
46
|
+
options[:group_class] = @group_class if @group_class == false
|
47
|
+
options
|
48
|
+
end
|
49
|
+
|
50
|
+
def field_label_size
|
51
|
+
@options[:label_size] || 'col-sm-3'
|
52
|
+
end
|
53
|
+
|
54
|
+
def field_input_size
|
55
|
+
@options[:input_size] || 'col-sm-6'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require 'simple_bootstrap_form'
|
2
2
|
require 'simple_bootstrap_form/css_class_list'
|
3
3
|
require 'simple_bootstrap_form/action_view_extensions'
|
4
|
-
require 'simple_bootstrap_form/
|
5
|
-
require 'simple_bootstrap_form/
|
6
|
-
require 'simple_bootstrap_form/fields/
|
7
|
-
require 'simple_bootstrap_form/fields/
|
8
|
-
require 'simple_bootstrap_form/fields/
|
9
|
-
require 'simple_bootstrap_form/fields/
|
10
|
-
require 'simple_bootstrap_form/fields/
|
11
|
-
require 'simple_bootstrap_form/fields/
|
4
|
+
require 'simple_bootstrap_form/field_factory'
|
5
|
+
require 'simple_bootstrap_form/horizontal_form/form_builder'
|
6
|
+
require 'simple_bootstrap_form/horizontal_form/fields/base_field'
|
7
|
+
require 'simple_bootstrap_form/horizontal_form/fields/boolean_field'
|
8
|
+
require 'simple_bootstrap_form/horizontal_form/fields/datetime_field'
|
9
|
+
require 'simple_bootstrap_form/horizontal_form/fields/email_field'
|
10
|
+
require 'simple_bootstrap_form/horizontal_form/fields/password_field'
|
11
|
+
require 'simple_bootstrap_form/horizontal_form/fields/text_field'
|
12
|
+
require 'simple_bootstrap_form/horizontal_form/fields/textarea_field'
|
12
13
|
|
13
14
|
ActionView::Base.send :include, SimpleBootstrapForm::ActionViewExtensions
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec-rails", ">= 3.0.0.beta1"
|
24
24
|
spec.add_development_dependency "sqlite3"
|
25
|
-
spec.add_development_dependency "
|
25
|
+
spec.add_development_dependency "nokogiri" # used by has_element matcher
|
26
26
|
spec.add_runtime_dependency "rails", ">= 4"
|
27
27
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleBootstrapForm::FieldFactory do
|
4
|
+
let(:model) { double 'model' }
|
5
|
+
let(:field_factory) { SimpleBootstrapForm::FieldFactory.new builder, nil }
|
6
|
+
|
7
|
+
describe "#for_attribute" do
|
8
|
+
let(:column) { double 'column' }
|
9
|
+
let(:attr_name) { 'foo' }
|
10
|
+
let(:options) { {} }
|
11
|
+
|
12
|
+
def setup_stubs
|
13
|
+
allow(builder).to receive(:object).and_return(model)
|
14
|
+
allow(model).to receive(:column_for_attribute).with(attr_name).and_return(column)
|
15
|
+
allow(column).to receive(:type).and_return(column_type)
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { field_factory.for_attribute attr_name, options }
|
19
|
+
|
20
|
+
context "when given a horizontal form builder" do
|
21
|
+
let(:builder) { SimpleBootstrapForm::HorizontalForm::FormBuilder.new 'bogomodel', model, nil, {} }
|
22
|
+
|
23
|
+
context "for a text field" do
|
24
|
+
let(:column_type) { :string }
|
25
|
+
before { setup_stubs }
|
26
|
+
|
27
|
+
it { expect(subject).to be_a SimpleBootstrapForm::HorizontalForm::Fields::TextField }
|
28
|
+
|
29
|
+
context "when given an :as option" do
|
30
|
+
let(:options) { { as: :password } }
|
31
|
+
|
32
|
+
it "should override the default field type with the supplied one" do
|
33
|
+
expect(subject).to be_a SimpleBootstrapForm::HorizontalForm::Fields::PasswordField
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "whose name includes 'email'" do
|
38
|
+
let(:attr_name) { 'email' }
|
39
|
+
|
40
|
+
it { expect(subject).to be_a SimpleBootstrapForm::HorizontalForm::Fields::EmailField }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "whose name includes 'password'" do
|
44
|
+
let(:attr_name) { 'password' }
|
45
|
+
|
46
|
+
it { should be_a SimpleBootstrapForm::HorizontalForm::Fields::PasswordField }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "for a boolean field" do
|
51
|
+
let(:column_type) { :boolean }
|
52
|
+
before { setup_stubs }
|
53
|
+
|
54
|
+
it { expect(subject).to be_a SimpleBootstrapForm::HorizontalForm::Fields::BooleanField }
|
55
|
+
end
|
56
|
+
|
57
|
+
context "for a datetime field" do
|
58
|
+
let(:column_type) { :datetime }
|
59
|
+
before { setup_stubs }
|
60
|
+
|
61
|
+
it { expect(subject).to be_a SimpleBootstrapForm::HorizontalForm::Fields::DatetimeField }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|