bootstrap_forms 1.0.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +4 -0
  3. data/Guardfile +7 -0
  4. data/Rakefile +18 -1
  5. data/bootstrap_forms.gemspec +8 -1
  6. data/lib/bootstrap_forms.rb +9 -1
  7. data/lib/bootstrap_forms/engine.rb +12 -2
  8. data/lib/bootstrap_forms/form_builder.rb +28 -84
  9. data/lib/bootstrap_forms/helpers.rb +7 -0
  10. data/lib/bootstrap_forms/{initializer.rb → helpers/form_helper.rb} +7 -9
  11. data/lib/bootstrap_forms/helpers/form_tag_helper.rb +76 -0
  12. data/lib/bootstrap_forms/helpers/wrappers.rb +92 -0
  13. data/spec/dummy/Rakefile +7 -0
  14. data/spec/dummy/app/assets/javascripts/application.js +5 -0
  15. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  16. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  17. data/spec/dummy/app/controllers/projects_controller.rb +5 -0
  18. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  19. data/spec/dummy/app/helpers/projects_helper.rb +2 -0
  20. data/spec/dummy/app/mailers/.gitkeep +0 -0
  21. data/spec/dummy/app/models/.gitkeep +0 -0
  22. data/spec/dummy/app/models/milestone.rb +3 -0
  23. data/spec/dummy/app/models/project.rb +4 -0
  24. data/spec/dummy/app/models/task.rb +3 -0
  25. data/spec/dummy/app/views/layouts/application.html.erb +11 -0
  26. data/spec/dummy/app/views/projects/new.html.erb +4 -0
  27. data/spec/dummy/config.ru +4 -0
  28. data/spec/dummy/config/application.rb +42 -0
  29. data/spec/dummy/config/boot.rb +10 -0
  30. data/spec/dummy/config/database.yml +25 -0
  31. data/spec/dummy/config/environment.rb +5 -0
  32. data/spec/dummy/config/environments/development.rb +27 -0
  33. data/spec/dummy/config/environments/production.rb +54 -0
  34. data/spec/dummy/config/environments/test.rb +39 -0
  35. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  36. data/spec/dummy/config/initializers/inflections.rb +10 -0
  37. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  38. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  39. data/spec/dummy/config/initializers/session_store.rb +8 -0
  40. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  41. data/spec/dummy/config/locales/en.yml +5 -0
  42. data/spec/dummy/config/routes.rb +59 -0
  43. data/spec/dummy/db/development.sqlite3 +0 -0
  44. data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +23 -0
  45. data/spec/dummy/db/schema.rb +29 -0
  46. data/spec/dummy/db/test.sqlite3 +0 -0
  47. data/spec/dummy/log/development.log +0 -0
  48. data/spec/dummy/public/404.html +26 -0
  49. data/spec/dummy/public/422.html +26 -0
  50. data/spec/dummy/public/500.html +26 -0
  51. data/spec/dummy/public/favicon.ico +0 -0
  52. data/spec/dummy/script/rails +6 -0
  53. data/spec/dummy/test/functional/projects_controller_test.rb +7 -0
  54. data/spec/dummy/test/unit/helpers/projects_helper_test.rb +4 -0
  55. data/spec/dummy/tmp/cache/.gitkeep +0 -0
  56. data/spec/lib/bootstrap_forms/form_builder_spec.rb +180 -0
  57. data/spec/spec_helper.rb +20 -0
  58. metadata +198 -6
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ .DS_Store
6
+ .rspec
7
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ guard 'rspec', :version => 2 do
4
+ watch(%r{^spec/.+_spec\.rb$})
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch('spec/spec_helper.rb') { "spec" }
7
+ end
data/Rakefile CHANGED
@@ -1 +1,18 @@
1
- require 'bundler/gem_tasks'
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
10
+ # Put spec opts in a file named .rspec in root
11
+ end
12
+
13
+ desc "Generate code coverage"
14
+ RSpec::Core::RakeTask.new(:coverage) do |t|
15
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
16
+ t.rcov = true
17
+ t.rcov_opts = ['--exclude', 'spec']
18
+ end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "bootstrap_forms"
6
- s.version = "1.0.5"
6
+ s.version = "2.0.0"
7
7
  s.author = "Seth Vargo"
8
8
  s.email = "sethvargo@gmail.com"
9
9
  s.homepage = "https://github.com/sethvargo/bootstrap_forms"
@@ -14,4 +14,11 @@ Gem::Specification.new do |s|
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = ["lib"]
17
+
18
+ s.add_development_dependency "rspec-rails", "~> 2.9.0"
19
+ s.add_development_dependency "capybara", "~> 1.1.0"
20
+ s.add_development_dependency "rake"
21
+ s.add_development_dependency "rails", "~> 3.2.0"
22
+ s.add_development_dependency "guard-rspec"
23
+ s.add_development_dependency "sqlite3"
17
24
  end
@@ -1 +1,9 @@
1
- require 'bootstrap_forms/engine' if defined?(Rails)
1
+ # encoding: utf-8
2
+ require 'bootstrap_forms/engine' if defined?(::Rails)
3
+
4
+ module BootstrapForms
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :FormBuilder
8
+ autoload :Helpers
9
+ end
@@ -1,7 +1,17 @@
1
1
  module BootstrapForms
2
2
  class Engine < ::Rails::Engine
3
- config.after_initialize do |app|
4
- require 'bootstrap_forms/initializer'
3
+ initializer 'bootstrap_forms.initialize' do
4
+ config.to_prepare do
5
+ ActiveSupport.on_load(:action_view) do
6
+ include BootstrapForms::Helpers::FormHelper
7
+ include BootstrapForms::Helpers::FormTagHelper
8
+
9
+ # Do not wrap errors in the extra div
10
+ ::ActionView::Base.field_error_proc = Proc.new do |html_tag, instance_tag|
11
+ html_tag
12
+ end
13
+ end
14
+ end
5
15
  end
6
16
  end
7
17
  end
@@ -1,5 +1,7 @@
1
1
  module BootstrapForms
2
- class FormBuilder < ActionView::Helpers::FormBuilder
2
+ class FormBuilder < ::ActionView::Helpers::FormBuilder
3
+ include BootstrapForms::Helpers::Wrappers
4
+
3
5
  delegate :content_tag, :hidden_field_tag, :check_box_tag, :radio_button_tag, :button_tag, :link_to, :to => :@template
4
6
 
5
7
  def error_messages
@@ -17,7 +19,7 @@ module BootstrapForms
17
19
  end
18
20
  end
19
21
 
20
- %w(collection_select select email_field file_field number_field password_field phone_field range_field search_field telephone_field text_area text_field url_field).each do |method_name|
22
+ %w(collection_select select country_select time_zone_select email_field file_field number_field password_field phone_field range_field search_field telephone_field text_area text_field url_field).each do |method_name|
21
23
  define_method(method_name) do |name, *args|
22
24
  @name = name
23
25
  @field_options = args.extract_options!
@@ -39,16 +41,16 @@ module BootstrapForms
39
41
  control_group_div do
40
42
  input_div do
41
43
  label(@name, :class => [ 'checkbox', required_class ].compact.join(' ')) do
42
- extras { super(name, *(@args << @field_options)) + human_attribute_name }
44
+ extras { super(name, *(@args << @field_options)) + (@field_options[:label].blank? ? human_attribute_name : @field_options[:label])}
43
45
  end
44
46
  end
45
47
  end
46
48
  end
47
49
 
48
- def radio_buttons(name, values={}, opts={})
50
+ def radio_buttons(name, values = {}, opts = {})
49
51
  @name = name
50
52
  @options = opts
51
-
53
+ @field_options = opts
52
54
  control_group_div do
53
55
  label_field + input_div do
54
56
  values.map do |text, value|
@@ -91,7 +93,7 @@ module BootstrapForms
91
93
  content_tag(:div, :class => 'controls') do
92
94
  records.collect do |record|
93
95
  element_id = "#{object_name}_#{attribute}_#{record.send(record_id)}"
94
- radiobutton = radio_button_tag("#{object_name}[#{attribute}][]", record.send(record_id), object.send(attribute) == record.send(record_id), @field_options.merge({:id => element_id}))
96
+ radiobutton = radio_button_tag("#{object_name}[#{attribute}]", record.send(record_id), object.send(attribute) == record.send(record_id), @field_options.merge({:id => element_id}))
95
97
 
96
98
  content_tag(:label, :class => ['radio', ('inline' if @field_options[:inline])].compact.join(' ')) do
97
99
  radiobutton + content_tag(:span, record.send(record_name))
@@ -118,95 +120,37 @@ module BootstrapForms
118
120
  end
119
121
  end
120
122
 
121
- %w(submit button).each do |method_name|
122
- define_method(method_name) do |name=nil, *args|
123
- @name = name
124
- @field_options = args.extract_options!
125
- @args = args
126
-
127
- @field_options[:class] = 'btn btn-primary'
128
-
129
- content_tag(:div, :class => 'form-actions') do
130
- if @field_options[:include_cancel] == false
131
- super(name, *(args << @field_options))
132
- else
133
- super(name, *(args << @field_options)) + ' ' + link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
134
- end
135
- end
136
- end
137
- end
138
-
139
- private
140
- def control_group_div(&block)
141
- @field_options[:error] = error_string
142
-
143
- klasses = ['control-group']
144
- klasses << 'error' if @field_options[:error]
145
- klasses << 'success' if @field_options[:success]
146
- klasses << 'warning' if @field_options[:warning]
147
- klass = klasses.join(' ')
148
-
149
- content_tag(:div, :class => klass, &block)
150
- end
151
-
152
- def error_string
153
- errors = object.errors[@name]
154
- if errors.present?
155
- errors.map { |e|
156
- "#{@options[:label] || human_attribute_name} #{e}"
157
- }.join(", ")
158
- end
159
- end
123
+ def button(name = nil, *args)
124
+ @name = name
125
+ @field_options = args.extract_options!
126
+ @args = args
160
127
 
161
- def human_attribute_name
162
- object.class.human_attribute_name(@name)
128
+ @field_options[:class] = 'btn btn-primary'
129
+ super(name, *(args << @field_options))
163
130
  end
164
131
 
165
- def input_div(&block)
166
- content_tag(:div, :class => 'controls') do
167
- if @field_options[:append] || @field_options[:prepend]
168
- klass = 'input-prepend' if @field_options[:prepend]
169
- klass = 'input-append' if @field_options[:append]
170
- content_tag(:div, :class => klass, &block)
171
- else
172
- yield if block_given?
173
- end
174
- end
175
- end
132
+ def submit(name = nil, *args)
133
+ @name = name
134
+ @field_options = args.extract_options!
135
+ @args = args
176
136
 
177
- def label_field(&block)
178
- label(@name, block_given? ? block : @field_options[:label], :class => ['control-label', required_class].compact.join(' '))
137
+ @field_options[:class] = 'btn btn-primary'
138
+ super(name, *(args << @field_options))
179
139
  end
180
140
 
181
- def required_class
182
- return 'required' if object.class.validators_on(@name).any? { |v| v.kind_of? ActiveModel::Validations::PresenceValidator }
183
- nil
141
+ def cancel(*args)
142
+ @field_options = args.extract_options!
143
+ link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
184
144
  end
185
145
 
186
- %w(help_inline error success warning help_block append prepend).each do |method_name|
187
- define_method(method_name) do |*args|
188
- return '' unless value = @field_options[method_name.to_sym]
189
- case method_name
190
- when 'help_block'
191
- element = :p
192
- klass = 'help-block'
193
- when 'append', 'prepend'
194
- element = :span
195
- klass = 'add-on'
146
+ def actions(&block)
147
+ content_tag(:div, :class => 'form-actions') do
148
+ if block_given?
149
+ yield
196
150
  else
197
- element = :span
198
- klass = 'help-inline'
151
+ [submit, cancel].join(' ').html_safe
199
152
  end
200
- content_tag(element, value, :class => klass)
201
153
  end
202
154
  end
203
-
204
- def extras(&block)
205
- [prepend, (yield if block_given?), append, help_inline, error, success, warning, help_block].join('').html_safe
206
- end
207
-
208
- def objectify_options(options)
209
- super.except(:label, :help_inline, :error, :success, :warning, :help_block, :prepend, :append)
210
- end
211
155
  end
212
156
  end
@@ -0,0 +1,7 @@
1
+ module BootstrapForms
2
+ module Helpers
3
+ autoload :FormHelper, 'bootstrap_forms/helpers/form_helper'
4
+ autoload :FormTagHelper, 'bootstrap_forms/helpers/form_tag_helper'
5
+ autoload :Wrappers, 'bootstrap_forms/helpers/wrappers'
6
+ end
7
+ end
@@ -1,19 +1,17 @@
1
- require 'bootstrap_forms/form_builder'
2
-
3
- module ActionView
1
+ module BootstrapForms
4
2
  module Helpers
5
- module FormHelper
3
+ module FormHelper
6
4
  def bootstrap_form_for(record, options = {}, &block)
7
5
  options[:builder] = BootstrapForms::FormBuilder
8
6
  form_for(record, options) do |f|
9
7
  f.error_messages.html_safe + capture(f, &block).html_safe
10
8
  end
11
9
  end
10
+
11
+ def bootstrap_fields_for(record, options = {}, &block)
12
+ options[:builder] = BootstrapForms::FormBuilder
13
+ fields_for(record, nil, options, &block)
14
+ end
12
15
  end
13
16
  end
14
- end
15
-
16
- # don't wrap in those special divs
17
- ActionView::Base.field_error_proc = Proc.new do |html_tag, instance_tag|
18
- html_tag
19
17
  end
@@ -0,0 +1,76 @@
1
+ module BootstrapForms
2
+ module Helpers
3
+ module FormTagHelper
4
+ include BootstrapForms::Helpers::Wrappers
5
+
6
+ def bootstrap_form_tag(url_for_options = {}, options = {}, &block)
7
+ form_tag(url_for_options, options, &block)
8
+ end
9
+
10
+ %w(button_tag check_box_tag email_field_tag field_set_tag file_field_tag image_submit_tag label_tag number_field_tag password_field_tag phone_field_tag radio_button_tag range_field_tag search_field_tag select_tag telephone_field_tag text_area_tag text_field_tag url_field_tag utf8_enforcer_tag).each do |method_name|
11
+ # prefix each method with bootstrap_*
12
+ define_method("bootstrap_#{method_name}") do |name, *args|
13
+ value = args.shift
14
+ @name = name
15
+ @field_options = args.extract_options!
16
+ @args = args
17
+
18
+ control_group_div do
19
+ label_field + input_div do
20
+ extras { send(method_name.to_sym, name, value, *(@args << @field_options)) }
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def uneditable_input_tag(name, *args)
27
+ @name = name
28
+ @field_options = args.extract_options!
29
+ @args = args
30
+
31
+ control_group_div do
32
+ label_field + input_div do
33
+ extras do
34
+ content_tag(:span, :class => 'uneditable-input') do
35
+ @field_options[:value] || object.send(@name.to_sym)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def bootstrap_button_tag(name = nil, *args)
43
+ @name = name
44
+ @field_options = args.extract_options!
45
+ @args = args
46
+
47
+ @field_options[:class] = 'btn btn-primary'
48
+ button_tag(name, *(args << @field_options))
49
+ end
50
+
51
+ def bootstrap_submit_tag(name = nil, *args)
52
+ @name = name
53
+ @field_options = args.extract_options!
54
+ @args = args
55
+
56
+ @field_options[:class] = 'btn btn-primary'
57
+ submit_tag(name, *(args << @field_options))
58
+ end
59
+
60
+ def bootstrap_cancel_tag(*args)
61
+ @field_options = args.extract_options!
62
+ link_to(I18n.t('bootstrap_forms.buttons.cancel'), (@field_options[:back] || :back), :class => 'btn cancel')
63
+ end
64
+
65
+ def bootstrap_actions(&block)
66
+ content_tag(:div, :class => 'form-actions') do
67
+ if block_given?
68
+ yield
69
+ else
70
+ [bootstrap_submit_tag, bootstrap_cancel_tag].join(' ').html_safe
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,92 @@
1
+ module BootstrapForms
2
+ module Helpers
3
+ module Wrappers
4
+ private
5
+ def control_group_div(&block)
6
+ field_errors = error_string
7
+ if @field_options[:error]
8
+ (@field_options[:error] << ", " << field_errors) if field_errors
9
+ else
10
+ @field_options[:error] = field_errors
11
+ end
12
+
13
+ klasses = ['control-group']
14
+ klasses << 'error' if @field_options[:error]
15
+ klasses << 'success' if @field_options[:success]
16
+ klasses << 'warning' if @field_options[:warning]
17
+ klass = klasses.join(' ')
18
+
19
+ content_tag(:div, :class => klass, &block)
20
+ end
21
+
22
+ def error_string
23
+ if respond_to?(:object)
24
+ errors = object.errors[@name]
25
+ if errors.present?
26
+ errors.map { |e|
27
+ "#{@options[:label] || human_attribute_name} #{e}"
28
+ }.join(", ")
29
+ end
30
+ end
31
+ end
32
+
33
+ def human_attribute_name
34
+ object.class.human_attribute_name(@name)
35
+ end
36
+
37
+ def input_div(&block)
38
+ content_tag(:div, :class => 'controls') do
39
+ if @field_options[:append] || @field_options[:prepend]
40
+ klass = 'input-prepend' if @field_options[:prepend]
41
+ klass = 'input-append' if @field_options[:append]
42
+ content_tag(:div, :class => klass, &block)
43
+ else
44
+ yield if block_given?
45
+ end
46
+ end
47
+ end
48
+
49
+ def label_field(&block)
50
+ if respond_to?(:object)
51
+ label(@name, block_given? ? block : @field_options[:label], :class => ['control-label', required_class].compact.join(' '))
52
+ else
53
+ label_tag(@name, block_given? ? block : @field_options[:label], :class => ['control-label', required_class].compact.join(' '))
54
+ end
55
+ end
56
+
57
+ def required_class
58
+ return 'required' if @field_options[:required]
59
+ if respond_to?(:object)
60
+ return 'required' if object.class.validators_on(@name).any? { |v| v.kind_of? ActiveModel::Validations::PresenceValidator }
61
+ end
62
+ nil
63
+ end
64
+
65
+ %w(help_inline error success warning help_block append prepend).each do |method_name|
66
+ define_method(method_name) do |*args|
67
+ return '' unless value = @field_options[method_name.to_sym]
68
+ case method_name
69
+ when 'help_block'
70
+ element = :p
71
+ klass = 'help-block'
72
+ when 'append', 'prepend'
73
+ element = :span
74
+ klass = 'add-on'
75
+ else
76
+ element = :span
77
+ klass = 'help-inline'
78
+ end
79
+ content_tag(element, value, :class => klass)
80
+ end
81
+ end
82
+
83
+ def extras(&block)
84
+ [prepend, (yield if block_given?), append, help_inline, error, success, warning, help_block].join('').html_safe
85
+ end
86
+
87
+ def objectify_options(options)
88
+ super.except(:label, :help_inline, :error, :success, :warning, :help_block, :prepend, :append)
89
+ end
90
+ end
91
+ end
92
+ end