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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Gemfile +9 -0
  4. data/Guardfile +9 -0
  5. data/README.md +84 -1
  6. data/Rakefile +9 -0
  7. data/circle.yml +5 -0
  8. data/lib/simple_bootstrap_form/action_view_extensions.rb +5 -5
  9. data/lib/simple_bootstrap_form/css_class_list.rb +1 -1
  10. data/lib/simple_bootstrap_form/field_factory.rb +58 -0
  11. data/lib/simple_bootstrap_form/horizontal_form/fields/base_field.rb +118 -0
  12. data/lib/simple_bootstrap_form/horizontal_form/fields/boolean_field.rb +16 -0
  13. data/lib/simple_bootstrap_form/horizontal_form/fields/datetime_field.rb +55 -0
  14. data/lib/simple_bootstrap_form/horizontal_form/fields/email_field.rb +10 -0
  15. data/lib/simple_bootstrap_form/horizontal_form/fields/password_field.rb +10 -0
  16. data/lib/simple_bootstrap_form/horizontal_form/fields/text_field.rb +10 -0
  17. data/lib/simple_bootstrap_form/horizontal_form/fields/textarea_field.rb +14 -0
  18. data/lib/simple_bootstrap_form/horizontal_form/form_builder.rb +59 -0
  19. data/lib/simple_bootstrap_form/version.rb +1 -1
  20. data/lib/simple_bootstrap_form.rb +9 -8
  21. data/simple_bootstrap_form.gemspec +1 -1
  22. data/spec/field_factory_spec.rb +65 -0
  23. data/spec/simple_bootstrap_form_spec.rb +360 -83
  24. data/spec/spec_helper.rb +3 -0
  25. data/spec/support/have_element.rb +109 -0
  26. metadata +19 -13
  27. data/lib/simple_bootstrap_form/fields/base_field.rb +0 -103
  28. data/lib/simple_bootstrap_form/fields/boolean_field.rb +0 -14
  29. data/lib/simple_bootstrap_form/fields/datetime_field.rb +0 -53
  30. data/lib/simple_bootstrap_form/fields/email_field.rb +0 -8
  31. data/lib/simple_bootstrap_form/fields/password_field.rb +0 -8
  32. data/lib/simple_bootstrap_form/fields/text_field.rb +0 -8
  33. data/lib/simple_bootstrap_form/fields/textarea_field.rb +0 -12
  34. data/lib/simple_bootstrap_form/form_builder.rb +0 -51
  35. data/spec/support/input_matchers.rb +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 27c4585ebe1f844686694e3d88cd045fe7b4c007
4
- data.tar.gz: a3f97b39f979917a0d140ab729bd6a5b036ebac8
3
+ metadata.gz: 49612ff415db9c67ef7d7fddec5ce1628a89bd56
4
+ data.tar.gz: f44b2d057f9fb6c315271314a119245dab29f9d1
5
5
  SHA512:
6
- metadata.gz: f02db029971faa1f602dfe08e2fd827c13da0beea257df0ff7824087454835513facd78b393d246f53e65d475e2ffef7759f877992f24bd40b7537e6ce8d4c45
7
- data.tar.gz: 1846b4a9972a30d0223e32ee685683ae56deb285e74eab3bfe0107f9a772efdd2f5eb6d87515f2bf43e2739fe1b3c97dd0fdd680b0c07e805fbcc2acd56e08c1
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
- imlementation. I believe the continued non-appearance of Simple Form Bootstrap
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
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ task :console do
4
+ require 'irb'
5
+ require 'irb/completion'
6
+ require File.expand_path("spec/dummy/config/environment")
7
+ require 'simple_bootstrap_form'
8
+ ARGV.clear
9
+ IRB.start
10
+ end
data/circle.yml ADDED
@@ -0,0 +1,5 @@
1
+ database:
2
+ override:
3
+ - cd spec/dummy ; bundle exec rake db:create --trace
4
+ - cd spec/dummy ; bundle exec rake db:migrate --trace
5
+ - cd spec/dummy ; bundle exec rake db:test:prepare --trace
@@ -2,11 +2,7 @@ module SimpleBootstrapForm
2
2
  module ActionViewExtensions
3
3
 
4
4
  def bootstrap_form_for(record, options={}, &block)
5
- options[:builder] ||= SimpleBootstrapForm::FormBuilder
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
@@ -12,7 +12,7 @@ module SimpleBootstrapForm
12
12
  end
13
13
 
14
14
  def to_s
15
- join ' '
15
+ sort.join ' '
16
16
  end
17
17
 
18
18
  private
@@ -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,10 @@
1
+ module SimpleBootstrapForm
2
+ module HorizontalForm
3
+ module Fields
4
+ class EmailField < BaseField
5
+
6
+ self.type = 'email'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module SimpleBootstrapForm
2
+ module HorizontalForm
3
+ module Fields
4
+ class PasswordField < BaseField
5
+
6
+ self.type = 'password'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module SimpleBootstrapForm
2
+ module HorizontalForm
3
+ module Fields
4
+ class TextField < BaseField
5
+
6
+ self.type = 'text'
7
+ end
8
+ end
9
+ end
10
+ 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,3 +1,3 @@
1
1
  module SimpleBootstrapForm
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  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/form_builder'
5
- require 'simple_bootstrap_form/fields/base_field'
6
- require 'simple_bootstrap_form/fields/boolean_field'
7
- require 'simple_bootstrap_form/fields/datetime_field'
8
- require 'simple_bootstrap_form/fields/email_field'
9
- require 'simple_bootstrap_form/fields/password_field'
10
- require 'simple_bootstrap_form/fields/text_field'
11
- require 'simple_bootstrap_form/fields/textarea_field'
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 "capybara" # for has_selector? method
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