simple_form 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

data/.travis.yml CHANGED
@@ -4,3 +4,4 @@ rvm:
4
4
  - 1.9.2
5
5
  - ree
6
6
  - jruby
7
+ - rubinius
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,14 @@
1
+ == 1.4.1
2
+
3
+ * enhancements
4
+ * ignore required attribute when conditional validations are present
5
+
6
+ * bug fix
7
+ * Do not use required='required' when browser validations are turned off
8
+ * Sanitize HMTL attributes in error and hint helpers when options are present
9
+ * Improve i18n lookup by ignoring explicit child index given to form builder (tests by github.com/rywall)
10
+ * Fixes the form specific validation option if specified on the form itself (by github.com/medihack)
11
+
1
12
  == 1.4.0
2
13
 
3
14
  * enhancements
data/Gemfile CHANGED
@@ -4,5 +4,5 @@ gem "rails", "~> 3.0.7"
4
4
 
5
5
  group :test do
6
6
  gem "mocha", :require => false
7
- gem "ruby-debug", :require => false, :platform => :ruby_18
7
+ gem "ruby-debug", :require => false, :platform => :mri_18
8
8
  end
data/README.rdoc CHANGED
@@ -232,6 +232,16 @@ All web forms need buttons, right? SimpleForm wraps them in the DSL, acting like
232
232
 
233
233
  The above will simply call submit. You choose to use it or not, it's just a question of taste.
234
234
 
235
+ == Wrapping Rails Form Helpers
236
+
237
+ Say you wanted to use a rails form helper but still wrap it in SimpleForm goodness? You can, by calling input with a block like so:
238
+
239
+ <%= f.input :role do %>
240
+ <%= f.select :role, Role.all.map { |r| [r.name, r.id, { :class => r.company.id }] }, :include_blank => true %>
241
+ <% end %>
242
+
243
+ In the above example, we're taking advantage of Rails 3's select method that allows us to pass in a hash of additional attributes for each option.
244
+
235
245
  == Extra helpers
236
246
 
237
247
  SimpleForm also comes with some extra helpers you can use inside rails default forms without relying on simple_form_for helper. They are listed below.
@@ -275,6 +285,13 @@ Creates a collection of check boxes with labels associated (same API as collecti
275
285
  <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
276
286
  <label class="collection_check_box" for="user_options_false">No</label>
277
287
 
288
+ To use this with associations in your model, you can do the following:
289
+
290
+ form_for @user do |f|
291
+ f.collection_check_boxes :role_ids, Role.all, :id, :name # using :roles here is not going to work.
292
+ end
293
+
294
+
278
295
  == Mappings/Inputs available
279
296
 
280
297
  SimpleForm comes with a lot of default mappings:
@@ -308,9 +325,9 @@ SimpleForm comes with a lot of default mappings:
308
325
  It is very easy to add custom inputs to SimpleForm. For instance, if you want to add a custom input that extends the string one, you just need to add this file:
309
326
 
310
327
  # app/inputs/currency_input.rb
311
- class CurrencyInput < SimpleForm::Inputs::StringInput
328
+ class CurrencyInput < SimpleForm::Inputs::Base
312
329
  def input
313
- "$ #{super}".html_safe
330
+ "$ #{@builder.text_field(attribute_name, input_html_options)}".html_safe
314
331
  end
315
332
  end
316
333
 
@@ -425,6 +442,10 @@ If you want to have all other HTML 5 features, such as the new field types, you
425
442
 
426
443
  This option adds a new `novalidate` property to the form, instructing it to skip all HTML 5 validation. The inputs will still be generated with the required and other attributes, that might help you to use some generic javascript validation.
427
444
 
445
+ You can also add `novalidate` to a specific form by setting the option on the form itself:
446
+
447
+ <%= simple_form_for(resource, :html => {:novalidate => true}) do |form| %>
448
+
428
449
  Please notice that any of the configurations above will disable the `placeholder` component, which is an HTML 5 feature. We believe most of the newest browsers are handling this attribute fine, and if they aren't, any plugin you use would take of using the placeholder attribute to do it. However, you can disable it if you want, by removing the placeholder component from the components list in SimpleForm configuration file.
429
450
 
430
451
  == Configuration
@@ -43,10 +43,10 @@ SimpleForm.setup do |config|
43
43
  # You can wrap each item in a collection of radio/check boxes with a tag, defaulting to span.
44
44
  # config.item_wrapper_tag = :span
45
45
 
46
- # Series of attemps to detect a default label method for collection.
46
+ # Series of attempts to detect a default label method for collection.
47
47
  # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
48
48
 
49
- # Series of attemps to detect a default value method for collection.
49
+ # Series of attempts to detect a default value method for collection.
50
50
  # config.collection_value_methods = [ :id, :to_s ]
51
51
 
52
52
  # How the label text should be generated altogether with the required text.
@@ -40,7 +40,9 @@ module SimpleForm
40
40
  else dom_class(record_or_name_or_array)
41
41
  end
42
42
  options[:html] ||= {}
43
- options[:html][:novalidate] = !SimpleForm.browser_validations
43
+ unless options[:html].key?(:novalidate)
44
+ options[:html][:novalidate] = !SimpleForm.browser_validations
45
+ end
44
46
  options[:html][:class] = "\#{SimpleForm.form_class} \#{css_class} \#{options[:html][:class]}".strip
45
47
 
46
48
  with_custom_field_error_proc do
@@ -204,7 +204,7 @@ module SimpleForm
204
204
  # f.error :name, :id => "cool_error"
205
205
  #
206
206
  def error(attribute_name, options={})
207
- options[:error_html] = options.dup
207
+ options[:error_html] = options.except(:error_tag, :error_prefix, :error_method)
208
208
  column = find_attribute_column(attribute_name)
209
209
  input_type = default_input_type(attribute_name, column, options)
210
210
  SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options).error
@@ -238,7 +238,7 @@ module SimpleForm
238
238
  # f.hint "Don't forget to accept this"
239
239
  #
240
240
  def hint(attribute_name, options={})
241
- options[:hint_html] = options.dup
241
+ options[:hint_html] = options.except(:hint_tag)
242
242
  if attribute_name.is_a?(String)
243
243
  options[:hint] = attribute_name
244
244
  attribute_name, column, input_type = nil, nil, nil
@@ -66,7 +66,9 @@ module SimpleForm
66
66
  if !options[:required].nil?
67
67
  options[:required]
68
68
  elsif has_validators?
69
- (attribute_validators + reflection_validators).any? { |v| v.kind == :presence }
69
+ (attribute_validators + reflection_validators).any? do |v|
70
+ v.kind == :presence && !conditional_validators?(v)
71
+ end
70
72
  else
71
73
  attribute_required_by_default?
72
74
  end
@@ -74,7 +76,7 @@ module SimpleForm
74
76
 
75
77
  # Whether this input is valid for HTML 5 required attribute.
76
78
  def has_required?
77
- attribute_required? && SimpleForm.html5
79
+ attribute_required? && SimpleForm.html5 && SimpleForm.browser_validations
78
80
  end
79
81
 
80
82
  def has_autofocus?
@@ -93,6 +95,10 @@ module SimpleForm
93
95
  reflection ? object.class.validators_on(reflection.name) : []
94
96
  end
95
97
 
98
+ def conditional_validators?(validator)
99
+ validator.options.include?(:if) || validator.options.include?(:unless)
100
+ end
101
+
96
102
  def attribute_required_by_default?
97
103
  SimpleForm.required_by_default
98
104
  end
@@ -169,7 +175,8 @@ module SimpleForm
169
175
  I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups).presence
170
176
  end
171
177
 
172
- # Extract the model names from the object_name mess.
178
+ # Extract the model names from the object_name mess, ignoring numeric and
179
+ # explicit child indexes.
173
180
  #
174
181
  # Example:
175
182
  #
@@ -177,9 +184,10 @@ module SimpleForm
177
184
  # ["route", "blocks", "blocks_learning_object", "foo"]
178
185
  #
179
186
  def lookup_model_names
180
- object_name.to_s.scan(/([a-zA-Z_]+)/).flatten.map do |x|
181
- x.gsub('_attributes', '')
182
- end
187
+ child_index = @builder.options[:child_index]
188
+ names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
189
+ names.delete(child_index) if child_index
190
+ names.each { |name| name.gsub!('_attributes', '') }
183
191
  end
184
192
 
185
193
  # The action to be used in lookup.
@@ -1,3 +1,3 @@
1
1
  module SimpleForm
2
- VERSION = "1.4.0".freeze
2
+ VERSION = "1.4.1".freeze
3
3
  end
@@ -25,6 +25,18 @@ class FormHelperTest < ActionView::TestCase
25
25
  end
26
26
  end
27
27
 
28
+ test 'a form specific disabled validation option should override the default enabled browser validation configuration option' do
29
+ concat(simple_form_for(:user, :html => { :novalidate => true }) do |f| end)
30
+ assert_select 'form[novalidate="novalidate"]'
31
+ end
32
+
33
+ test 'a form specific enabled validation option should override the disabled browser validation configuration option' do
34
+ swap SimpleForm, :browser_validations => false do
35
+ concat(simple_form_for(:user, :html => { :novalidate => false }) do |f| end)
36
+ assert_no_select 'form[novalidate]'
37
+ end
38
+ end
39
+
28
40
  test 'simple form should add object name as css class to form when object is not present' do
29
41
  concat(simple_form_for(:user) do |f| end)
30
42
  assert_select 'form.simple_form.user'
@@ -133,6 +133,25 @@ class LabelTest < ActionView::TestCase
133
133
  end
134
134
  end
135
135
 
136
+ test 'label should do correct i18n lookup for nested has_many models with no nested translation' do
137
+ @user.tags = [Tag.new(1, 'Empresa')]
138
+
139
+ store_translations(:en, :simple_form => { :labels => {
140
+ :user => { :name => 'Usuario' },
141
+ :tags => { :name => 'Nome da empresa' }
142
+ } } ) do
143
+ with_concat_form_for @user do |f|
144
+ concat f.input :name
145
+ concat(f.simple_fields_for(:tags, :child_index => "new_index") do |tags_form|
146
+ concat(tags_form.input :name)
147
+ end)
148
+ end
149
+
150
+ assert_select 'label[for=user_name]', /Usuario/
151
+ assert_select 'label[for=user_tags_attributes_new_index_name]', /Nome da empresa/
152
+ end
153
+ end
154
+
136
155
  test 'label should have css class from type' do
137
156
  with_label_for @user, :name, :string
138
157
  assert_select 'label.string'
@@ -52,7 +52,7 @@ class FormBuilderTest < ActionView::TestCase
52
52
  end
53
53
 
54
54
  # All
55
- test 'nested simple fields should yields an instance of FormBuilder' do
55
+ test 'nested simple fields should yield an instance of FormBuilder' do
56
56
  simple_form_for :user do |f|
57
57
  f.simple_fields_for :posts do |posts_form|
58
58
  assert posts_form.instance_of?(SimpleForm::FormBuilder)
@@ -90,7 +90,7 @@ class FormBuilderTest < ActionView::TestCase
90
90
  end
91
91
  end
92
92
 
93
- test 'builder uses the first matching custom input map when more than one match' do
93
+ test 'builder uses the first matching custom input map when more than one matches' do
94
94
  swap SimpleForm, :input_mappings => { /count$/ => :integer, /^post_/ => :password } do
95
95
  with_form_for @user, :post_count
96
96
  assert_no_select 'form input#user_post_count.password'
@@ -338,6 +338,20 @@ class FormBuilderTest < ActionView::TestCase
338
338
  assert_select 'input.optional#user_name'
339
339
  end
340
340
 
341
+ test 'builder input should not be required when ActiveModel::Validations is included and if option is present' do
342
+ with_form_for @validating_user, :age
343
+ assert_no_select 'input.required'
344
+ assert_no_select 'input[required]'
345
+ assert_select 'input.optional#validating_user_age'
346
+ end
347
+
348
+ test 'builder input should not be required when ActiveModel::Validations is included and unless option is present' do
349
+ with_form_for @validating_user, :amount
350
+ assert_no_select 'input.required'
351
+ assert_no_select 'input[required]'
352
+ assert_select 'input.optional#validating_user_amount'
353
+ end
354
+
341
355
  # WRAPPERS
342
356
  test 'builder support wrapping around an specific tag' do
343
357
  swap SimpleForm, :wrapper_tag => :p do
@@ -456,6 +470,14 @@ class FormBuilderTest < ActionView::TestCase
456
470
  assert_no_select 'span.error[error_html]'
457
471
  end
458
472
 
473
+ test 'builder should generate an error tag with a clean HTML when errors options are present' do
474
+ with_error_for @user, :name, :error_tag => :p, :error_prefix => 'Name', :error_method => :first
475
+ assert_no_select 'p.error[error_html]'
476
+ assert_no_select 'p.error[error_tag]'
477
+ assert_no_select 'p.error[error_prefix]'
478
+ assert_no_select 'p.error[error_method]'
479
+ end
480
+
459
481
  test 'builder should allow passing options to error tag' do
460
482
  with_error_for @user, :name, :id => 'name_error'
461
483
  assert_select 'span.error#name_error', "can't be blank"
@@ -501,6 +523,13 @@ class FormBuilderTest < ActionView::TestCase
501
523
  assert_no_select 'span.hint[hint_html]'
502
524
  end
503
525
 
526
+ test 'builder should generate a hint componet tag with a clean HTML when hint_tag option is present' do
527
+ with_hint_for @user, 'Hello World!', :hint_tag => :p
528
+ assert_no_select 'p.hint[hint]'
529
+ assert_no_select 'p.hint[hint_html]'
530
+ assert_no_select 'p.hint[hint_tag]'
531
+ end
532
+
504
533
  test 'builder should allow passing options to hint tag' do
505
534
  with_hint_for @user, :name, :hint => 'Hello World!', :id => 'name_hint'
506
535
  assert_select 'span.hint#name_hint', 'Hello World!'
@@ -559,7 +588,7 @@ class FormBuilderTest < ActionView::TestCase
559
588
  end
560
589
  end
561
590
 
562
- test 'builder association with a block call simple_fields_for' do
591
+ test 'builder association with a block calls simple_fields_for' do
563
592
  simple_form_for @user do |f|
564
593
  f.association :posts do |posts_form|
565
594
  assert posts_form.instance_of?(SimpleForm::FormBuilder)
@@ -578,7 +607,7 @@ class FormBuilderTest < ActionView::TestCase
578
607
  assert_equal 3, calls
579
608
  end
580
609
 
581
- test 'builder association mark input as required based both association and attribute' do
610
+ test 'builder association marks input as required based on both association and attribute' do
582
611
  swap SimpleForm, :required_by_default => false do
583
612
  with_association_for @validating_user, :company, :collection => []
584
613
  assert_select 'label.required'
@@ -595,7 +624,7 @@ class FormBuilderTest < ActionView::TestCase
595
624
  assert_select 'form select option[value=3]', 'Tag 3'
596
625
  end
597
626
 
598
- test 'builder does not preload collection association if preload false' do
627
+ test 'builder does not preload collection association if preload is false' do
599
628
  value = @user.company
600
629
  value.expects(:to_a).never
601
630
  with_association_for @user, :company, :preload => false
@@ -605,7 +634,7 @@ class FormBuilderTest < ActionView::TestCase
605
634
  assert_select 'form select option[value=3]', 'Company 3'
606
635
  end
607
636
 
608
- test 'builder does not preload non collection association' do
637
+ test 'builder does not preload non-collection association' do
609
638
  value = @user.company
610
639
  value.expects(:to_a).never
611
640
  with_association_for @user, :company, :preload => false
data/test/inputs_test.rb CHANGED
@@ -780,6 +780,14 @@ class InputTest < ActionView::TestCase
780
780
  end
781
781
  end
782
782
 
783
+ test 'when not using browser validations, input should not generate required html attribute' do
784
+ swap SimpleForm, :browser_validations => false do
785
+ with_input_for @user, :name, :string
786
+ assert_select 'input[type=text].required'
787
+ assert_no_select 'input[type=text][required]'
788
+ end
789
+ end
790
+
783
791
  test 'collection input with select type should not generate invalid required html attribute' do
784
792
  with_input_for @user, :name, :select, :collection => ['Jose' , 'Carlos']
785
793
  assert_select 'select.required'
@@ -61,6 +61,9 @@ class User
61
61
  def company_attributes=(*)
62
62
  end
63
63
 
64
+ def tags_attributes=(*)
65
+ end
66
+
64
67
  def column_for_attribute(attribute)
65
68
  column_type, limit = case attribute.to_sym
66
69
  when :name, :status, :password then [:string, 100]
@@ -124,6 +127,8 @@ class ValidatingUser < User
124
127
  include ActiveModel::Validations
125
128
  validates :name, :presence => true
126
129
  validates :company, :presence => true
130
+ validates :age, :presence => true, :if => Proc.new { |user| user.name }
131
+ validates :amount, :presence => true, :unless => Proc.new { |user| user.age }
127
132
  validates_numericality_of :age,
128
133
  :greater_than_or_equal_to => 18,
129
134
  :less_than_or_equal_to => 99,
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_form
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 4
9
- - 0
10
- version: 1.4.0
9
+ - 1
10
+ version: 1.4.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Jos\xC3\xA9 Valim"
@@ -16,8 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-05-18 00:00:00 -03:00
20
- default_executable:
19
+ date: 2011-06-14 00:00:00 Z
21
20
  dependencies: []
22
21
 
23
22
  description: Forms made easy!
@@ -90,7 +89,6 @@ files:
90
89
  - test/support/mock_response.rb
91
90
  - test/support/models.rb
92
91
  - test/test_helper.rb
93
- has_rdoc: true
94
92
  homepage: http://github.com/plataformatec/simple_form
95
93
  licenses: []
96
94
 
@@ -120,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
118
  requirements: []
121
119
 
122
120
  rubyforge_project: simple_form
123
- rubygems_version: 1.6.2
121
+ rubygems_version: 1.8.5
124
122
  signing_key:
125
123
  specification_version: 3
126
124
  summary: Forms made easy!