simple-form-3.2.0/ 0000755 0001750 0001750 00000000000 12623141213 014153 5 ustar terceiro terceiro simple-form-3.2.0/MIT-LICENSE 0000644 0001750 0001750 00000002103 12623141213 015603 0 ustar terceiro terceiro Copyright (c) 2009-2015 Plataformatec http://plataformatec.com.br/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
simple-form-3.2.0/metadata.yml 0000644 0001750 0001750 00000015514 12623141213 016464 0 ustar terceiro terceiro --- !ruby/object:Gem::Specification
name: simple_form
version: !ruby/object:Gem::Version
version: 3.2.0
platform: ruby
authors:
- José Valim
- Carlos Antônio
- Rafael França
autorequire:
bindir: bin
cert_chain: []
date: 2015-09-22 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: activemodel
requirement: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '4.0'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '4.0'
- !ruby/object:Gem::Dependency
name: actionpack
requirement: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '4.0'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '4.0'
description: Forms made easy!
email: opensource@plataformatec.com.br
executables: []
extensions: []
extra_rdoc_files: []
files:
- CHANGELOG.md
- MIT-LICENSE
- README.md
- lib/generators/simple_form/install_generator.rb
- lib/generators/simple_form/templates/_form.html.erb
- lib/generators/simple_form/templates/_form.html.haml
- lib/generators/simple_form/templates/_form.html.slim
- lib/generators/simple_form/templates/config/initializers/simple_form.rb
- lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb
- lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb
- lib/generators/simple_form/templates/config/locales/simple_form.en.yml
- lib/generators/simple_form/templates/README
- lib/generators/simple_form/USAGE
- lib/simple_form/action_view_extensions/builder.rb
- lib/simple_form/action_view_extensions/form_helper.rb
- lib/simple_form/components/errors.rb
- lib/simple_form/components/hints.rb
- lib/simple_form/components/html5.rb
- lib/simple_form/components/label_input.rb
- lib/simple_form/components/labels.rb
- lib/simple_form/components/maxlength.rb
- lib/simple_form/components/min_max.rb
- lib/simple_form/components/pattern.rb
- lib/simple_form/components/placeholders.rb
- lib/simple_form/components/readonly.rb
- lib/simple_form/components.rb
- lib/simple_form/error_notification.rb
- lib/simple_form/form_builder.rb
- lib/simple_form/helpers/autofocus.rb
- lib/simple_form/helpers/disabled.rb
- lib/simple_form/helpers/readonly.rb
- lib/simple_form/helpers/required.rb
- lib/simple_form/helpers/validators.rb
- lib/simple_form/helpers.rb
- lib/simple_form/i18n_cache.rb
- lib/simple_form/inputs/base.rb
- lib/simple_form/inputs/block_input.rb
- lib/simple_form/inputs/boolean_input.rb
- lib/simple_form/inputs/collection_check_boxes_input.rb
- lib/simple_form/inputs/collection_input.rb
- lib/simple_form/inputs/collection_radio_buttons_input.rb
- lib/simple_form/inputs/collection_select_input.rb
- lib/simple_form/inputs/date_time_input.rb
- lib/simple_form/inputs/file_input.rb
- lib/simple_form/inputs/grouped_collection_select_input.rb
- lib/simple_form/inputs/hidden_input.rb
- lib/simple_form/inputs/numeric_input.rb
- lib/simple_form/inputs/password_input.rb
- lib/simple_form/inputs/priority_input.rb
- lib/simple_form/inputs/range_input.rb
- lib/simple_form/inputs/string_input.rb
- lib/simple_form/inputs/text_input.rb
- lib/simple_form/inputs.rb
- lib/simple_form/map_type.rb
- lib/simple_form/railtie.rb
- lib/simple_form/tags.rb
- lib/simple_form/version.rb
- lib/simple_form/wrappers/builder.rb
- lib/simple_form/wrappers/leaf.rb
- lib/simple_form/wrappers/many.rb
- lib/simple_form/wrappers/root.rb
- lib/simple_form/wrappers/single.rb
- lib/simple_form/wrappers.rb
- lib/simple_form.rb
- test/action_view_extensions/builder_test.rb
- test/action_view_extensions/form_helper_test.rb
- test/components/label_test.rb
- test/form_builder/association_test.rb
- test/form_builder/button_test.rb
- test/form_builder/error_notification_test.rb
- test/form_builder/error_test.rb
- test/form_builder/general_test.rb
- test/form_builder/hint_test.rb
- test/form_builder/input_field_test.rb
- test/form_builder/label_test.rb
- test/form_builder/wrapper_test.rb
- test/generators/simple_form_generator_test.rb
- test/inputs/boolean_input_test.rb
- test/inputs/collection_check_boxes_input_test.rb
- test/inputs/collection_radio_buttons_input_test.rb
- test/inputs/collection_select_input_test.rb
- test/inputs/datetime_input_test.rb
- test/inputs/disabled_test.rb
- test/inputs/discovery_test.rb
- test/inputs/file_input_test.rb
- test/inputs/general_test.rb
- test/inputs/grouped_collection_select_input_test.rb
- test/inputs/hidden_input_test.rb
- test/inputs/numeric_input_test.rb
- test/inputs/priority_input_test.rb
- test/inputs/readonly_test.rb
- test/inputs/required_test.rb
- test/inputs/string_input_test.rb
- test/inputs/text_input_test.rb
- test/simple_form_test.rb
- test/support/discovery_inputs.rb
- test/support/misc_helpers.rb
- test/support/mock_controller.rb
- test/support/models.rb
- test/test_helper.rb
homepage: https://github.com/plataformatec/simple_form
licenses:
- MIT
metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: '0'
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - '>='
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project: simple_form
rubygems_version: 2.0.3
signing_key:
specification_version: 4
summary: Forms made easy!
test_files:
- test/action_view_extensions/builder_test.rb
- test/action_view_extensions/form_helper_test.rb
- test/components/label_test.rb
- test/form_builder/association_test.rb
- test/form_builder/button_test.rb
- test/form_builder/error_notification_test.rb
- test/form_builder/error_test.rb
- test/form_builder/general_test.rb
- test/form_builder/hint_test.rb
- test/form_builder/input_field_test.rb
- test/form_builder/label_test.rb
- test/form_builder/wrapper_test.rb
- test/generators/simple_form_generator_test.rb
- test/inputs/boolean_input_test.rb
- test/inputs/collection_check_boxes_input_test.rb
- test/inputs/collection_radio_buttons_input_test.rb
- test/inputs/collection_select_input_test.rb
- test/inputs/datetime_input_test.rb
- test/inputs/disabled_test.rb
- test/inputs/discovery_test.rb
- test/inputs/file_input_test.rb
- test/inputs/general_test.rb
- test/inputs/grouped_collection_select_input_test.rb
- test/inputs/hidden_input_test.rb
- test/inputs/numeric_input_test.rb
- test/inputs/priority_input_test.rb
- test/inputs/readonly_test.rb
- test/inputs/required_test.rb
- test/inputs/string_input_test.rb
- test/inputs/text_input_test.rb
- test/simple_form_test.rb
- test/support/discovery_inputs.rb
- test/support/misc_helpers.rb
- test/support/mock_controller.rb
- test/support/models.rb
- test/test_helper.rb
simple-form-3.2.0/test/ 0000755 0001750 0001750 00000000000 12623141213 015132 5 ustar terceiro terceiro simple-form-3.2.0/test/test_helper.rb 0000644 0001750 0001750 00000003545 12623141213 020004 0 ustar terceiro terceiro require 'bundler/setup'
require 'minitest/autorun'
require 'active_model'
require 'action_controller'
require 'action_view'
ActionView::RoutingUrlFor.send(:include, ActionDispatch::Routing::UrlFor)
require 'action_view/template'
require 'action_view/test_case'
module Rails
def self.env
ActiveSupport::StringInquirer.new("test")
end
end
$:.unshift File.expand_path("../../lib", __FILE__)
require 'simple_form'
require "rails/generators/test_case"
require 'generators/simple_form/install_generator'
Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file|
require file unless file.end_with?('discovery_inputs.rb')
end
I18n.default_locale = :en
require 'country_select'
if defined?(HTMLSelector::NO_STRIP)
HTMLSelector::NO_STRIP << "label"
else
ActionDispatch::Assertions::NO_STRIP << "label"
end
if ActiveSupport::TestCase.respond_to?(:test_order=)
ActiveSupport::TestCase.test_order = :random
end
class ActionView::TestCase
include MiscHelpers
include SimpleForm::ActionViewExtensions::FormHelper
setup :set_controller
setup :setup_users
def set_controller
@controller = MockController.new
end
def setup_users(extra_attributes = {})
@user = User.build(extra_attributes)
@validating_user = ValidatingUser.build({
home_picture: 'Home picture',
age: 19,
amount: 15,
attempts: 1,
company: [1]
}.merge!(extra_attributes))
@other_validating_user = OtherValidatingUser.build({
age: 19,
company: 1
}.merge!(extra_attributes))
end
def protect_against_forgery?
false
end
def user_path(*args)
'/users'
end
def company_user_path(*args)
'/company/users'
end
alias :users_path :user_path
alias :super_user_path :user_path
alias :validating_user_path :user_path
alias :validating_users_path :user_path
alias :other_validating_user_path :user_path
end
simple-form-3.2.0/test/action_view_extensions/ 0000755 0001750 0001750 00000000000 12623141213 021720 5 ustar terceiro terceiro simple-form-3.2.0/test/action_view_extensions/form_helper_test.rb 0000644 0001750 0001750 00000012610 12623141213 025606 0 ustar terceiro terceiro require 'test_helper'
class FormHelperTest < ActionView::TestCase
test 'SimpleForm for yields an instance of FormBuilder' do
simple_form_for :user do |f|
assert f.instance_of?(SimpleForm::FormBuilder)
end
end
test 'SimpleForm adds default class to form' do
with_concat_form_for(:user)
assert_select 'form.simple_form'
end
test 'SimpleForm allows overriding default form class' do
swap SimpleForm, default_form_class: "my_custom_class" do
with_concat_form_for :user, html: { class: "override_class" }
assert_no_select 'form.my_custom_class'
assert_select 'form.override_class'
end
end
# Remove this test when SimpleForm.form_class is removed in 4.x
test 'SimpleForm allows overriding default form class, but not form class' do
ActiveSupport::Deprecation.silence do
swap SimpleForm, form_class: "fixed_class", default_form_class: "my_custom_class" do
with_concat_form_for :user, html: { class: "override_class" }
assert_no_select 'form.my_custom_class'
assert_select 'form.fixed_class.override_class'
end
end
end
test 'SimpleForm uses default browser validations by default' do
with_concat_form_for(:user)
assert_no_select 'form[novalidate]'
end
test 'SimpleForm does not use default browser validations if specified in the configuration options' do
swap SimpleForm, browser_validations: false do
with_concat_form_for(:user)
assert_select 'form[novalidate="novalidate"]'
end
end
test 'disabled browser validations overrides default configuration' do
with_concat_form_for(:user, html: { novalidate: true })
assert_select 'form[novalidate="novalidate"]'
end
test 'enabled browser validations overrides disabled configuration' do
swap SimpleForm, browser_validations: false do
with_concat_form_for(:user, html: { novalidate: false })
assert_no_select 'form[novalidate]'
end
end
test 'SimpleForm adds object name as css class to form when object is not present' do
with_concat_form_for(:user, html: { novalidate: true })
assert_select 'form.simple_form.user'
end
test 'SimpleForm adds :as option as css class to form when object is not present' do
with_concat_form_for(:user, as: 'superuser')
assert_select 'form.simple_form.superuser'
end
test 'SimpleForm adds object class name with new prefix as css class to form if record is not persisted' do
@user.new_record!
with_concat_form_for(@user)
assert_select 'form.simple_form.new_user'
end
test 'SimpleForm adds :as option with new prefix as css class to form if record is not persisted' do
@user.new_record!
with_concat_form_for(@user, as: 'superuser')
assert_select 'form.simple_form.new_superuser'
end
test 'SimpleForm adds edit class prefix as css class to form if record is persisted' do
with_concat_form_for(@user)
assert_select 'form.simple_form.edit_user'
end
test 'SimpleForm adds :as options with edit prefix as css class to form if record is persisted' do
with_concat_form_for(@user, as: 'superuser')
assert_select 'form.simple_form.edit_superuser'
end
test 'SimpleForm adds last object name as css class to form when there is array of objects' do
with_concat_form_for([Company.new, @user])
assert_select 'form.simple_form.edit_user'
end
test 'SimpleForm does not add object class to form if css_class is specified' do
with_concat_form_for(:user, html: { class: nil })
assert_no_select 'form.user'
end
test 'SimpleForm adds custom class to form if css_class is specified' do
with_concat_form_for(:user, html: { class: 'my_class' })
assert_select 'form.my_class'
end
test 'passes options to SimpleForm' do
with_concat_form_for(:user, url: '/account', html: { id: 'my_form' })
assert_select 'form#my_form'
assert_select 'form[action="/account"]'
end
test 'form_for yields an instance of FormBuilder' do
with_concat_form_for(:user) do |f|
assert f.instance_of?(SimpleForm::FormBuilder)
end
end
test 'fields_for with a hash like model yields an instance of FormBuilder' do
with_concat_fields_for(:author, HashBackedAuthor.new) do |f|
assert f.instance_of?(SimpleForm::FormBuilder)
f.input :name
end
assert_select "input[name='author[name]'][value='hash backed author']"
end
test 'custom error proc is not destructive' do
swap_field_error_proc do
result = nil
simple_form_for :user do |f|
result = simple_fields_for 'address' do
'hello'
end
end
assert_equal 'hello', result
end
end
test 'custom error proc survives an exception' do
swap_field_error_proc do
begin
simple_form_for :user do |f|
simple_fields_for 'address' do
raise 'an exception'
end
end
rescue StandardError
end
end
end
test 'SimpleForm for swaps default action view field_error_proc' do
expected_error_proc = lambda {}
swap SimpleForm, field_error_proc: expected_error_proc do
simple_form_for :user do |f|
assert_equal expected_error_proc, ::ActionView::Base.field_error_proc
end
end
end
private
def swap_field_error_proc(expected_error_proc = lambda {})
swap ActionView::Base, field_error_proc: expected_error_proc do
yield
assert_equal expected_error_proc, ActionView::Base.field_error_proc
end
end
end
simple-form-3.2.0/test/action_view_extensions/builder_test.rb 0000644 0001750 0001750 00000063014 12623141213 024736 0 ustar terceiro terceiro require 'test_helper'
class BuilderTest < ActionView::TestCase
def with_custom_form_for(object, *args, &block)
with_concat_custom_form_for(object) do |f|
assert f.instance_of?(CustomFormBuilder)
yield f
end
end
def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block)
with_concat_form_for(object) do |f|
f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block
end
end
def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block)
with_concat_form_for(object) do |f|
f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block
end
end
# COLLECTION RADIO
test "collection radio accepts a collection and generate inputs from value method" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=radio][value=true]#user_active_true'
assert_select 'form input[type=radio][value=false]#user_active_false'
end
test "collection radio accepts a collection and generate inputs from label method" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
assert_select 'form label.collection_radio_buttons[for=user_active_true]', 'true'
assert_select 'form label.collection_radio_buttons[for=user_active_false]', 'false'
end
test "collection radio handles camelized collection values for labels correctly" do
with_collection_radio_buttons @user, :active, ['Yes', 'No'], :to_s, :to_s
assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
end
test "collection radio sanitizes collection values for labels correctly" do
with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
end
test "collection radio checks the correct value to local variables" do
user = User.build(active: false)
with_collection_radio_buttons user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=radio][value=true]'
assert_select 'form input[type=radio][value=false][checked=checked]'
end
test "collection radio accepts checked item" do
with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, checked: true
assert_select 'form input[type=radio][value=true][checked=checked]'
assert_no_select 'form input[type=radio][value=false][checked=checked]'
end
test "collection radio accepts checked item which has a value of false" do
with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, checked: false
assert_no_select 'form input[type=radio][value=true][checked=checked]'
assert_select 'form input[type=radio][value=false][checked=checked]'
end
test "collection radio accepts multiple disabled items" do
collection = [[1, true], [0, false], [2, 'other']]
with_collection_radio_buttons @user, :active, collection, :last, :first, disabled: [true, false]
assert_select 'form input[type=radio][value=true][disabled=disabled]'
assert_select 'form input[type=radio][value=false][disabled=disabled]'
assert_no_select 'form input[type=radio][value=other][disabled=disabled]'
end
test "collection radio accepts single disable item" do
collection = [[1, true], [0, false]]
with_collection_radio_buttons @user, :active, collection, :last, :first, disabled: true
assert_select 'form input[type=radio][value=true][disabled=disabled]'
assert_no_select 'form input[type=radio][value=false][disabled=disabled]'
end
test "collection radio accepts html options as input" do
collection = [[1, true], [0, false]]
with_collection_radio_buttons @user, :active, collection, :last, :first, {}, class: 'special-radio'
assert_select 'form input[type=radio][value=true].special-radio#user_active_true'
assert_select 'form input[type=radio][value=false].special-radio#user_active_false'
end
test "collection radio wraps the collection in the given collection wrapper tag" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: :ul
assert_select 'form ul input[type=radio]', count: 2
end
test "collection radio does not render any wrapper tag by default" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
end
test "collection radio does not wrap the collection when given falsy values" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: false
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
end
test "collection radio uses the given class for collection wrapper tag" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
collection_wrapper_tag: :ul, collection_wrapper_class: "items-list"
assert_select 'form ul.items-list input[type=radio]', count: 2
end
test "collection radio uses no class for collection wrapper tag when no wrapper tag is given" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
collection_wrapper_class: "items-list"
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
assert_no_select '.items-list'
end
test "collection radio uses no class for collection wrapper tag by default" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: :ul
assert_select 'form ul'
assert_no_select 'form ul[class]'
end
test "collection radio wrap items in a span tag by default" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
assert_select 'form span input[type=radio][value=true]#user_active_true + label'
assert_select 'form span input[type=radio][value=false]#user_active_false + label'
end
test "collection radio wraps each item in the given item wrapper tag" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, item_wrapper_tag: :li
assert_select 'form li input[type=radio]', count: 2
end
test "collection radio does not wrap each item when given explicitly falsy value" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, item_wrapper_tag: false
assert_select 'form input[type=radio]'
assert_no_select 'form span input[type=radio]'
end
test "collection radio uses the given class for item wrapper tag" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: :li, item_wrapper_class: "inline"
assert_select "form li.inline input[type=radio]", count: 2
end
test "collection radio uses no class for item wrapper tag when no wrapper tag is given" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: nil, item_wrapper_class: "inline"
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form li'
assert_no_select '.inline'
end
test "collection radio uses no class for item wrapper tag by default" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: :li
assert_select "form li", count: 2
assert_no_select "form li[class]"
end
test "collection radio does not wrap input inside the label" do
with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=radio] + label'
assert_no_select 'form label input'
end
test "collection radio accepts a block to render the label as radio button wrapper" do
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
b.label { b.radio_button }
end
assert_select 'label[for=user_active_true] > input#user_active_true[type=radio]'
assert_select 'label[for=user_active_false] > input#user_active_false[type=radio]'
end
test "collection radio accepts a block to change the order of label and radio button" do
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
b.label + b.radio_button
end
assert_select 'label[for=user_active_true] + input#user_active_true[type=radio]'
assert_select 'label[for=user_active_false] + input#user_active_false[type=radio]'
end
test "collection radio with block helpers accept extra html options" do
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
b.label(class: "radio_button") + b.radio_button(class: "radio_button")
end
assert_select 'label.radio_button[for=user_active_true] + input#user_active_true.radio_button[type=radio]'
assert_select 'label.radio_button[for=user_active_false] + input#user_active_false.radio_button[type=radio]'
end
test "collection radio with block helpers allows access to current text and value" do
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
b.label(:"data-value" => b.value) { b.radio_button + b.text }
end
assert_select 'label[for=user_active_true][data-value=true]', 'true' do
assert_select 'input#user_active_true[type=radio]'
end
assert_select 'label[for=user_active_false][data-value=false]', 'false' do
assert_select 'input#user_active_false[type=radio]'
end
end
test "collection radio with block helpers allows access to the current object item in the collection to access extra properties" do
with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
b.label(class: b.object) { b.radio_button + b.text }
end
assert_select 'label.true[for=user_active_true]', 'true' do
assert_select 'input#user_active_true[type=radio]'
end
assert_select 'label.false[for=user_active_false]', 'false' do
assert_select 'input#user_active_false[type=radio]'
end
end
test "collection radio with block helpers does not leak the template" do
with_concat_form_for(@user) do |f|
collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
b.label(class: b.object) { b.radio_button + b.text }
end
concat collection_input
concat f.hidden_field :name
end
assert_select 'label.true[for=user_active_true]', text: 'true', count: 1 do
assert_select 'input#user_active_true[type=radio]'
end
assert_select 'label.false[for=user_active_false]', text: 'false', count: 1 do
assert_select 'input#user_active_false[type=radio]'
end
end
# COLLECTION CHECK BOX
test "collection check box accepts a collection and generate a serie of checkboxes for value method" do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
assert_select 'form input#user_tag_ids_1[type=checkbox][value="1"]'
assert_select 'form input#user_tag_ids_2[type=checkbox][value="2"]'
end
test "collection check box generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection" do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
assert_select "form input[type=hidden][name='user[tag_ids][]'][value='']", count: 1
end
test "collection check box accepts a collection and generate a serie of checkboxes with labels for label method" do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
with_collection_check_boxes @user, :tag_ids, collection, :id, :name
assert_select 'form label.collection_check_boxes[for=user_tag_ids_1]', 'Tag 1'
assert_select 'form label.collection_check_boxes[for=user_tag_ids_2]', 'Tag 2'
end
test "collection check box handles camelized collection values for labels correctly" do
with_collection_check_boxes @user, :active, ['Yes', 'No'], :to_s, :to_s
assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
end
test "collection check box sanitizes collection values for labels correctly" do
with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
end
test "collection check box checks the correct value to local variables" do
user = User.build(tag_ids: [1, 3])
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes user, :tag_ids, collection, :first, :last
assert_select 'form input[type=checkbox][value="1"][checked=checked]'
assert_select 'form input[type=checkbox][value="3"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
end
test "collection check box accepts selected values as :checked option" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: [1, 3]
assert_select 'form input[type=checkbox][value="1"][checked=checked]'
assert_select 'form input[type=checkbox][value="3"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
end
test "collection check boxes accepts selected string values as :checked option" do
collection = (1..3).map { |i| [i, "Category #{i}"] }
with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: ['1', '3']
assert_select 'input[type=checkbox][value="1"][checked=checked]'
assert_select 'input[type=checkbox][value="3"][checked=checked]'
assert_no_select 'input[type=checkbox][value="2"][checked=checked]'
end
test "collection check box accepts a single checked value" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: 3
assert_select 'form input[type=checkbox][value="3"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="1"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
end
test "collection check box accepts selected values as :checked option and override the model values" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
@user.tag_ids = [2]
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: [1, 3]
assert_select 'form input[type=checkbox][value="1"][checked=checked]'
assert_select 'form input[type=checkbox][value="3"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
end
test "collection check box accepts multiple disabled items" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: [1, 3]
assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
assert_select 'form input[type=checkbox][value="3"][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
end
test "collection check box accepts single disable item" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: 1
assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value="3"][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
end
test "collection check box accepts a proc to disabled items" do
collection = (1..3).map { |i| [i, "Tag #{i}"] }
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: proc { |i| i.first == 1 }
assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value="3"][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
end
test "collection check box accepts html options" do
collection = [[1, 'Tag 1'], [2, 'Tag 2']]
with_collection_check_boxes @user, :tag_ids, collection, :first, :last, {}, class: 'check'
assert_select 'form input.check[type=checkbox][value="1"]'
assert_select 'form input.check[type=checkbox][value="2"]'
end
test "collection check box with fields for" do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
with_concat_form_for(@user) do |f|
f.fields_for(:post) do |p|
p.collection_check_boxes :tag_ids, collection, :id, :name
end
end
assert_select 'form input#user_post_tag_ids_1[type=checkbox][value="1"]'
assert_select 'form input#user_post_tag_ids_2[type=checkbox][value="2"]'
assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_1]', 'Tag 1'
assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_2]', 'Tag 2'
end
test "collection check boxes wraps the collection in the given collection wrapper tag" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: :ul
assert_select 'form ul input[type=checkbox]', count: 2
end
test "collection check boxes does not render any wrapper tag by default" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
test "collection check boxes does not wrap the collection when given falsy values" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: false
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
test "collection check boxes uses the given class for collection wrapper tag" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
collection_wrapper_tag: :ul, collection_wrapper_class: "items-list"
assert_select 'form ul.items-list input[type=checkbox]', count: 2
end
test "collection check boxes uses no class for collection wrapper tag when no wrapper tag is given" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
collection_wrapper_class: "items-list"
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
assert_no_select '.items-list'
end
test "collection check boxes uses no class for collection wrapper tag by default" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, collection_wrapper_tag: :ul
assert_select 'form ul'
assert_no_select 'form ul[class]'
end
test "collection check boxes wrap items in a span tag by default" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
assert_select 'form span input[type=checkbox]', count: 2
end
test "collection check boxes wraps each item in the given item wrapper tag" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, item_wrapper_tag: :li
assert_select 'form li input[type=checkbox]', count: 2
end
test "collection check boxes does not wrap each item when given explicitly falsy value" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, item_wrapper_tag: false
assert_select 'form input[type=checkbox]'
assert_no_select 'form span input[type=checkbox]'
end
test "collection check boxes uses the given class for item wrapper tag" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: :li, item_wrapper_class: "inline"
assert_select "form li.inline input[type=checkbox]", count: 2
end
test "collection check boxes uses no class for item wrapper tag when no wrapper tag is given" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: nil, item_wrapper_class: "inline"
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form li'
assert_no_select '.inline'
end
test "collection check boxes uses no class for item wrapper tag by default" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
item_wrapper_tag: :li
assert_select "form li", count: 2
assert_no_select "form li[class]"
end
test "collection check box does not wrap input inside the label" do
with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
assert_select 'form input[type=checkbox] + label'
assert_no_select 'form label input'
end
test "collection check boxes accepts a block to render the label as check box wrapper" do
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
b.label { b.check_box }
end
assert_select 'label[for=user_active_true] > input#user_active_true[type=checkbox]'
assert_select 'label[for=user_active_false] > input#user_active_false[type=checkbox]'
end
test "collection check boxes accepts a block to change the order of label and check box" do
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
b.label + b.check_box
end
assert_select 'label[for=user_active_true] + input#user_active_true[type=checkbox]'
assert_select 'label[for=user_active_false] + input#user_active_false[type=checkbox]'
end
test "collection check boxes with block helpers accept extra html options" do
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
b.label(class: "check_box") + b.check_box(class: "check_box")
end
assert_select 'label.check_box[for=user_active_true] + input#user_active_true.check_box[type=checkbox]'
assert_select 'label.check_box[for=user_active_false] + input#user_active_false.check_box[type=checkbox]'
end
test "collection check boxes with block helpers allows access to current text and value" do
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
b.label(:"data-value" => b.value) { b.check_box + b.text }
end
assert_select 'label[for=user_active_true][data-value=true]', 'true' do
assert_select 'input#user_active_true[type=checkbox]'
end
assert_select 'label[for=user_active_false][data-value=false]', 'false' do
assert_select 'input#user_active_false[type=checkbox]'
end
end
test "collection check boxes with block helpers allows access to the current object item in the collection to access extra properties" do
with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
b.label(class: b.object) { b.check_box + b.text }
end
assert_select 'label.true[for=user_active_true]', 'true' do
assert_select 'input#user_active_true[type=checkbox]'
end
assert_select 'label.false[for=user_active_false]', 'false' do
assert_select 'input#user_active_false[type=checkbox]'
end
end
test "collection check boxes with block helpers does not leak the template" do
with_concat_form_for(@user) do |f|
collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
b.label(class: b.object) { b.check_box + b.text }
end
concat collection_input
concat f.hidden_field :name
end
assert_select 'label.true[for=user_active_true]', text: 'true', count: 1 do
assert_select 'input#user_active_true[type=checkbox]'
end
assert_select 'label.false[for=user_active_false]', text: 'false', count: 1 do
assert_select 'input#user_active_false[type=checkbox]'
end
end
# SIMPLE FIELDS
test "simple fields for is available and yields an instance of FormBuilder" do
with_concat_form_for(@user) do |f|
f.simple_fields_for(:posts) do |posts_form|
assert posts_form.instance_of?(SimpleForm::FormBuilder)
end
end
end
test "fields for with a hash like model yeilds an instance of FormBuilder" do
with_concat_form_for(:user) do |f|
f.simple_fields_for(:author, HashBackedAuthor.new) do |author|
assert author.instance_of?(SimpleForm::FormBuilder)
author.input :name
end
end
assert_select "input[name='user[author][name]'][value='hash backed author']"
end
test "fields for yields an instance of CustomBuilder if main builder is a CustomBuilder" do
with_custom_form_for(:user) do |f|
f.simple_fields_for(:company) do |company|
assert company.instance_of?(CustomFormBuilder)
end
end
end
test "fields for yields an instance of FormBuilder if it was set in options" do
with_custom_form_for(:user) do |f|
f.simple_fields_for(:company, builder: SimpleForm::FormBuilder) do |company|
assert company.instance_of?(SimpleForm::FormBuilder)
end
end
end
test "fields inherits wrapper option from the parent form" do
swap_wrapper :another do
simple_form_for(:user, wrapper: :another) do |f|
f.simple_fields_for(:company) do |company|
assert_equal :another, company.options[:wrapper]
end
end
end
end
test "fields overrides wrapper option from the parent form" do
swap_wrapper :another do
simple_form_for(:user, wrapper: :another) do |f|
f.simple_fields_for(:company, wrapper: false) do |company|
assert_equal false, company.options[:wrapper]
end
end
end
end
end
simple-form-3.2.0/test/inputs/ 0000755 0001750 0001750 00000000000 12623141213 016454 5 ustar terceiro terceiro simple-form-3.2.0/test/inputs/boolean_input_test.rb 0000644 0001750 0001750 00000020255 12623141213 022702 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class BooleanInputTest < ActionView::TestCase
test 'input generates a checkbox by default for boolean attributes' do
with_input_for @user, :active, :boolean
assert_select 'input[type=checkbox].boolean#user_active'
assert_select 'label.boolean.optional', 'Active'
end
test 'input does not generate the label with the checkbox when label option is false' do
with_input_for @user, :active, :boolean, label: false
assert_select 'input[type=checkbox].boolean#user_active'
assert_no_select 'label'
end
test 'input uses custom checked value' do
@user.action = 'on'
with_input_for @user, :action, :boolean, checked_value: 'on', unchecked_value: 'off'
assert_select 'input[type=checkbox][value=on][checked=checked]'
end
test 'input uses custom unchecked value' do
@user.action = 'off'
with_input_for @user, :action, :boolean, checked_value: 'on', unchecked_value: 'off'
assert_select 'input[type=checkbox][value=on]'
assert_no_select 'input[checked=checked][value=on]'
end
test 'input generates hidden input with custom unchecked value' do
with_input_for @user, :action, :boolean, checked_value: 'on', unchecked_value: 'off'
assert_select 'input[type=hidden][value=off]'
end
test 'input uses inline boolean style by default' do
with_input_for @user, :active, :boolean
assert_select 'input.boolean + label.boolean.optional'
assert_no_select 'label > input'
end
test 'input allows changing default boolean style config to nested, generating a default label and a manual hidden field for checkbox' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean
assert_select 'label[for=user_active]', 'Active'
assert_select 'label.boolean > input.boolean'
assert_no_select 'input[type=checkbox] + label'
end
end
test 'input boolean with nested allows :inline_label' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: 'I am so inline.'
assert_select 'label.checkbox', text: ' I am so inline.'
end
end
test 'input boolean with nested escapes :inline_label with HTML' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: 'I am so inline.'
assert_no_select 'label.checkbox b'
end
end
test 'input boolean with nested allows :inline_label with HTML when safe' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: 'I am so inline.'.html_safe
assert_select 'label.checkbox b', text: 'I am so inline.'
end
end
test 'input boolean with nested style creates an inline label using the default label text when inline_label option set to true' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: true
assert_select 'label.checkbox', text: ' Active'
end
end
test 'input boolean with nested style creates an inline label using the label text when inline_label option set to true' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: true, label_text: proc { 'New Active' }
assert_select 'label.checkbox', text: ' New Active'
end
end
test 'input boolean with nested style creates an inline label using the label html when inline_label option set to true' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, inline_label: true, label_text: proc { 'New Active' }
assert_select 'label.checkbox', text: ' New Active'
end
end
test 'input boolean with nested generates a manual hidden field for checkbox outside the label, to recreate Rails functionality with valid html5' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean
assert_select "input[type=hidden][name='user[active]'] + label.boolean > input.boolean"
assert_no_select 'input[type=checkbox] + label'
end
end
test 'input boolean with nested generates a disabled hidden field for checkbox outside the label, if the field is disabled' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, disabled: true
assert_select "input[type=hidden][name='user[active]'][disabled] + label.boolean > input.boolean[disabled]"
end
end
test 'input accepts changing boolean style to nested through given options' do
with_input_for @user, :active, :boolean, boolean_style: :nested
assert_select 'label[for=user_active]', 'Active'
assert_select 'label.boolean > input.boolean'
assert_no_select 'input[type=checkbox] + label'
end
test 'input accepts changing boolean style to inline through given options, when default is nested' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, boolean_style: :inline
assert_select 'label[for=user_active]', 'Active'
assert_select 'input.boolean + label.boolean'
assert_no_select 'label > input'
end
end
test 'input with nested style allows disabling label' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, label: false
assert_select 'input.boolean'
assert_no_select 'label.boolean'
end
end
test 'input with nested style allows customizing input_html' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean, input_html: { name: 'active_user' }
assert_select "input[type=hidden][name=active_user] + label.boolean > input.boolean[name=active_user]"
end
end
test 'input boolean works using :input only in wrapper config (no label_input)' do
swap_wrapper do
with_input_for @user, :active, :boolean
assert_select 'label.boolean + input[type=hidden] + input.boolean'
assert_no_select 'label.checkbox'
end
end
test 'input boolean with nested style works using :input only in wrapper config (no label_input), adding the extra "checkbox" label wrapper' do
swap_wrapper do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean
assert_select 'label.boolean + input[type=hidden] + label.checkbox > input.boolean'
end
end
end
test 'input boolean with nested style works using :input only in wrapper config (no label_input), adding the extra label wrapper with custom class' do
swap_wrapper do
swap SimpleForm, boolean_style: :nested, boolean_label_class: 'foo' do
with_input_for @user, :active, :boolean
assert_select 'label.boolean + input[type=hidden] + label.foo > input.boolean'
end
end
end
test 'input boolean with nested style works using :label_input in wrapper config, adding "checkbox" class to label' do
swap_wrapper :default, self.custom_wrapper_without_top_level do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :boolean
assert_select 'input[type=hidden] + label.boolean.checkbox > input.boolean'
end
end
end
test 'input boolean with nested style works using :label_input in wrapper config, adding custom class to label' do
swap_wrapper :default, self.custom_wrapper_without_top_level do
swap SimpleForm, boolean_style: :nested, boolean_label_class: 'foo' do
with_input_for @user, :active, :boolean
assert_select 'input[type=hidden] + label.boolean.foo > input.boolean'
end
end
end
test 'input boolean without additional classes adds "checkbox" class to label' do
swap_wrapper :default, self.custom_wrapper_without_top_level do
swap SimpleForm, boolean_style: :nested, generate_additional_classes_for: [:input] do
with_input_for @user, :active, :boolean
assert_select 'label'
assert_select 'label.checkbox'
assert_no_select 'label.boolean'
end
end
end
test 'input boolean works with wrapper config defining a class for the input' do
swap_wrapper :default, self.custom_wrapper_with_input_class do
with_input_for @user, :active, :boolean
assert_select 'input.boolean.inline-class'
end
end
end
simple-form-3.2.0/test/inputs/required_test.rb 0000644 0001750 0001750 00000011562 12623141213 021665 0 ustar terceiro terceiro require 'test_helper'
class RequiredTest < ActionView::TestCase
# REQUIRED AND PRESENCE VALIDATION
test 'builder input obtains required from ActiveModel::Validations when it is included' do
with_form_for @validating_user, :name
assert_select 'input.required[required]#validating_user_name'
with_form_for @validating_user, :status
assert_select 'input.optional#validating_user_status'
end
test 'builder input allows overriding required when ActiveModel::Validations is included' do
with_form_for @validating_user, :name, required: false
assert_select 'input.optional#validating_user_name'
with_form_for @validating_user, :status, required: true
assert_select 'input.required[required]#validating_user_status'
end
test 'builder input is required by default when ActiveModel::Validations is not included' do
with_form_for @user, :name
assert_select 'input.required[required]#user_name'
end
test 'builder input does not be required by default when ActiveModel::Validations is not included if option is set to false' do
swap SimpleForm, required_by_default: false do
with_form_for @user, :name
assert_select 'input.optional#user_name'
assert_no_select 'input[required]'
end
end
test 'when not using browser validations, input does not generate required html attribute' do
swap SimpleForm, browser_validations: false do
with_input_for @user, :name, :string
assert_select 'input[type=text].required'
assert_no_select 'input[type=text][required]'
end
end
test 'builder input allows disabling required when ActiveModel::Validations is not included' do
with_form_for @user, :name, required: false
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_select 'input.optional#user_name'
end
test 'when not the required component the input does not have the required attribute but has the required class' do
swap_wrapper do
with_input_for @user, :name, :string
assert_select 'input[type=text].required'
assert_no_select 'input[type=text][required]'
end
end
# VALIDATORS :if :unless
test 'builder input does not be required when ActiveModel::Validations is included and if option is present' do
with_form_for @validating_user, :age
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_select 'input.optional#validating_user_age'
end
test 'builder input does not be required when ActiveModel::Validations is included and unless option is present' do
with_form_for @validating_user, :amount
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_select 'input.optional#validating_user_amount'
end
# VALIDATORS :on
test 'builder input is required when validation is on create and is not persisted' do
@validating_user.new_record!
with_form_for @validating_user, :action
assert_select 'input.required'
assert_select 'input[required]'
assert_select 'input.required[required]#validating_user_action'
end
test 'builder input does not be required when validation is on create and is persisted' do
with_form_for @validating_user, :action
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_select 'input.optional#validating_user_action'
end
test 'builder input is required when validation is on save' do
with_form_for @validating_user, :credit_limit
assert_select 'input.required'
assert_select 'input[required]'
assert_select 'input.required[required]#validating_user_credit_limit'
@validating_user.new_record!
with_form_for @validating_user, :credit_limit
assert_select 'input.required'
assert_select 'input[required]'
assert_select 'input.required[required]#validating_user_credit_limit'
end
test 'builder input is required when validation is on update and is persisted' do
with_form_for @validating_user, :phone_number
assert_select 'input.required'
assert_select 'input[required]'
assert_select 'input.required[required]#validating_user_phone_number'
end
test 'builder input does not be required when validation is on update and is not persisted' do
@validating_user.new_record!
with_form_for @validating_user, :phone_number
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_select 'input.optional#validating_user_phone_number'
end
test 'builder input does not generate required html attribute when option is set to false when it is set to true in wrapper' do
swap SimpleForm, browser_validations: true do
swap_wrapper :default, self.custom_wrapper_with_required_input do
with_concat_form_for(@user) do |f|
concat f.input :name, required: false
end
assert_no_select 'input[type=text][required]'
assert_no_select 'input[type=text][aria-required]'
end
end
end
end
simple-form-3.2.0/test/inputs/datetime_input_test.rb 0000644 0001750 0001750 00000014433 12623141213 023060 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
class DateTimeInputWithHtml5Test < ActionView::TestCase
test 'input generates a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do
with_input_for @user, :created_at, :datetime, html5: true
assert_select 'input[type="datetime"]'
end
test 'input generates a datetime select for datetime attributes' do
with_input_for @user, :created_at, :datetime
assert_select 'select.datetime'
end
test 'input generates a date input for date attributes if HTML5 compatibility is explicitly enbled' do
with_input_for @user, :born_at, :date, html5: true
assert_select 'input[type="date"]'
end
test 'input generates a date select for date attributes' do
with_input_for @user, :born_at, :date
assert_select 'select.date'
end
test 'input generates a time input for time attributes if HTML5 compatibility is explicitly enbled' do
with_input_for @user, :delivery_time, :time, html5: true
assert_select 'input[type="time"]'
end
test 'input generates a time select for time attributes' do
with_input_for @user, :delivery_time, :time
assert_select 'select.time'
end
test 'input generates required html attribute' do
with_input_for @user, :delivery_time, :time, required: true, html5: true
assert_select 'input.required'
assert_select 'input[required]'
end
test 'input has an aria-required html attribute' do
with_input_for @user, :delivery_time, :time, required: true, html5: true
assert_select 'input[aria-required=true]'
end
end
# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
class DateTimeInputWithoutHtml5Test < ActionView::TestCase
test 'input generates a datetime select by default for datetime attributes' do
swap_wrapper do
with_input_for @user, :created_at, :datetime
1.upto(5) do |i|
assert_select "form select.datetime#user_created_at_#{i}i"
end
end
end
test 'input is able to pass options to datetime select' do
with_input_for @user, :created_at, :datetime, html5: false,
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.datetime[disabled=disabled]'
assert_select 'select.datetime option', 'ano'
assert_select 'select.datetime option', 'mês'
assert_select 'select.datetime option', 'dia'
end
test 'input generates a datetime input for datetime attributes if HTML5 compatibility is explicitly enabled' do
swap_wrapper do
with_input_for @user, :created_at, :datetime, html5: true
assert_select 'input[type="datetime"]'
end
end
test 'input generates a date select for date attributes' do
swap_wrapper do
with_input_for @user, :born_at, :date
assert_select 'select.date#user_born_at_1i'
assert_select 'select.date#user_born_at_2i'
assert_select 'select.date#user_born_at_3i'
assert_no_select 'select.date#user_born_at_4i'
end
end
test 'input is able to pass options to date select' do
with_input_for @user, :born_at, :date, as: :date, html5: false,
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
assert_select 'select.date[disabled=disabled]'
assert_select 'select.date option', 'ano'
assert_select 'select.date option', 'mês'
assert_select 'select.date option', 'dia'
end
test 'input is able to pass :default to date select' do
with_input_for @user, :born_at, :date, default: Date.today, html5: false
assert_select "select.date option[value='#{Date.today.year}'][selected=selected]"
end
test 'input generates a date input for date attributes if HTML5 compatibility is explicitly enabled' do
swap_wrapper do
with_input_for @user, :born_at, :date, html5: true
assert_select 'input[type="date"]'
end
end
test 'input generates a time select for time attributes' do
swap_wrapper do
with_input_for @user, :delivery_time, :time
assert_select 'input[type=hidden]#user_delivery_time_1i'
assert_select 'input[type=hidden]#user_delivery_time_2i'
assert_select 'input[type=hidden]#user_delivery_time_3i'
assert_select 'select.time#user_delivery_time_4i'
assert_select 'select.time#user_delivery_time_5i'
end
end
test 'input is able to pass options to time select' do
with_input_for @user, :delivery_time, :time, required: true, html5: false,
disabled: true, prompt: { hour: 'hora', minute: 'minuto' }
assert_select 'select.time[disabled=disabled]'
assert_select 'select.time option', 'hora'
assert_select 'select.time option', 'minuto'
end
test 'input generates a time input for time attributes if HTML5 compatibility is explicitly enabled' do
swap_wrapper do
with_input_for @user, :delivery_time, :time, html5: true
assert_select 'input[type="time"]'
end
end
test 'label uses i18n to get target for date input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
with_input_for :project, :created_at, :date, html5: false
assert_select 'label[for=project_created_at_2i]'
end
end
test 'label uses i18n to get target for datetime input type' do
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
with_input_for :project, :created_at, :datetime, html5: false
assert_select 'label[for=project_created_at_2i]'
end
end
test 'label uses order to get target when date input type' do
with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'], html5: false
assert_select 'label[for=project_created_at_2i]'
end
test 'label uses order to get target when datetime input type' do
with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'], html5: false
assert_select 'label[for=project_created_at_2i]'
end
test 'label points to first option when time input type' do
with_input_for :project, :created_at, :time, html5: false
assert_select 'label[for=project_created_at_4i]'
end
test 'label points to attribute name if HTML5 compatibility is explicitly enabled' do
with_input_for :project, :created_at, :date, html5: true
assert_select 'label[for=project_created_at]'
end
end
simple-form-3.2.0/test/inputs/collection_radio_buttons_input_test.rb 0000644 0001750 0001750 00000041442 12623141213 026353 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class CollectionRadioButtonsInputTest < ActionView::TestCase
setup do
SimpleForm::Inputs::CollectionRadioButtonsInput.reset_i18n_cache :boolean_collection
end
test 'input generates boolean radio buttons by default for radio types' do
with_input_for @user, :active, :radio_buttons
assert_select 'input[type=radio][value=true].radio_buttons#user_active_true'
assert_select 'input[type=radio][value=false].radio_buttons#user_active_false'
end
test 'input as radio generates internal labels by default' do
with_input_for @user, :active, :radio_buttons
assert_select 'label[for=user_active_true]', 'Yes'
assert_select 'label[for=user_active_false]', 'No'
end
test 'input as radio generates internal labels with accurate `for` values with nested boolean style' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons
assert_select 'label[for=user_active_true]', 'Yes'
assert_select 'label[for=user_active_false]', 'No'
end
end
test 'nested label does not duplicate input id' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons, id: 'nested_id'
assert_select 'input#user_active_true'
assert_no_select 'label#user_active_true'
end
end
test 'input as radio uses i18n to translate internal labels' do
store_translations(:en, simple_form: { yes: 'Sim', no: 'Não' }) do
with_input_for @user, :active, :radio_buttons
assert_select 'label[for=user_active_true]', 'Sim'
assert_select 'label[for=user_active_false]', 'Não'
end
end
test 'input radio does not include for attribute by default' do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_select 'label'
assert_no_select 'label[for=user_gender]'
end
test 'input radio includes for attribute when giving as html option' do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female], label_html: { for: 'gender' }
assert_select 'label[for=gender]'
end
test 'input marks the checked value when using boolean and radios' do
@user.active = false
with_input_for @user, :active, :radio_buttons
assert_no_select 'input[type=radio][value=true][checked]'
assert_select 'input[type=radio][value=false][checked]'
end
test 'input allows overriding collection for radio types' do
with_input_for @user, :name, :radio_buttons, collection: ['Jose', 'Carlos']
assert_select 'input[type=radio][value=Jose]'
assert_select 'input[type=radio][value=Carlos]'
assert_select 'label.collection_radio_buttons[for=user_name_jose]', 'Jose'
assert_select 'label.collection_radio_buttons[for=user_name_carlos]', 'Carlos'
end
test 'input does automatic collection translation for radio types using defaults key' do
store_translations(:en, simple_form: { options: { defaults: {
gender: { male: 'Male', female: 'Female'}
} } } ) do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_select 'input[type=radio][value=male]'
assert_select 'input[type=radio][value=female]'
assert_select 'label.collection_radio_buttons[for=user_gender_male]', 'Male'
assert_select 'label.collection_radio_buttons[for=user_gender_female]', 'Female'
end
end
test 'input does automatic collection translation for radio types using specific object key' do
store_translations(:en, simple_form: { options: { user: {
gender: { male: 'Male', female: 'Female'}
} } } ) do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_select 'input[type=radio][value=male]'
assert_select 'input[type=radio][value=female]'
assert_select 'label.collection_radio_buttons[for=user_gender_male]', 'Male'
assert_select 'label.collection_radio_buttons[for=user_gender_female]', 'Female'
end
end
test 'input does automatic collection translation and preserve html markup' do
swap SimpleForm, boolean_style: :nested do
store_translations(:en, simple_form: { options: { user: {
gender: { male_html: 'Male', female_html: 'Female' }
} } } ) do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_select 'input[type=radio][value=male]'
assert_select 'input[type=radio][value=female]'
assert_select 'label[for=user_gender_male] strong', 'Male'
assert_select 'label[for=user_gender_female] strong', 'Female'
end
end
end
test 'input does automatic collection translation with keys prefixed with _html and a string value' do
swap SimpleForm, boolean_style: :nested do
store_translations(:en, simple_form: { options: { user: {
gender: { male_html: 'Male', female_html: 'Female' }
} } } ) do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_select 'input[type=radio][value=male]'
assert_select 'input[type=radio][value=female]'
assert_select 'label[for=user_gender_male]', 'Male'
assert_select 'label[for=user_gender_female]', 'Female'
end
end
end
test 'input marks the current radio value by default' do
@user.name = "Carlos"
with_input_for @user, :name, :radio_buttons, collection: ['Jose', 'Carlos']
assert_select 'input[type=radio][value=Carlos][checked=checked]'
end
test 'input accepts html options as the last element of collection' do
with_input_for @user, :name, :radio_buttons, collection: [['Jose', 'jose', class: 'foo']]
assert_select 'input.foo[type=radio][value=jose]'
end
test 'input allows using a collection with text/value arrays' do
with_input_for @user, :name, :radio_buttons, collection: [['Jose', 'jose'], ['Carlos', 'carlos']]
assert_select 'input[type=radio][value=jose]'
assert_select 'input[type=radio][value=carlos]'
assert_select 'label.collection_radio_buttons', 'Jose'
assert_select 'label.collection_radio_buttons', 'Carlos'
end
test 'input allows using a collection with a Proc' do
with_input_for @user, :name, :radio_buttons, collection: Proc.new { ['Jose', 'Carlos' ] }
assert_select 'label.collection_radio_buttons', 'Jose'
assert_select 'label.collection_radio_buttons', 'Carlos'
end
test 'input allows overriding only label method for collections' do
with_input_for @user, :name, :radio_buttons,
collection: ['Jose', 'Carlos'],
label_method: :upcase
assert_select 'label.collection_radio_buttons', 'JOSE'
assert_select 'label.collection_radio_buttons', 'CARLOS'
end
test 'input allows overriding only value method for collections' do
with_input_for @user, :name, :radio_buttons,
collection: ['Jose', 'Carlos'],
value_method: :upcase
assert_select 'input[type=radio][value=JOSE]'
assert_select 'input[type=radio][value=CARLOS]'
end
test 'input allows overriding label and value method for collections' do
with_input_for @user, :name, :radio_buttons,
collection: ['Jose', 'Carlos'],
label_method: :upcase,
value_method: :downcase
assert_select 'input[type=radio][value=jose]'
assert_select 'input[type=radio][value=carlos]'
assert_select 'label.collection_radio_buttons', 'JOSE'
assert_select 'label.collection_radio_buttons', 'CARLOS'
end
test 'input allows overriding label and value method using a lambda for collections' do
with_input_for @user, :name, :radio_buttons,
collection: ['Jose', 'Carlos'],
label_method: lambda { |i| i.upcase },
value_method: lambda { |i| i.downcase }
assert_select 'input[type=radio][value=jose]'
assert_select 'input[type=radio][value=carlos]'
assert_select 'label.collection_radio_buttons', 'JOSE'
assert_select 'label.collection_radio_buttons', 'CARLOS'
end
test 'collection input with radio type generates required html attribute' do
with_input_for @user, :name, :radio_buttons, collection: ['Jose', 'Carlos']
assert_select 'input[type=radio].required'
assert_select 'input[type=radio][required]'
end
test 'collection input with radio type generates aria-required html attribute' do
with_input_for @user, :name, :radio_buttons, collection: ['Jose', 'Carlos']
assert_select 'input[type=radio].required'
assert_select 'input[type=radio][aria-required=true]'
end
test 'input radio does not wrap the collection by default' do
with_input_for @user, :active, :radio_buttons
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
end
test 'input radio wraps the collection in the configured collection wrapper tag' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :radio_buttons
assert_select 'form ul input[type=radio]', count: 2
end
end
test 'input radio does not wrap the collection when configured with falsy values' do
swap SimpleForm, collection_wrapper_tag: false do
with_input_for @user, :active, :radio_buttons
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
end
end
test 'input radio allows overriding the collection wrapper tag at input level' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :radio_buttons, collection_wrapper_tag: :section
assert_select 'form section input[type=radio]', count: 2
assert_no_select 'form ul'
end
end
test 'input radio allows disabling the collection wrapper tag at input level' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :radio_buttons, collection_wrapper_tag: false
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form ul'
end
end
test 'input radio renders the wrapper tag with the configured wrapper class' do
swap SimpleForm, collection_wrapper_tag: :ul, collection_wrapper_class: 'inputs-list' do
with_input_for @user, :active, :radio_buttons
assert_select 'form ul.inputs-list input[type=radio]', count: 2
end
end
test 'input radio allows giving wrapper class at input level only' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :radio_buttons, collection_wrapper_class: 'items-list'
assert_select 'form ul.items-list input[type=radio]', count: 2
end
end
test 'input radio uses both configured and given wrapper classes for wrapper tag' do
swap SimpleForm, collection_wrapper_tag: :ul, collection_wrapper_class: 'inputs-list' do
with_input_for @user, :active, :radio_buttons, collection_wrapper_class: 'items-list'
assert_select 'form ul.inputs-list.items-list input[type=radio]', count: 2
end
end
test 'input radio wraps each item in the configured item wrapper tag' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :radio_buttons
assert_select 'form li input[type=radio]', count: 2
end
end
test 'input radio does not wrap items when configured with falsy values' do
swap SimpleForm, item_wrapper_tag: false do
with_input_for @user, :active, :radio_buttons
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form li'
end
end
test 'input radio allows overriding the item wrapper tag at input level' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :radio_buttons, item_wrapper_tag: :dl
assert_select 'form dl input[type=radio]', count: 2
assert_no_select 'form li'
end
end
test 'input radio allows disabling the item wrapper tag at input level' do
swap SimpleForm, item_wrapper_tag: :ul do
with_input_for @user, :active, :radio_buttons, item_wrapper_tag: false
assert_select 'form input[type=radio]', count: 2
assert_no_select 'form li'
end
end
test 'input radio wraps items in a span tag by default' do
with_input_for @user, :active, :radio_buttons
assert_select 'form span input[type=radio]', count: 2
end
test 'input radio renders the item wrapper tag with a default class "radio"' do
with_input_for @user, :active, :radio_buttons, item_wrapper_tag: :li
assert_select 'form li.radio input[type=radio]', count: 2
end
test 'input radio renders the item wrapper tag with the configured item wrapper class' do
swap SimpleForm, item_wrapper_tag: :li, item_wrapper_class: 'item' do
with_input_for @user, :active, :radio_buttons
assert_select 'form li.radio.item input[type=radio]', count: 2
end
end
test 'input radio allows giving item wrapper class at input level only' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :radio_buttons, item_wrapper_class: 'item'
assert_select 'form li.radio.item input[type=radio]', count: 2
end
end
test 'input radio uses both configured and given item wrapper classes for item wrapper tag' do
swap SimpleForm, item_wrapper_tag: :li, item_wrapper_class: 'item' do
with_input_for @user, :active, :radio_buttons, item_wrapper_class: 'inline'
assert_select 'form li.radio.item.inline input[type=radio]', count: 2
end
end
test 'input radio respects the nested boolean style config, generating nested label > input' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons
assert_select 'span.radio > label > input#user_active_true[type=radio]'
assert_select 'span.radio > label', 'Yes'
assert_select 'span.radio > label > input#user_active_false[type=radio]'
assert_select 'span.radio > label', 'No'
assert_no_select 'label.collection_radio_buttons'
end
end
test 'input radio with nested style does not overrides configured item wrapper tag' do
swap SimpleForm, boolean_style: :nested, item_wrapper_tag: :li do
with_input_for @user, :active, :radio_buttons
assert_select 'li.radio > label > input'
end
end
test 'input radio with nested style does not overrides given item wrapper tag' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons, item_wrapper_tag: :li
assert_select 'li.radio > label > input'
end
end
test 'input radio with nested style accepts giving extra wrapper classes' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons, item_wrapper_class: "inline"
assert_select 'span.radio.inline > label > input'
end
end
test 'input radio with nested style renders item labels with specified class' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :radio_buttons, item_label_class: "test"
assert_select 'span.radio > label.test > input'
end
end
test 'input radio with nested style and falsey input wrapper renders item labels with specified class' do
swap SimpleForm, boolean_style: :nested, item_wrapper_tag: false do
with_input_for @user, :active, :radio_buttons, item_label_class: "radio-inline"
assert_select 'label.radio-inline > input'
assert_no_select 'span.radio'
end
end
test 'input radio wrapper class are not included when set to falsey' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female]
assert_no_select 'label.radio'
end
end
test 'input radio custom wrapper class is included when include input wrapper class is falsey' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_input_for @user, :gender, :radio_buttons, collection: [:male, :female], item_wrapper_class: 'custom'
assert_no_select 'label.radio'
assert_select 'span.custom'
end
end
test 'input radio with nested style and namespace uses the right for attribute' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_concat_form_for @user, namespace: :foo do |f|
concat f.input :gender, as: :radio_buttons, collection: [:male, :female]
end
assert_select 'label[for=foo_user_gender_male]'
assert_select 'label[for=foo_user_gender_female]'
end
end
test 'input radio with nested style and index uses the right for attribute' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_concat_form_for @user, index: 1 do |f|
concat f.input :gender, as: :radio_buttons, collection: [:male, :female]
end
assert_select 'label[for=user_1_gender_male]'
assert_select 'label[for=user_1_gender_female]'
end
end
end
simple-form-3.2.0/test/inputs/discovery_test.rb 0000644 0001750 0001750 00000007047 12623141213 022057 0 ustar terceiro terceiro require 'test_helper'
class DiscoveryTest < ActionView::TestCase
# Setup new inputs and remove them after the test.
def discovery(value = false)
swap SimpleForm, cache_discovery: value do
begin
load "support/discovery_inputs.rb"
yield
ensure
SimpleForm::FormBuilder.discovery_cache.clear
Object.send :remove_const, :StringInput
Object.send :remove_const, :NumericInput
Object.send :remove_const, :CustomizedInput
Object.send :remove_const, :DeprecatedInput
Object.send :remove_const, :CollectionSelectInput
CustomInputs.send :remove_const, :PasswordInput
CustomInputs.send :remove_const, :NumericInput
end
end
end
test 'builder does not discover new inputs if cached' do
with_form_for @user, :name
assert_select 'form input#user_name.string'
discovery(true) do
with_form_for @user, :name
assert_no_select 'form section input#user_name.string'
end
end
test 'builder discovers new inputs' do
discovery do
with_form_for @user, :name, as: :customized
assert_select 'form section input#user_name.string'
end
end
test 'builder does not discover new inputs if discovery is off' do
with_form_for @user, :name
assert_select 'form input#user_name.string'
swap SimpleForm, inputs_discovery: false do
discovery do
with_form_for @user, :name
assert_no_select 'form section input#user_name.string'
end
end
end
test 'builder discovers new inputs from mappings if not cached' do
discovery do
with_form_for @user, :name
assert_select 'form section input#user_name.string'
end
end
test 'builder discovers new inputs from internal fallbacks if not cached' do
discovery do
with_form_for @user, :age
assert_select 'form section input#user_age.numeric.integer'
end
end
test 'builder discovers new maped inputs from configured namespaces if not cached' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['CustomInputs'] do
with_form_for @user, :password
assert_select 'form input#user_password.password-custom-input'
end
end
end
test 'builder discovers new maped inputs from configured namespaces before the ones from top level namespace' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['CustomInputs'] do
with_form_for @user, :age
assert_select 'form input#user_age.numeric-custom-input'
end
end
end
test 'builder discovers new custom inputs from configured namespace before the ones from top level namespace' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['CustomInputs'] do
with_form_for @user, :name, as: 'customized'
assert_select 'form input#user_name.customized-namespace-custom-input'
end
end
end
test 'raises error when configured namespace does not exists' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['InvalidNamespace'] do
assert_raise NameError do
with_form_for @user, :age
end
end
end
end
test 'new inputs can override the input_html_options' do
discovery do
with_form_for @user, :active, as: :select
assert_select 'form select#user_active.select.chosen'
end
end
test 'inputs method without wrapper_options are deprecated' do
discovery do
assert_deprecated do
with_form_for @user, :name, as: :deprecated
end
assert_select 'form section input#user_name.string'
end
end
end
simple-form-3.2.0/test/inputs/collection_check_boxes_input_test.rb 0000644 0001750 0001750 00000027035 12623141213 025756 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class CollectionCheckBoxesInputTest < ActionView::TestCase
setup do
SimpleForm::Inputs::CollectionCheckBoxesInput.reset_i18n_cache :boolean_collection
end
test 'input check boxes does not include for attribute by default' do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
assert_select 'label'
assert_no_select 'label[for=user_gender]'
end
test 'input check boxes includes for attribute when giving as html option' do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female], label_html: { for: 'gender' }
assert_select 'label[for=gender]'
end
test 'collection input with check_boxes type does not generate required html attribute' do
with_input_for @user, :name, :check_boxes, collection: ['Jose', 'Carlos']
assert_select 'input.required'
assert_no_select 'input[required]'
end
test 'collection input with check_boxes type does not generate aria-required html attribute' do
with_input_for @user, :name, :check_boxes, collection: ['Jose', 'Carlos']
assert_select 'input.required'
assert_no_select 'input[aria-required]'
end
test 'input does automatic collection translation for check_box types using defaults key' do
store_translations(:en, simple_form: { options: { defaults: {
gender: { male: 'Male', female: 'Female'}
} } } ) do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
assert_select 'input[type=checkbox][value=male]'
assert_select 'input[type=checkbox][value=female]'
assert_select 'label.collection_check_boxes', 'Male'
assert_select 'label.collection_check_boxes', 'Female'
end
end
test 'input does automatic collection translation for check_box types using specific object key' do
store_translations(:en, simple_form: { options: { user: {
gender: { male: 'Male', female: 'Female'}
} } } ) do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
assert_select 'input[type=checkbox][value=male]'
assert_select 'input[type=checkbox][value=female]'
assert_select 'label.collection_check_boxes', 'Male'
assert_select 'label.collection_check_boxes', 'Female'
end
end
test 'input that uses automatic collection translation for check_boxes properly sets checked values' do
store_translations(:en, simple_form: { options: { defaults: {
gender: { male: 'Male', female: 'Female'}
} } } ) do
@user.gender = 'male'
with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
assert_select 'input[type=checkbox][value=male][checked=checked]'
assert_select 'input[type=checkbox][value=female]'
assert_select 'label.collection_check_boxes', 'Male'
assert_select 'label.collection_check_boxes', 'Female'
end
end
test 'input check boxes does not wrap the collection by default' do
with_input_for @user, :active, :check_boxes
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
test 'input check boxes accepts html options as the last element of collection' do
with_input_for @user, :name, :check_boxes, collection: [['Jose', 'jose', class: 'foo']]
assert_select 'input.foo[type=checkbox][value=jose]'
end
test 'input check boxes wraps the collection in the configured collection wrapper tag' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :check_boxes
assert_select 'form ul input[type=checkbox]', count: 2
end
end
test 'input check boxes does not wrap the collection when configured with falsy values' do
swap SimpleForm, collection_wrapper_tag: false do
with_input_for @user, :active, :check_boxes
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
end
test 'input check boxes allows overriding the collection wrapper tag at input level' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :check_boxes, collection_wrapper_tag: :section
assert_select 'form section input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
end
test 'input check boxes allows disabling the collection wrapper tag at input level' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :check_boxes, collection_wrapper_tag: false
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form ul'
end
end
test 'input check boxes renders the wrapper tag with the configured wrapper class' do
swap SimpleForm, collection_wrapper_tag: :ul, collection_wrapper_class: 'inputs-list' do
with_input_for @user, :active, :check_boxes
assert_select 'form ul.inputs-list input[type=checkbox]', count: 2
end
end
test 'input check boxes allows giving wrapper class at input level only' do
swap SimpleForm, collection_wrapper_tag: :ul do
with_input_for @user, :active, :check_boxes, collection_wrapper_class: 'items-list'
assert_select 'form ul.items-list input[type=checkbox]', count: 2
end
end
test 'input check boxes uses both configured and given wrapper classes for wrapper tag' do
swap SimpleForm, collection_wrapper_tag: :ul, collection_wrapper_class: 'inputs-list' do
with_input_for @user, :active, :check_boxes, collection_wrapper_class: 'items-list'
assert_select 'form ul.inputs-list.items-list input[type=checkbox]', count: 2
end
end
test 'input check boxes wraps each item in the configured item wrapper tag' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :check_boxes
assert_select 'form li input[type=checkbox]', count: 2
end
end
test 'input check boxes does not wrap items when configured with falsy values' do
swap SimpleForm, item_wrapper_tag: false do
with_input_for @user, :active, :check_boxes
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form li'
end
end
test 'input check boxes allows overriding the item wrapper tag at input level' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :check_boxes, item_wrapper_tag: :dl
assert_select 'form dl input[type=checkbox]', count: 2
assert_no_select 'form li'
end
end
test 'input check boxes allows disabling the item wrapper tag at input level' do
swap SimpleForm, item_wrapper_tag: :ul do
with_input_for @user, :active, :check_boxes, item_wrapper_tag: false
assert_select 'form input[type=checkbox]', count: 2
assert_no_select 'form li'
end
end
test 'input check boxes wraps items in a span tag by default' do
with_input_for @user, :active, :check_boxes
assert_select 'form span input[type=checkbox]', count: 2
end
test 'input check boxes renders the item wrapper tag with a default class "checkbox"' do
with_input_for @user, :active, :check_boxes, item_wrapper_tag: :li
assert_select 'form li.checkbox input[type=checkbox]', count: 2
end
test 'input check boxes renders the item wrapper tag with the configured item wrapper class' do
swap SimpleForm, item_wrapper_tag: :li, item_wrapper_class: 'item' do
with_input_for @user, :active, :check_boxes
assert_select 'form li.checkbox.item input[type=checkbox]', count: 2
end
end
test 'input check boxes allows giving item wrapper class at input level only' do
swap SimpleForm, item_wrapper_tag: :li do
with_input_for @user, :active, :check_boxes, item_wrapper_class: 'item'
assert_select 'form li.checkbox.item input[type=checkbox]', count: 2
end
end
test 'input check boxes uses both configured and given item wrapper classes for item wrapper tag' do
swap SimpleForm, item_wrapper_tag: :li, item_wrapper_class: 'item' do
with_input_for @user, :active, :check_boxes, item_wrapper_class: 'inline'
assert_select 'form li.checkbox.item.inline input[type=checkbox]', count: 2
end
end
test 'input check boxes respects the nested boolean style config, generating nested label > input' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :check_boxes
assert_select 'span.checkbox > label > input#user_active_true[type=checkbox]'
assert_select 'span.checkbox > label', 'Yes'
assert_select 'span.checkbox > label > input#user_active_false[type=checkbox]'
assert_select 'span.checkbox > label', 'No'
assert_no_select 'label.collection_radio_buttons'
end
end
test 'input check boxes with nested style does not overrides configured item wrapper tag' do
swap SimpleForm, boolean_style: :nested, item_wrapper_tag: :li do
with_input_for @user, :active, :check_boxes
assert_select 'li.checkbox > label > input'
end
end
test 'input check boxes with nested style does not overrides given item wrapper tag' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :check_boxes, item_wrapper_tag: :li
assert_select 'li.checkbox > label > input'
end
end
test 'input check boxes with nested style accepts giving extra wrapper classes' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :check_boxes, item_wrapper_class: "inline"
assert_select 'span.checkbox.inline > label > input'
end
end
test 'input check boxes with nested style renders item labels with specified class' do
swap SimpleForm, boolean_style: :nested do
with_input_for @user, :active, :check_boxes, item_label_class: "test"
assert_select 'span.checkbox > label.test > input'
end
end
test 'input check boxes with nested style and falsey input wrapper renders item labels with specified class' do
swap SimpleForm, boolean_style: :nested, item_wrapper_tag: false do
with_input_for @user, :active, :check_boxes, item_label_class: "checkbox-inline"
assert_select 'label.checkbox-inline > input'
assert_no_select 'span.checkbox'
end
end
test 'input check boxes wrapper class are not included when set to falsey' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female]
assert_no_select 'label.checkbox'
end
end
test 'input check boxes custom wrapper class is included when include input wrapper class is falsey' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_input_for @user, :gender, :check_boxes, collection: [:male, :female], item_wrapper_class: 'custom'
assert_no_select 'label.checkbox'
assert_select 'span.custom'
end
end
test 'input check boxes with nested style and namespace uses the right for attribute' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_concat_form_for @user, namespace: :foo do |f|
concat f.input :gender, as: :check_boxes, collection: [:male, :female]
end
assert_select 'label[for=foo_user_gender_male]'
assert_select 'label[for=foo_user_gender_female]'
end
end
test 'input check boxes with nested style and index uses the right for attribute' do
swap SimpleForm, include_default_input_wrapper_class: false, boolean_style: :nested do
with_concat_form_for @user, index: 1 do |f|
concat f.input :gender, as: :check_boxes, collection: [:male, :female]
end
assert_select 'label[for=user_1_gender_male]'
assert_select 'label[for=user_1_gender_female]'
end
end
end
simple-form-3.2.0/test/inputs/general_test.rb 0000644 0001750 0001750 00000011516 12623141213 021461 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class InputTest < ActionView::TestCase
test 'input generates css class based on default input type' do
with_input_for @user, :name, :string
assert_select 'input.string'
with_input_for @user, :description, :text
assert_select 'textarea.text'
with_input_for @user, :age, :integer
assert_select 'input.integer'
with_input_for @user, :born_at, :date
assert_select 'select.date'
with_input_for @user, :created_at, :datetime
assert_select 'select.datetime'
end
test 'string input generates autofocus attribute when autofocus option is true' do
with_input_for @user, :name, :string, autofocus: true
assert_select 'input.string[autofocus]'
end
test 'input accepts input_class configuration' do
swap SimpleForm, input_class: :xlarge do
with_input_for @user, :name, :string
assert_select 'input.xlarge'
assert_no_select 'div.xlarge'
end
end
test 'input does not add input_class when configured to not generate additional classes for input' do
swap SimpleForm, input_class: 'xlarge', generate_additional_classes_for: [:wrapper] do
with_input_for @user, :name, :string
assert_select 'input'
assert_no_select '.xlarge'
end
end
test 'text input generates autofocus attribute when autofocus option is true' do
with_input_for @user, :description, :text, autofocus: true
assert_select 'textarea.text[autofocus]'
end
test 'numeric input generates autofocus attribute when autofocus option is true' do
with_input_for @user, :age, :integer, autofocus: true
assert_select 'input.integer[autofocus]'
end
test 'date input generates autofocus attribute when autofocus option is true' do
with_input_for @user, :born_at, :date, autofocus: true
assert_select 'select.date[autofocus]'
end
test 'datetime input generates autofocus attribute when autofocus option is true' do
with_input_for @user, :created_at, :datetime, autofocus: true
assert_select 'select.datetime[autofocus]'
end
test 'string input generates autofocus attribute when autofocus option is false' do
with_input_for @user, :name, :string, autofocus: false
assert_no_select 'input.string[autofocus]'
end
test 'text input generates autofocus attribute when autofocus option is false' do
with_input_for @user, :description, :text, autofocus: false
assert_no_select 'textarea.text[autofocus]'
end
test 'numeric input generates autofocus attribute when autofocus option is false' do
with_input_for @user, :age, :integer, autofocus: false
assert_no_select 'input.integer[autofocus]'
end
test 'date input generates autofocus attribute when autofocus option is false' do
with_input_for @user, :born_at, :date, autofocus: false
assert_no_select 'select.date[autofocus]'
end
test 'datetime input generates autofocus attribute when autofocus option is false' do
with_input_for @user, :created_at, :datetime, autofocus: false
assert_no_select 'select.datetime[autofocus]'
end
test 'string input generates autofocus attribute when autofocus option is not present' do
with_input_for @user, :name, :string
assert_no_select 'input.string[autofocus]'
end
test 'text input generates autofocus attribute when autofocus option is not present' do
with_input_for @user, :description, :text
assert_no_select 'textarea.text[autofocus]'
end
test 'numeric input generates autofocus attribute when autofocus option is not present' do
with_input_for @user, :age, :integer
assert_no_select 'input.integer[autofocus]'
end
test 'date input generates autofocus attribute when autofocus option is not present' do
with_input_for @user, :born_at, :date
assert_no_select 'select.date[autofocus]'
end
test 'datetime input generates autofocus attribute when autofocus option is not present' do
with_input_for @user, :created_at, :datetime
assert_no_select 'select.datetime[autofocus]'
end
# With no object
test 'input is generated properly when object is not present' do
with_input_for :project, :name, :string
assert_select 'input.string.required#project_name'
end
test 'input as radio is generated properly when object is not present ' do
with_input_for :project, :name, :radio_buttons
assert_select 'input.radio_buttons#project_name_true'
assert_select 'input.radio_buttons#project_name_false'
end
test 'input as select with collection is generated properly when object is not present' do
with_input_for :project, :name, :select, collection: ['Jose', 'Carlos']
assert_select 'select.select#project_name'
end
test 'input does not generate empty css class' do
swap SimpleForm, generate_additional_classes_for: [:wrapper, :label] do
with_input_for :project, :name, :string
assert_no_select 'input#project_name[class]'
end
end
end
simple-form-3.2.0/test/inputs/hidden_input_test.rb 0000644 0001750 0001750 00000001723 12623141213 022515 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class HiddenInputTest < ActionView::TestCase
test 'input generates a hidden field' do
with_input_for @user, :name, :hidden
assert_no_select 'input[type=text]'
assert_select 'input#user_name[type=hidden]'
end
test 'hint does not be generated for hidden fields' do
store_translations(:en, simple_form: { hints: { user: { name: "text" } } }) do
with_input_for @user, :name, :hidden
assert_no_select 'span.hint'
end
end
test 'label does not be generated for hidden inputs' do
with_input_for @user, :name, :hidden
assert_no_select 'label'
end
test 'required/aria-required/optional options does not be generated for hidden inputs' do
with_input_for @user, :name, :hidden
assert_no_select 'input.required'
assert_no_select 'input[required]'
assert_no_select 'input[aria-required]'
assert_no_select 'input.optional'
assert_select 'input.hidden#user_name'
end
end
simple-form-3.2.0/test/inputs/file_input_test.rb 0000644 0001750 0001750 00000000744 12623141213 022203 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class FileInputTest < ActionView::TestCase
test 'input generates a file field' do
with_input_for @user, :name, :file
assert_select 'input#user_name[type=file]'
end
test "input generates a file field that doesn't accept placeholder" do
store_translations(:en, simple_form: { placeholders: { user: { name: "text" } } }) do
with_input_for @user, :name, :file
assert_no_select 'input[placeholder]'
end
end
end
simple-form-3.2.0/test/inputs/grouped_collection_select_input_test.rb 0000644 0001750 0001750 00000013535 12623141213 026505 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class GroupedCollectionSelectInputTest < ActionView::TestCase
test 'grouped collection accepts array collection form' do
with_input_for @user, :tag_ids, :grouped_select,
collection: [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]],
group_method: :last
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option', 'Jose'
assert_select 'option', 'Carlos'
end
assert_select 'optgroup[label=General]' do
assert_select 'option', 'Bob'
assert_select 'option', 'John'
end
end
end
test 'grouped collection accepts empty array collection form' do
with_input_for @user, :tag_ids, :grouped_select,
collection: [],
group_method: :last
assert_select 'select.grouped_select#user_tag_ids'
end
test 'grouped collection accepts proc as collection' do
with_input_for @user, :tag_ids, :grouped_select,
collection: Proc.new { [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]] },
group_method: :last
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option', 'Jose'
assert_select 'option', 'Carlos'
end
assert_select 'optgroup[label=General]' do
assert_select 'option', 'Bob'
assert_select 'option', 'John'
end
end
end
test 'grouped collection accepts hash collection form' do
with_input_for @user, :tag_ids, :grouped_select,
collection: { 'Authors' => ['Jose', 'Carlos'], 'General' => ['Bob', 'John'] },
group_method: :last
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option', 'Jose'
assert_select 'option', 'Carlos'
end
assert_select 'optgroup[label=General]' do
assert_select 'option', 'Bob'
assert_select 'option', 'John'
end
end
end
test 'grouped collection accepts group_label_method option' do
with_input_for @user, :tag_ids, :grouped_select,
collection: { ['Jose', 'Carlos'] => 'Authors' },
group_method: :first,
group_label_method: :last
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option', 'Jose'
assert_select 'option', 'Carlos'
end
end
end
test 'grouped collection finds default label methods on the group objects' do
option_list = ['Jose', 'Carlos']
GroupedClass = Struct.new(:to_label, :options)
group = GroupedClass.new("Authors", option_list)
with_input_for @user, :tag_ids, :grouped_select,
collection: [group],
group_method: :options
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option', 'Jose'
assert_select 'option', 'Carlos'
end
end
end
test 'grouped collections finds the default label method from the first non-empty object' do
Agent = Struct.new(:id, :name)
agents = [["First", []], ["Second", [Agent.new(7, 'Bond'), Agent.new(47, 'Hitman')]]]
with_input_for @user, :tag_ids, :grouped_select,
collection: agents,
group_label_method: :first,
group_method: :last,
include_blank: false
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Second]' do
assert_select 'option[value="7"]', 'Bond'
assert_select 'option[value="47"]', 'Hitman'
end
end
end
test 'grouped collection accepts label and value methods options' do
with_input_for @user, :tag_ids, :grouped_select,
collection: { 'Authors' => ['Jose', 'Carlos'] },
group_method: :last,
label_method: :upcase,
value_method: :downcase
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option[value=jose]', 'JOSE'
assert_select 'option[value=carlos]', 'CARLOS'
end
end
end
test 'grouped collection allows overriding label and value methods using a lambda' do
with_input_for @user, :tag_ids, :grouped_select,
collection: { 'Authors' => ['Jose', 'Carlos'] },
group_method: :last,
label_method: lambda { |i| i.upcase },
value_method: lambda { |i| i.downcase }
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option[value=jose]', 'JOSE'
assert_select 'option[value=carlos]', 'CARLOS'
end
end
end
test 'grouped collection with associations' do
tag_groups = [
TagGroup.new(1, "Group of Tags", [Tag.new(1, "Tag 1"), Tag.new(2, "Tag 2")]),
TagGroup.new(2, "Other group", [Tag.new(3, "Tag 3"), Tag.new(4,"Tag 4")])
]
with_input_for @user, :tag_ids, :grouped_select,
collection: tag_groups, group_method: :tags
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label="Group of Tags"]' do
assert_select 'option[value="1"]', 'Tag 1'
assert_select 'option[value="2"]', 'Tag 2'
end
assert_select 'optgroup[label="Other group"]' do
assert_select 'option[value="3"]', 'Tag 3'
assert_select 'option[value="4"]', 'Tag 4'
end
end
end
test 'grouped collection accepts html options as the last element of collection' do
with_input_for @user, :tag_ids, :grouped_select,
collection: [['Authors', [['Jose', 'jose', class: 'foo'], ['Carlos', 'carlos', class: 'bar']]]],
group_method: :last
assert_select 'select.grouped_select#user_tag_ids' do
assert_select 'optgroup[label=Authors]' do
assert_select 'option.foo', 'Jose'
assert_select 'option.bar', 'Carlos'
end
end
end
end
simple-form-3.2.0/test/inputs/priority_input_test.rb 0000644 0001750 0001750 00000003463 12623141213 023146 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class PriorityInputTest < ActionView::TestCase
test 'input generates a country select field' do
with_input_for @user, :country, :country
assert_select 'select#user_country'
assert_select 'select option[value=Brazil]', 'Brazil'
assert_no_select 'select option[value=""][disabled=disabled]'
end
test 'input generates a country select with SimpleForm default' do
swap SimpleForm, country_priority: [ 'Brazil' ] do
with_input_for @user, :country, :country
assert_select 'select option[value=""][disabled=disabled]'
end
end
test 'input generates a time zone select field' do
with_input_for @user, :time_zone, :time_zone
assert_select 'select#user_time_zone'
assert_select 'select option[value=Brasilia]', '(GMT-03:00) Brasilia'
assert_no_select 'select option[value=""][disabled=disabled]'
end
test 'input generates a time zone select field with default' do
with_input_for @user, :time_zone, :time_zone, default: 'Brasilia'
assert_select 'select option[value=Brasilia][selected=selected]'
assert_no_select 'select option[value=""]'
end
test 'input generates a time zone select using options priority' do
with_input_for @user, :time_zone, :time_zone, priority: /Brasilia/
assert_select 'select option[value=""][disabled=disabled]'
assert_no_select 'select option[value=""]', /^$/
end
test 'priority input does not generate invalid required html attribute' do
with_input_for @user, :country, :country
assert_select 'select.required'
assert_no_select 'select[required]'
end
test 'priority input does not generate invalid aria-required html attribute' do
with_input_for @user, :country, :country
assert_select 'select.required'
assert_no_select 'select[aria-required]'
end
end
simple-form-3.2.0/test/inputs/numeric_input_test.rb 0000644 0001750 0001750 00000013552 12623141213 022727 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class NumericInputTest < ActionView::TestCase
test 'input generates an integer text field for integer attributes ' do
with_input_for @user, :age, :integer
assert_select 'input[type=number].integer#user_age'
end
test 'input generates a float text field for float attributes ' do
with_input_for @user, :age, :float
assert_select 'input[type=number].float#user_age'
end
test 'input generates a decimal text field for decimal attributes ' do
with_input_for @user, :age, :decimal
assert_select 'input[type=number].decimal#user_age'
end
test 'input does not generate min attribute by default' do
with_input_for @user, :age, :integer
assert_no_select 'input[min]'
end
test 'input does not generate max attribute by default' do
with_input_for @user, :age, :integer
assert_no_select 'input[max]'
end
test 'input infers min value from integer attributes with greater than validation' do
with_input_for @other_validating_user, :age, :float
assert_no_select 'input[min]'
with_input_for @other_validating_user, :age, :integer
assert_select 'input[min="18"]'
end
test 'input infers min value from integer attributes with greater than validation using symbol' do
with_input_for @validating_user, :amount, :float
assert_no_select 'input[min]'
with_input_for @validating_user, :amount, :integer
assert_select 'input[min="11"]'
end
test 'input infers min value from integer attributes with greater than or equal to validation using symbol' do
with_input_for @validating_user, :attempts, :float
assert_select 'input[min="1"]'
with_input_for @validating_user, :attempts, :integer
assert_select 'input[min="1"]'
end
test 'input infers min value from integer attributes with greater than validation using proc' do
with_input_for @other_validating_user, :amount, :float
assert_no_select 'input[min]'
with_input_for @other_validating_user, :amount, :integer
assert_select 'input[min="20"]'
end
test 'input infers min value from integer attributes with greater than or equal to validation using proc' do
with_input_for @other_validating_user, :attempts, :float
assert_select 'input[min="19"]'
with_input_for @other_validating_user, :attempts, :integer
assert_select 'input[min="19"]'
end
test 'input infers max value from attributes with less than validation' do
with_input_for @other_validating_user, :age, :float
assert_no_select 'input[max]'
with_input_for @other_validating_user, :age, :integer
assert_select 'input[max="99"]'
end
test 'input infers max value from attributes with less than validation using symbol' do
with_input_for @validating_user, :amount, :float
assert_no_select 'input[max]'
with_input_for @validating_user, :amount, :integer
assert_select 'input[max="99"]'
end
test 'input infers max value from attributes with less than or equal to validation using symbol' do
with_input_for @validating_user, :attempts, :float
assert_select 'input[max="100"]'
with_input_for @validating_user, :attempts, :integer
assert_select 'input[max="100"]'
end
test 'input infers max value from attributes with less than validation using proc' do
with_input_for @other_validating_user, :amount, :float
assert_no_select 'input[max]'
with_input_for @other_validating_user, :amount, :integer
assert_select 'input[max="118"]'
end
test 'input infers max value from attributes with less than or equal to validation using proc' do
with_input_for @other_validating_user, :attempts, :float
assert_select 'input[max="119"]'
with_input_for @other_validating_user, :attempts, :integer
assert_select 'input[max="119"]'
end
test 'input has step value of any except for integer attribute' do
with_input_for @validating_user, :age, :float
assert_select 'input[step="any"]'
with_input_for @validating_user, :age, :integer
assert_select 'input[step="1"]'
end
test 'numeric input does not generate placeholder by default' do
with_input_for @user, :age, :integer
assert_no_select 'input[placeholder]'
end
test 'numeric input accepts the placeholder option' do
with_input_for @user, :age, :integer, placeholder: 'Put in your age'
assert_select 'input.integer[placeholder="Put in your age"]'
end
test 'numeric input uses i18n to translate placeholder text' do
store_translations(:en, simple_form: { placeholders: { user: {
age: 'Age goes here'
} } }) do
with_input_for @user, :age, :integer
assert_select 'input.integer[placeholder="Age goes here"]'
end
end
# Numeric input but HTML5 disabled
test 'when not using HTML5 input does not generate field with type number and use text instead' do
swap_wrapper do
with_input_for @user, :age, :integer
assert_no_select "input[type=number]"
assert_no_select "input#user_age[text]"
end
end
test 'when not using HTML5 input does not use min or max or step attributes' do
swap_wrapper do
with_input_for @validating_user, :age, :integer
assert_no_select "input[type=number]"
assert_no_select "input[min]"
assert_no_select "input[max]"
assert_no_select "input[step]"
end
end
[:integer, :float, :decimal].each do |type|
test "#{type} input infers min value from attributes with greater than or equal validation" do
with_input_for @validating_user, :age, type
assert_select 'input[min="18"]'
end
test "#{type} input infers the max value from attributes with less than or equal to validation" do
with_input_for @validating_user, :age, type
assert_select 'input[max="99"]'
end
end
test 'min_max does not emit max value as bare string' do
with_input_for @other_validating_user, :age, :integer
assert_select 'input[max]'
assert_no_select 'div', %r{^99}
end
end
simple-form-3.2.0/test/inputs/collection_select_input_test.rb 0000644 0001750 0001750 00000040265 12623141213 024760 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class CollectionSelectInputTest < ActionView::TestCase
setup do
SimpleForm::Inputs::CollectionSelectInput.reset_i18n_cache :boolean_collection
end
test 'input generates a boolean select with options by default for select types' do
with_input_for @user, :active, :select
assert_select 'select.select#user_active'
assert_select 'select option[value=true]', 'Yes'
assert_select 'select option[value=false]', 'No'
end
test 'input as select uses i18n to translate select boolean options' do
store_translations(:en, simple_form: { yes: 'Sim', no: 'Não' }) do
with_input_for @user, :active, :select
assert_select 'select option[value=true]', 'Sim'
assert_select 'select option[value=false]', 'Não'
end
end
test 'input allows overriding collection for select types' do
with_input_for @user, :name, :select, collection: ['Jose', 'Carlos']
assert_select 'select.select#user_name'
assert_select 'select option', 'Jose'
assert_select 'select option', 'Carlos'
end
test 'input does automatic collection translation for select types using defaults key' do
store_translations(:en, simple_form: { options: { defaults: {
gender: { male: 'Male', female: 'Female'}
} } }) do
with_input_for @user, :gender, :select, collection: [:male, :female]
assert_select 'select.select#user_gender'
assert_select 'select option', 'Male'
assert_select 'select option', 'Female'
end
end
test 'input does automatic collection translation for select types using specific object key' do
store_translations(:en, simple_form: { options: { user: {
gender: { male: 'Male', female: 'Female'}
} } }) do
with_input_for @user, :gender, :select, collection: [:male, :female]
assert_select 'select.select#user_gender'
assert_select 'select option', 'Male'
assert_select 'select option', 'Female'
end
end
test 'input marks the selected value by default' do
@user.name = "Carlos"
with_input_for @user, :name, :select, collection: ['Jose', 'Carlos']
assert_select 'select option[selected=selected]', 'Carlos'
end
test 'input accepts html options as the last element of collection' do
with_input_for @user, :name, :select, collection: [['Jose', class: 'foo']]
assert_select 'select.select#user_name'
assert_select 'select option.foo', 'Jose'
end
test 'input marks the selected value also when using integers' do
@user.age = 18
with_input_for @user, :age, :select, collection: 18..60
assert_select 'select option[selected=selected]', '18'
end
test 'input marks the selected value when using booleans and select' do
@user.active = false
with_input_for @user, :active, :select
assert_no_select 'select option[selected][value=true]', 'Yes'
assert_select 'select option[selected][value=false]', 'No'
end
test 'input sets the correct value when using a collection that includes floats' do
with_input_for @user, :age, :select, collection: [2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
assert_select 'select option[value="2.0"]'
assert_select 'select option[value="2.5"]'
end
test 'input sets the correct values when using a collection that uses mixed values' do
with_input_for @user, :age, :select, collection: ["Hello Kitty", 2, 4.5, :johnny, nil, true, false]
assert_select 'select option[value="Hello Kitty"]'
assert_select 'select option[value="2"]'
assert_select 'select option[value="4.5"]'
assert_select 'select option[value="johnny"]'
assert_select 'select option[value=""]'
assert_select 'select option[value="true"]'
assert_select 'select option[value="false"]'
end
test 'input includes a blank option even if :include_blank is set to false if the collection includes a nil value' do
with_input_for @user, :age, :select, collection: [nil], include_blank: false
assert_select 'select option[value=""]'
end
test 'input automatically sets include blank' do
with_input_for @user, :age, :select, collection: 18..30
assert_select 'select option[value=""]', ''
end
test 'input translates include blank when set to :translate' do
store_translations(:en, simple_form: { include_blanks: { user: {
age: 'Rather not say'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, include_blank: :translate
assert_select 'select option[value=""]', 'Rather not say'
end
end
test 'input translates include blank with a default' do
store_translations(:en, simple_form: { include_blanks: { defaults: {
age: 'Rather not say',
} } }) do
with_input_for @user, :age, :select, collection: 18..30, include_blank: :translate
assert_select 'select option[value=""]', 'Rather not say'
end
end
test 'input does not translate include blank when set to a string' do
store_translations(:en, simple_form: { include_blanks: { user: {
age: 'Rather not say'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, include_blank: 'Young at heart'
assert_select 'select option[value=""]', 'Young at heart'
end
end
test 'input does not translate include blank when automatically set' do
store_translations(:en, simple_form: { include_blanks: { user: {
age: 'Rather not say'
} } }) do
with_input_for @user, :age, :select, collection: 18..30
assert_select 'select option[value=""]', ''
end
end
test 'input does not translate include blank when set to true' do
store_translations(:en, simple_form: { include_blanks: { user: {
age: 'Rather not say'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, include_blank: true
assert_select 'select option[value=""]', ''
end
end
test 'input does not translate include blank when set to false' do
store_translations(:en, simple_form: { include_blanks: { user: {
age: 'Rather not say'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, include_blank: false
assert_no_select 'select option[value=""]'
end
end
test 'input does not set include blank if otherwise is told' do
with_input_for @user, :age, :select, collection: 18..30, include_blank: false
assert_no_select 'select option[value=""]'
end
test 'input does not set include blank if prompt is given' do
with_input_for @user, :age, :select, collection: 18..30, prompt: "Please select foo"
assert_no_select 'select option[value=""]', ''
end
test 'input does not set include blank if multiple is given' do
with_input_for @user, :age, :select, collection: 18..30, input_html: { multiple: true }
assert_no_select 'select option[value=""]', ''
end
test 'input translates prompt when set to :translate' do
store_translations(:en, simple_form: { prompts: { user: {
age: 'Select age:'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, prompt: :translate
assert_select 'select option[value=""]', 'Select age:'
end
end
test 'input translates prompt with a default' do
store_translations(:en, simple_form: { prompts: { defaults: {
age: 'Select age:',
} } }) do
with_input_for @user, :age, :select, collection: 18..30, prompt: :translate
assert_select 'select option[value=""]', 'Select age:'
end
end
test 'input does not translate prompt when set to a string' do
store_translations(:en, simple_form: { prompts: { user: {
age: 'Select age:'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, prompt: 'Do it:'
assert_select 'select option[value=""]', 'Do it:'
end
end
test 'input does not translate prompt when set to false' do
store_translations(:en, simple_form: { prompts: { user: {
age: 'Select age:'
} } }) do
with_input_for @user, :age, :select, collection: 18..30, prompt: false
assert_no_select 'select option[value=""]'
end
end
test 'input uses Rails prompt translation as a fallback' do
store_translations(:en, helpers: { select: {
prompt: 'Select value:'
} }) do
with_input_for @user, :age, :select, collection: 18..30, prompt: :translate
assert_select 'select option[value=""]', "Select value:"
end
end
test 'input detects label and value on collections' do
users = [User.build(id: 1, name: "Jose"), User.build(id: 2, name: "Carlos")]
with_input_for @user, :description, :select, collection: users
assert_select 'select option[value="1"]', 'Jose'
assert_select 'select option[value="2"]', 'Carlos'
end
test 'input disables the anothers components when the option is a object' do
with_input_for @user, :description, :select, collection: ["Jose", "Carlos"], disabled: true
assert_no_select 'select option[value=Jose][disabled=disabled]', 'Jose'
assert_no_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
assert_select 'select[disabled=disabled]'
assert_select 'div.disabled'
end
test 'input does not disable the anothers components when the option is a object' do
with_input_for @user, :description, :select, collection: ["Jose", "Carlos"], disabled: 'Jose'
assert_select 'select option[value=Jose][disabled=disabled]', 'Jose'
assert_no_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
assert_no_select 'select[disabled=disabled]'
assert_no_select 'div.disabled'
end
test 'input allows overriding label and value method using a lambda for collection selects' do
with_input_for @user, :name, :select,
collection: ['Jose', 'Carlos'],
label_method: lambda { |i| i.upcase },
value_method: lambda { |i| i.downcase }
assert_select 'select option[value=jose]', "JOSE"
assert_select 'select option[value=carlos]', "CARLOS"
end
test 'input allows overriding only label but not value method using a lambda for collection select' do
with_input_for @user, :name, :select,
collection: ['Jose', 'Carlos'],
label_method: lambda { |i| i.upcase }
assert_select 'select option[value=Jose]', "JOSE"
assert_select 'select option[value=Carlos]', "CARLOS"
end
test 'input allows overriding only value but not label method using a lambda for collection select' do
with_input_for @user, :name, :select,
collection: ['Jose', 'Carlos'],
value_method: lambda { |i| i.downcase }
assert_select 'select option[value=jose]', "Jose"
assert_select 'select option[value=carlos]', "Carlos"
end
test 'input allows symbols for collections' do
with_input_for @user, :name, :select, collection: [:jose, :carlos]
assert_select 'select.select#user_name'
assert_select 'select option[value=jose]', 'jose'
assert_select 'select option[value=carlos]', 'carlos'
end
test 'collection input with select type generates required html attribute only with blank option' do
with_input_for @user, :name, :select, include_blank: true, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[required]'
end
test 'collection input with select type generates required html attribute only with blank option or prompt' do
with_input_for @user, :name, :select, prompt: 'Name...', collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[required]'
end
test 'collection input with select type does not generate required html attribute without blank option' do
with_input_for @user, :name, :select, include_blank: false, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_no_select 'select[required]'
assert_no_select 'select[aria-required=true]'
end
test 'collection input with select type with multiple attribute generates required html attribute without blank option' do
with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[required]'
end
test 'collection input with select type with multiple attribute generates required html attribute with blank option' do
with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[required]'
end
test 'with a blank option, a collection input of type select has an aria-required html attribute' do
with_input_for @user, :name, :select, include_blank: true, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[aria-required=true]'
end
test 'without a blank option, a collection input of type select does not have an aria-required html attribute' do
with_input_for @user, :name, :select, include_blank: false, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_no_select 'select[aria-required]'
end
test 'without a blank option and with a multiple option, a collection input of type select has an aria-required html attribute' do
with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[aria-required=true]'
end
test 'with a blank option and a multiple option, a collection input of type select has an aria-required html attribute' do
with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
assert_select 'select.required'
assert_select 'select[aria-required]'
end
test 'input allows disabled options with a lambda for collection select' do
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
disabled: lambda { |x| x == "Carlos" }
assert_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
assert_select 'select option[value=Antonio]', 'Antonio'
assert_no_select 'select option[value=Antonio][disabled]'
end
test 'input allows disabled and label method with lambdas for collection select' do
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
disabled: lambda { |x| x == "Carlos" }, label_method: lambda { |x| x.upcase }
assert_select 'select option[value=Carlos][disabled=disabled]', 'CARLOS'
assert_select 'select option[value=Antonio]', 'ANTONIO'
assert_no_select 'select option[value=Antonio][disabled]'
end
test 'input allows a non lambda disabled option with lambda label method for collections' do
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
disabled: "Carlos", label_method: lambda { |x| x.upcase }
assert_select 'select option[value=Carlos][disabled=disabled]', 'CARLOS'
assert_select 'select option[value=Antonio]', 'ANTONIO'
assert_no_select 'select option[value=Antonio][disabled]'
end
test 'input allows selected and label method with lambdas for collection select' do
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
selected: lambda { |x| x == "Carlos" }, label_method: lambda { |x| x.upcase }
assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
assert_select 'select option[value=Antonio]', 'ANTONIO'
assert_no_select 'select option[value=Antonio][selected]'
end
test 'input allows a non lambda selected option with lambda label method for collection select' do
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
selected: "Carlos", label_method: lambda { |x| x.upcase }
assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
assert_select 'select option[value=Antonio]', 'ANTONIO'
assert_no_select 'select option[value=Antonio][selected]'
end
test 'input does not override default selection through attribute value with label method as lambda for collection select' do
@user.name = "Carlos"
with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
label_method: lambda { |x| x.upcase }
assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
assert_select 'select option[value=Antonio]', 'ANTONIO'
assert_no_select 'select option[value=Antonio][selected]'
end
end
simple-form-3.2.0/test/inputs/readonly_test.rb 0000644 0001750 0001750 00000007666 12623141213 021674 0 ustar terceiro terceiro require 'test_helper'
class ReadonlyTest < ActionView::TestCase
test 'string input generates readonly elements when readonly option is true' do
with_input_for @user, :name, :string, readonly: true
assert_select 'input.string.readonly[readonly]'
end
test 'text input generates readonly elements when readonly option is true' do
with_input_for @user, :description, :text, readonly: true
assert_select 'textarea.text.readonly[readonly]'
end
test 'numeric input generates readonly elements when readonly option is true' do
with_input_for @user, :age, :integer, readonly: true
assert_select 'input.integer.readonly[readonly]'
end
test 'date input generates readonly elements when readonly option is true' do
with_input_for @user, :born_at, :date, readonly: true
assert_select 'select.date.readonly[readonly]'
end
test 'datetime input generates readonly elements when readonly option is true' do
with_input_for @user, :created_at, :datetime, readonly: true
assert_select 'select.datetime.readonly[readonly]'
end
test 'string input generates readonly elements when readonly option is false' do
with_input_for @user, :name, :string, readonly: false
assert_no_select 'input.string.readonly[readonly]'
end
test 'text input generates readonly elements when readonly option is false' do
with_input_for @user, :description, :text, readonly: false
assert_no_select 'textarea.text.readonly[readonly]'
end
test 'numeric input generates readonly elements when readonly option is false' do
with_input_for @user, :age, :integer, readonly: false
assert_no_select 'input.integer.readonly[readonly]'
end
test 'date input generates readonly elements when readonly option is false' do
with_input_for @user, :born_at, :date, readonly: false
assert_no_select 'select.date.readonly[readonly]'
end
test 'datetime input generates readonly elements when readonly option is false' do
with_input_for @user, :created_at, :datetime, readonly: false
assert_no_select 'select.datetime.readonly[readonly]'
end
test 'string input generates readonly elements when readonly option is not present' do
with_input_for @user, :name, :string
assert_no_select 'input.string.readonly[readonly]'
end
test 'text input generates readonly elements when readonly option is not present' do
with_input_for @user, :description, :text
assert_no_select 'textarea.text.readonly[readonly]'
end
test 'numeric input generates readonly elements when readonly option is not present' do
with_input_for @user, :age, :integer
assert_no_select 'input.integer.readonly[readonly]'
end
test 'date input generates readonly elements when readonly option is not present' do
with_input_for @user, :born_at, :date
assert_no_select 'select.date.readonly[readonly]'
end
test 'datetime input generates readonly elements when readonly option is not present' do
with_input_for @user, :created_at, :datetime
assert_no_select 'select.datetime.readonly[readonly]'
end
test 'input generates readonly attribute when the field is readonly and the object is persisted' do
with_input_for @user, :credit_card, :string, readonly: :lookup
assert_select 'input.string.readonly[readonly]'
end
test 'input does not generate readonly attribute when the field is readonly and the object is not persisted' do
@user.new_record!
with_input_for @user, :credit_card, :string, readonly: :lookup
assert_no_select 'input.string.readonly[readonly]'
end
test 'input does not generate readonly attribute when the field is not readonly and the object is persisted' do
with_input_for @user, :name, :string
assert_no_select 'input.string.readonly[readonly]'
end
test 'input does not generate readonly attribute when the component is not used' do
swap_wrapper do
with_input_for @user, :credit_card, :string
assert_no_select 'input.string.readonly[readonly]'
end
end
end
simple-form-3.2.0/test/inputs/string_input_test.rb 0000644 0001750 0001750 00000012447 12623141213 022575 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class StringInputTest < ActionView::TestCase
test 'input maps text field to string attribute' do
with_input_for @user, :name, :string
assert_select "input#user_name[type=text][name='user[name]'][value='New in SimpleForm!']"
end
test 'input generates a password field for password attributes' do
with_input_for @user, :password, :password
assert_select "input#user_password.password[type=password][name='user[password]']"
end
test 'input gets maxlength from column definition for string attributes' do
with_input_for @user, :name, :string
assert_select 'input.string[maxlength="100"]'
end
test 'input does not get maxlength from column without size definition for string attributes' do
with_input_for @user, :action, :string
assert_no_select 'input.string[maxlength]'
end
test 'input gets maxlength from column definition for password attributes' do
with_input_for @user, :password, :password
assert_select 'input.password[type=password][maxlength="100"]'
end
test 'input infers maxlength column definition from validation when present' do
with_input_for @validating_user, :name, :string
assert_select 'input.string[maxlength="25"]'
end
test 'input does not get maxlength from validation when tokenizer present' do
with_input_for @validating_user, :action, :string
assert_no_select 'input.string[maxlength]'
end
test 'input gets maxlength from validation when :is option present' do
with_input_for @validating_user, :home_picture, :string
assert_select 'input.string[maxlength="12"]'
end
test 'input maxlength is the column limit plus one to make room for decimal point' do
with_input_for @user, :credit_limit, :string
assert_select 'input.string[maxlength="16"]'
end
test 'input does not generate placeholder by default' do
with_input_for @user, :name, :string
assert_no_select 'input[placeholder]'
end
test 'input accepts the placeholder option' do
with_input_for @user, :name, :string, placeholder: 'Put in some text'
assert_select 'input.string[placeholder="Put in some text"]'
end
test 'input generates a password field for password attributes that accept placeholder' do
with_input_for @user, :password, :password, placeholder: 'Password Confirmation'
assert_select 'input[type=password].password[placeholder="Password Confirmation"]#user_password'
end
test 'input does not infer pattern from attributes by default' do
with_input_for @other_validating_user, :country, :string
assert_no_select 'input[pattern="\w+"]'
end
test 'input infers pattern from attributes' do
with_input_for @other_validating_user, :country, :string, pattern: true
assert_select 'input[pattern="\w+"]'
end
test 'input infers pattern from attributes using proc' do
with_input_for @other_validating_user, :name, :string, pattern: true
assert_select 'input[pattern="\w+"]'
end
test 'input does not infer pattern from attributes if root default is false' do
swap_wrapper do
with_input_for @other_validating_user, :country, :string
assert_no_select 'input[pattern="\w+"]'
end
end
test 'input uses given pattern from attributes' do
with_input_for @other_validating_user, :country, :string, input_html: { pattern: "\\d+" }
assert_select 'input[pattern="\d+"]'
end
test 'input does not use pattern if model has :without validation option' do
with_input_for @other_validating_user, :description, :string, pattern: true
assert_no_select 'input[pattern="\d+"]'
end
test 'input uses i18n to translate placeholder text' do
store_translations(:en, simple_form: { placeholders: { user: {
name: 'Name goes here'
} } }) do
with_input_for @user, :name, :string
assert_select 'input.string[placeholder="Name goes here"]'
end
end
test 'input uses custom i18n scope to translate placeholder text' do
store_translations(:en, my_scope: { placeholders: { user: {
name: 'Name goes here'
} } }) do
swap SimpleForm, i18n_scope: :my_scope do
with_input_for @user, :name, :string
assert_select 'input.string[placeholder="Name goes here"]'
end
end
end
[:email, :url, :search, :tel].each do |type|
test "input allows type #{type}" do
with_input_for @user, :name, type
assert_select "input.string.#{type}"
assert_select "input[type=#{type}]"
end
test "input does not allow type #{type} if HTML5 compatibility is disabled" do
swap_wrapper do
with_input_for @user, :name, type
assert_select "input[type=text]"
assert_no_select "input[type=#{type}]"
end
end
end
test 'input strips extra spaces from class html attribute with default classes' do
with_input_for @user, :name, :string
assert_select "input[class='string required']"
assert_no_select "input[class='string required ']"
assert_no_select "input[class=' string required']"
end
test 'input strips extra spaces from class html attribute when giving a custom class' do
with_input_for @user, :name, :string, input_html: { class: "my_input" }
assert_select "input[class='string required my_input']"
assert_no_select "input[class='string required my_input ']"
assert_no_select "input[class=' string required my_input']"
end
end
simple-form-3.2.0/test/inputs/text_input_test.rb 0000644 0001750 0001750 00000002353 12623141213 022246 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class TextInputTest < ActionView::TestCase
test 'input generates a text area for text attributes' do
with_input_for @user, :description, :text
assert_select 'textarea.text#user_description'
end
test 'input generates a text area for text attributes that accept placeholder' do
with_input_for @user, :description, :text, placeholder: 'Put in some text'
assert_select 'textarea.text[placeholder="Put in some text"]'
end
test 'input generates a placeholder from the translations' do
store_translations(:en, simple_form: { placeholders: { user: { name: "placeholder from i18n en.simple_form.placeholders.user.name" } } }) do
with_input_for @user, :name, :text
assert_select 'textarea.text[placeholder="placeholder from i18n en.simple_form.placeholders.user.name"]'
end
end
test 'input gets maxlength from column definition for text attributes' do
with_input_for @user, :description, :text
assert_select 'textarea.text[maxlength="200"]'
end
test 'input infers maxlength column definition from validation when present for text attributes' do
with_input_for @validating_user, :description, :text
assert_select 'textarea.text[maxlength="50"]'
end
end
simple-form-3.2.0/test/inputs/disabled_test.rb 0000644 0001750 0001750 00000005566 12623141213 021623 0 ustar terceiro terceiro require 'test_helper'
class DisabledTest < ActionView::TestCase
test 'string input is disabled when disabled option is true' do
with_input_for @user, :name, :string, disabled: true
assert_select 'input.string.disabled[disabled]'
end
test 'text input is disabled when disabled option is true' do
with_input_for @user, :description, :text, disabled: true
assert_select 'textarea.text.disabled[disabled]'
end
test 'numeric input is disabled when disabled option is true' do
with_input_for @user, :age, :integer, disabled: true
assert_select 'input.integer.disabled[disabled]'
end
test 'date input is disabled when disabled option is true' do
with_input_for @user, :born_at, :date, disabled: true
assert_select 'select.date.disabled[disabled]'
end
test 'datetime input is disabled when disabled option is true' do
with_input_for @user, :created_at, :datetime, disabled: true
assert_select 'select.datetime.disabled[disabled]'
end
test 'string input does not be disabled when disabled option is false' do
with_input_for @user, :name, :string, disabled: false
assert_no_select 'input.string.disabled[disabled]'
end
test 'text input does not be disabled when disabled option is false' do
with_input_for @user, :description, :text, disabled: false
assert_no_select 'textarea.text.disabled[disabled]'
end
test 'numeric input does not be disabled when disabled option is false' do
with_input_for @user, :age, :integer, disabled: false
assert_no_select 'input.integer.disabled[disabled]'
end
test 'date input does not be disabled when disabled option is false' do
with_input_for @user, :born_at, :date, disabled: false
assert_no_select 'select.date.disabled[disabled]'
end
test 'datetime input does not be disabled when disabled option is false' do
with_input_for @user, :created_at, :datetime, disabled: false
assert_no_select 'select.datetime.disabled[disabled]'
end
test 'string input does not be disabled when disabled option is not present' do
with_input_for @user, :name, :string
assert_no_select 'input.string.disabled[disabled]'
end
test 'text input does not be disabled when disabled option is not present' do
with_input_for @user, :description, :text
assert_no_select 'textarea.text.disabled[disabled]'
end
test 'numeric input does not be disabled when disabled option is not present' do
with_input_for @user, :age, :integer
assert_no_select 'input.integer.disabled[disabled]'
end
test 'date input does not be disabled when disabled option is not present' do
with_input_for @user, :born_at, :date
assert_no_select 'select.date.disabled[disabled]'
end
test 'datetime input does not be disabled when disabled option is not present' do
with_input_for @user, :created_at, :datetime
assert_no_select 'select.datetime.disabled[disabled]'
end
end
simple-form-3.2.0/test/support/ 0000755 0001750 0001750 00000000000 12623141213 016646 5 ustar terceiro terceiro simple-form-3.2.0/test/support/mock_controller.rb 0000644 0001750 0001750 00000000625 12623141213 022372 0 ustar terceiro terceiro class MockController
attr_writer :action_name
def _routes
self
end
def action_name
defined?(@action_name) ? @action_name : "edit"
end
def url_for(*args)
"http://example.com"
end
def url_options
{}
end
def hash_for_user_path(*); end
def hash_for_validating_user_path(*); end
def hash_for_other_validating_user_path(*); end
def hash_for_users_path(*); end
end
simple-form-3.2.0/test/support/discovery_inputs.rb 0000644 0001750 0001750 00000002317 12623141213 022607 0 ustar terceiro terceiro class StringInput < SimpleForm::Inputs::StringInput
def input(wrapper_options = nil)
"#{super}".html_safe
end
end
class NumericInput < SimpleForm::Inputs::NumericInput
def input(wrapper_options = nil)
"#{super}".html_safe
end
end
class CustomizedInput < SimpleForm::Inputs::StringInput
def input(wrapper_options = nil)
"#{super}".html_safe
end
def input_method
:text_field
end
end
class DeprecatedInput < SimpleForm::Inputs::StringInput
def input
"#{super}".html_safe
end
def input_method
:text_field
end
end
class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
def input_html_classes
super.push('chosen')
end
end
module CustomInputs
class CustomizedInput < SimpleForm::Inputs::StringInput
def input_html_classes
super.push('customized-namespace-custom-input')
end
end
class PasswordInput < SimpleForm::Inputs::PasswordInput
def input_html_classes
super.push('password-custom-input')
end
end
class NumericInput < SimpleForm::Inputs::PasswordInput
def input_html_classes
super.push('numeric-custom-input')
end
end
end
simple-form-3.2.0/test/support/misc_helpers.rb 0000644 0001750 0001750 00000015021 12623141213 021647 0 ustar terceiro terceiro module MiscHelpers
def store_translations(locale, translations, &block)
I18n.backend.store_translations locale, translations
yield
ensure
I18n.reload!
I18n.backend.send :init_translations
end
def assert_no_select(selector, value = nil)
assert_select(selector, text: value, count: 0)
end
def swap(object, new_values)
old_values = {}
new_values.each do |key, value|
old_values[key] = object.send key
object.send :"#{key}=", value
end
yield
ensure
old_values.each do |key, value|
object.send :"#{key}=", value
end
end
def stub_any_instance(klass, method, value)
klass.class_eval do
alias_method :"new_#{method}", method
define_method(method) do
if value.respond_to?(:call)
value.call
else
value
end
end
end
yield
ensure
klass.class_eval do
undef_method method
alias_method method, :"new_#{method}"
undef_method :"new_#{method}"
end
end
def swap_wrapper(name = :default, wrapper = custom_wrapper)
old = SimpleForm.wrappers[name.to_s]
SimpleForm.wrappers[name.to_s] = wrapper
yield
ensure
SimpleForm.wrappers[name.to_s] = old
end
def custom_wrapper
SimpleForm.build tag: :section, class: "custom_wrapper", pattern: false do |b|
b.use :pattern
b.wrapper :another, class: "another_wrapper" do |ba|
ba.use :label
ba.use :input
end
b.wrapper :error_wrapper, tag: :div, class: "error_wrapper" do |be|
be.use :error, wrap_with: { tag: :span, class: "omg_error" }
end
b.use :hint, wrap_with: { class: "omg_hint" }
end
end
def custom_wrapper_with_wrapped_optional_component
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
b.wrapper tag: :div, class: 'no_output_wrapper' do |ba|
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
end
end
end
def custom_wrapper_with_unless_blank
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
b.wrapper tag: :div, class: 'no_output_wrapper', unless_blank: true do |ba|
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
end
end
end
def custom_wrapper_with_input_class
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.use :label
b.use :input, class: 'inline-class'
end
end
def custom_wrapper_with_label_class
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.use :label, class: 'inline-class'
b.use :input
end
end
def custom_wrapper_with_input_attributes
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.use :input, data: { modal: true }
end
end
def custom_wrapper_with_label_input_class
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.use :label_input, class: 'inline-class'
end
end
def custom_wrapper_with_wrapped_input
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.wrapper tag: :div, class: 'elem' do |component|
component.use :label
component.use :input, wrap_with: { tag: :div, class: 'input' }
end
end
end
def custom_wrapper_with_wrapped_label
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
b.wrapper tag: :div, class: 'elem' do |component|
component.use :label, wrap_with: { tag: :div, class: 'label' }
component.use :input
end
end
end
def custom_wrapper_without_top_level
SimpleForm.build tag: false, class: 'custom_wrapper_without_top_level' do |b|
b.use :label_input
b.use :hint, wrap_with: { tag: :span, class: :hint }
b.use :error, wrap_with: { tag: :span, class: :error }
end
end
def custom_wrapper_without_class
SimpleForm.build tag: :div, wrapper_html: { id: 'custom_wrapper_without_class' } do |b|
b.use :label_input
end
end
def custom_wrapper_with_label_html_option
SimpleForm.build tag: :div, class: "custom_wrapper", label_html: { class: 'extra-label-class' } do |b|
b.use :label_input
end
end
def custom_wrapper_with_wrapped_label_input
SimpleForm.build tag: :section, class: "custom_wrapper", pattern: false do |b|
b.use :label_input, wrap_with: { tag: :div, class: :field }
end
end
def custom_wrapper_with_additional_attributes
SimpleForm.build tag: :div, class: 'custom_wrapper', html: { data: { wrapper: :test }, title: 'some title' } do |b|
b.use :label_input
end
end
def custom_wrapper_with_full_error
SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
b.use :full_error, wrap_with: { tag: :span, class: :error }
end
end
def custom_wrapper_with_label_text
SimpleForm.build :label_text => proc { |label, required| "**#{label}**" } do |b|
b.use :label_input
end
end
def custom_wrapper_with_custom_label_component
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
b.use :label_text
end
end
def custom_wrapper_with_html5_components
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
b.use :label_text
end
end
def custom_wrapper_with_required_input
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
b.use :html5
b.use :input, required: true
end
end
def custom_form_for(object, *args, &block)
simple_form_for(object, *args, { builder: CustomFormBuilder }, &block)
end
def custom_mapping_form_for(object, *args, &block)
simple_form_for(object, *args, { builder: CustomMapTypeFormBuilder }, &block)
end
def with_concat_form_for(*args, &block)
concat simple_form_for(*args, &(block || proc {}))
end
def with_concat_fields_for(*args, &block)
concat simple_fields_for(*args, &block)
end
def with_concat_custom_form_for(*args, &block)
concat custom_form_for(*args, &block)
end
def with_concat_custom_mapping_form_for(*args, &block)
concat custom_mapping_form_for(*args, &block)
end
def with_form_for(object, *args, &block)
with_concat_form_for(object) do |f|
f.input(*args, &block)
end
end
def with_input_for(object, attribute_name, type, options = {})
with_concat_form_for(object) do |f|
f.input(attribute_name, options.merge(as: type))
end
end
end
class CustomFormBuilder < SimpleForm::FormBuilder
def input(attribute_name, *args, &block)
super(attribute_name, *args, { input_html: { class: 'custom' } }, &block)
end
end
class CustomMapTypeFormBuilder < SimpleForm::FormBuilder
map_type :custom_type, to: SimpleForm::Inputs::StringInput
end
simple-form-3.2.0/test/support/models.rb 0000644 0001750 0001750 00000016027 12623141213 020464 0 ustar terceiro terceiro Association = Struct.new(:klass, :name, :macro, :scope, :options)
Column = Struct.new(:name, :type, :limit) do
# Returns +true+ if the column is either of type integer, float or decimal.
def number?
type == :integer || type == :float || type == :decimal
end
end
Relation = Struct.new(:records) do
delegate :each, to: :records
def where(conditions = nil)
self.class.new conditions ? records.first : records
end
def order(conditions = nil)
self.class.new conditions ? records.last : records
end
alias_method :to_a, :records
alias_method :to_ary, :records
end
Picture = Struct.new(:id, :name) do
extend ActiveModel::Naming
include ActiveModel::Conversion
def self.where(conditions = nil)
if conditions.is_a?(Hash) && conditions[:name]
all.to_a.last
else
all
end
end
def self.all
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
end
end
Company = Struct.new(:id, :name) do
extend ActiveModel::Naming
include ActiveModel::Conversion
class << self
delegate :order, :where, to: :_relation
end
def self._relation
all
end
def self.all
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
end
def persisted?
true
end
end
class Tag < Company; end
TagGroup = Struct.new(:id, :name, :tags)
class User
extend ActiveModel::Naming
include ActiveModel::Conversion
attr_accessor :id, :name, :company, :company_id, :time_zone, :active, :age,
:description, :created_at, :updated_at, :credit_limit, :password, :url,
:delivery_time, :born_at, :special_company_id, :country, :tags, :tag_ids,
:avatar, :home_picture, :email, :status, :residence_country, :phone_number,
:post_count, :lock_version, :amount, :attempts, :action, :credit_card, :gender,
:extra_special_company_id, :pictures, :picture_ids, :special_pictures,
:special_picture_ids, :uuid
def self.build(extra_attributes = {})
attributes = {
id: 1,
name: 'New in SimpleForm!',
description: 'Hello!',
created_at: Time.now
}.merge! extra_attributes
new attributes
end
def initialize(options = {})
@new_record = false
options.each do |key, value|
send("#{key}=", value)
end if options
end
def new_record!
@new_record = true
end
def persisted?
!@new_record
end
def company_attributes=(*)
end
def tags_attributes=(*)
end
def column_for_attribute(attribute)
column_type, limit = case attribute.to_sym
when :name, :status, :password then [:string, 100]
when :description then [:text, 200]
when :age then :integer
when :credit_limit then [:decimal, 15]
when :active then :boolean
when :born_at then :date
when :delivery_time then :time
when :created_at then :datetime
when :updated_at then :timestamp
when :lock_version then :integer
when :home_picture then :string
when :amount then :integer
when :attempts then :integer
when :action then :string
when :credit_card then :string
when :uuid then :uuid
end
Column.new(attribute, column_type, limit)
end
def has_attribute?(attribute)
case attribute.to_sym
when :name, :status, :password, :description, :age,
:credit_limit, :active, :born_at, :delivery_time,
:created_at, :updated_at, :lock_version, :home_picture,
:amount, :attempts, :action, :credit_card, :uuid then true
else false
end
end
def self.human_attribute_name(attribute, options = {})
case attribute
when 'name'
'Super User Name!'
when 'description'
'User Description!'
when 'company'
'Company Human Name!'
else
attribute.to_s.humanize
end
end
def self.reflect_on_association(association)
case association
when :company
Association.new(Company, association, :belongs_to, nil, {})
when :tags
Association.new(Tag, association, :has_many, nil, {})
when :first_company
Association.new(Company, association, :has_one, nil, {})
when :special_company
Association.new(Company, association, :belongs_to, nil, { conditions: { id: 1 } })
when :extra_special_company
Association.new(Company, association, :belongs_to, nil, { conditions: proc { { id: self.id } } })
when :pictures
Association.new(Picture, association, :has_many, nil, {})
when :special_pictures
Association.new(Picture, association, :has_many, proc { where(name: self.name) }, {})
end
end
def errors
@errors ||= begin
errors = ActiveModel::Errors.new(self)
errors.add(:name, "cannot be blank")
errors.add(:description, 'must be longer than 15 characters')
errors.add(:age, 'is not a number')
errors.add(:age, 'must be greater than 18')
errors.add(:company, 'company must be present')
errors.add(:company_id, 'must be valid')
errors
end
end
def self.readonly_attributes
["credit_card"]
end
end
class ValidatingUser < User
include ActiveModel::Validations
validates :name, presence: true
validates :company, presence: true
validates :age, presence: true, if: Proc.new { |user| user.name }
validates :amount, presence: true, unless: Proc.new { |user| user.age }
validates :action, presence: true, on: :create
validates :credit_limit, presence: true, on: :save
validates :phone_number, presence: true, on: :update
validates_numericality_of :age,
greater_than_or_equal_to: 18,
less_than_or_equal_to: 99,
only_integer: true
validates_numericality_of :amount,
greater_than: :min_amount,
less_than: :max_amount,
only_integer: true
validates_numericality_of :attempts,
greater_than_or_equal_to: :min_attempts,
less_than_or_equal_to: :max_attempts,
only_integer: true
validates_length_of :name, maximum: 25
validates_length_of :description, maximum: 50
validates_length_of :action, maximum: 10, tokenizer: lambda { |str| str.scan(/\w+/) }
validates_length_of :home_picture, is: 12
def min_amount
10
end
def max_amount
100
end
def min_attempts
1
end
def max_attempts
100
end
end
class OtherValidatingUser < User
include ActiveModel::Validations
validates_numericality_of :age,
greater_than: 17,
less_than: 100,
only_integer: true
validates_numericality_of :amount,
greater_than: Proc.new { |user| user.age },
less_than: Proc.new { |user| user.age + 100 },
only_integer: true
validates_numericality_of :attempts,
greater_than_or_equal_to: Proc.new { |user| user.age },
less_than_or_equal_to: Proc.new { |user| user.age + 100 },
only_integer: true
validates_format_of :country, with: /\w+/
validates_format_of :name, with: Proc.new { /\w+/ }
validates_format_of :description, without: /\d+/
end
class HashBackedAuthor < Hash
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?; false; end
def name
'hash backed author'
end
end
class UserNumber1And2 < User
end
simple-form-3.2.0/test/generators/ 0000755 0001750 0001750 00000000000 12623141213 017303 5 ustar terceiro terceiro simple-form-3.2.0/test/generators/simple_form_generator_test.rb 0000644 0001750 0001750 00000003225 12623141213 025253 0 ustar terceiro terceiro require 'test_helper'
class SimpleFormGeneratorTest < Rails::Generators::TestCase
tests SimpleForm::Generators::InstallGenerator
destination File.expand_path('../../tmp', __FILE__)
setup :prepare_destination
teardown { rm_rf(destination_root) }
test 'generates example locale file' do
run_generator
assert_file 'config/locales/simple_form.en.yml'
end
test 'generates the simple_form initializer' do
run_generator
assert_file 'config/initializers/simple_form.rb',
/config\.default_wrapper = :default/, /config\.boolean_style = :nested/
end
test 'generates the simple_form initializer with the bootstrap wrappers' do
run_generator %w(--bootstrap)
assert_file 'config/initializers/simple_form.rb',
/config\.default_wrapper = :default/, /config\.boolean_style = :nested/
assert_file 'config/initializers/simple_form_bootstrap.rb', /config\.wrappers :vertical_form/,
/config\.wrappers :horizontal_form/, /config\.default_wrapper = :vertical_form/
end
test 'generates the simple_form initializer with the foundation wrappers' do
run_generator %w(--foundation)
assert_file 'config/initializers/simple_form.rb',
/config\.default_wrapper = :default/, /config\.boolean_style = :nested/
assert_file 'config/initializers/simple_form_foundation.rb', /config\.wrappers :vertical_form/,
/config\.default_wrapper = :vertical_form/, /config\.item_wrapper_tag = :div/
end
%W(erb haml slim).each do |engine|
test "generates the scaffold template when using #{engine}" do
run_generator ['-e', engine]
assert_file "lib/templates/#{engine}/scaffold/_form.html.#{engine}"
end
end
end
simple-form-3.2.0/test/simple_form_test.rb 0000644 0001750 0001750 00000000566 12623141213 021041 0 ustar terceiro terceiro require 'test_helper'
class SimpleFormTest < ActiveSupport::TestCase
test 'setup block yields self' do
SimpleForm.setup do |config|
assert_equal SimpleForm, config
end
end
test 'setup block configure Simple Form' do
SimpleForm.setup do |config|
assert_equal SimpleForm, config
end
assert_equal true, SimpleForm.configured?
end
end
simple-form-3.2.0/test/form_builder/ 0000755 0001750 0001750 00000000000 12623141213 017603 5 ustar terceiro terceiro simple-form-3.2.0/test/form_builder/error_test.rb 0000644 0001750 0001750 00000017442 12623141213 022330 0 ustar terceiro terceiro require 'test_helper'
# Tests for f.error and f.full_error
class ErrorTest < ActionView::TestCase
def with_error_for(object, *args)
with_concat_form_for(object) do |f|
f.error(*args)
end
end
def with_full_error_for(object, *args)
with_concat_form_for(object) do |f|
f.full_error(*args)
end
end
test 'error does not generate content for attribute without errors' do
with_error_for @user, :active
assert_no_select 'span.error'
end
test 'error does not generate messages when object is not present' do
with_error_for :project, :name
assert_no_select 'span.error'
end
test "error does not generate messages when object doesn't respond to errors method" do
@user.instance_eval { undef errors }
with_error_for @user, :name
assert_no_select 'span.error'
end
test 'error generates messages for attribute with single error' do
with_error_for @user, :name
assert_select 'span.error', "cannot be blank"
end
test 'error generates messages for attribute with one error when using first' do
swap SimpleForm, error_method: :first do
with_error_for @user, :age
assert_select 'span.error', 'is not a number'
end
end
test 'error generates messages for attribute with several errors when using to_sentence' do
swap SimpleForm, error_method: :to_sentence do
with_error_for @user, :age
assert_select 'span.error', 'is not a number and must be greater than 18'
end
end
test 'error is able to pass html options' do
with_error_for @user, :name, id: 'error', class: 'yay'
assert_select 'span#error.error.yay'
end
test 'error does not modify the options hash' do
options = { id: 'error', class: 'yay' }
with_error_for @user, :name, options
assert_select 'span#error.error.yay'
assert_equal({ id: 'error', class: 'yay' }, options)
end
test 'error finds errors on attribute and association' do
with_error_for @user, :company_id, as: :select,
error_method: :to_sentence, reflection: Association.new(Company, :company, {})
assert_select 'span.error', 'must be valid and company must be present'
end
test 'error generates an error tag with a clean HTML' do
with_error_for @user, :name
assert_no_select 'span.error[error_html]'
end
test 'error generates an error tag with a clean HTML when errors options are present' do
with_error_for @user, :name, error_tag: :p, error_prefix: 'Name', error_method: :first
assert_no_select 'p.error[error_html]'
assert_no_select 'p.error[error_tag]'
assert_no_select 'p.error[error_prefix]'
assert_no_select 'p.error[error_method]'
end
test 'error escapes error prefix text' do
with_error_for @user, :name, error_prefix: 'Name'
assert_no_select 'span.error b'
end
test 'error escapes error text' do
@user.errors.add(:action, 'must not contain markup')
with_error_for @user, :action
assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end
test 'error generates an error message with raw HTML tags' do
with_error_for @user, :name, error_prefix: 'Name'.html_safe
assert_select 'span.error', "Name cannot be blank"
assert_select 'span.error b', "Name"
end
# FULL ERRORS
test 'full error generates a full error tag for the attribute' do
with_full_error_for @user, :name
assert_select 'span.error', "Super User Name! cannot be blank"
end
test 'full error generates a full error tag with a clean HTML' do
with_full_error_for @user, :name
assert_no_select 'span.error[error_html]'
end
test 'full error allows passing options to full error tag' do
with_full_error_for @user, :name, id: 'name_error', error_prefix: "Your name"
assert_select 'span.error#name_error', "Your name cannot be blank"
end
test 'full error does not modify the options hash' do
options = { id: 'name_error' }
with_full_error_for @user, :name, options
assert_select 'span.error#name_error', "Super User Name! cannot be blank"
assert_equal({ id: 'name_error' }, options)
end
test 'full error escapes error text' do
@user.errors.add(:action, 'must not contain markup')
with_full_error_for @user, :action
assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end
# CUSTOM WRAPPERS
test 'error with custom wrappers works' do
swap_wrapper do
with_error_for @user, :name
assert_select 'span.omg_error', "cannot be blank"
end
end
# FULL_ERROR_WRAPPER
test 'full error finds errors on association' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :company_id, as: :select
assert_select 'span.error', 'Company must be valid'
end
end
test 'full error finds errors on association with reflection' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :company_id, as: :select,
reflection: Association.new(Company, :company, {})
assert_select 'span.error', 'Company must be valid'
end
end
test 'full error can be disabled' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :company_id, as: :select, full_error: false
assert_no_select 'span.error'
end
end
test 'full error can be disabled setting error to false' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :company_id, as: :select, error: false
assert_no_select 'span.error'
end
end
# CUSTOM ERRORS
test 'input with custom error works' do
error_text = "Super User Name! cannot be blank"
with_form_for @user, :name, error: error_text
assert_select 'span.error', error_text
end
test 'input with error option as true does not use custom error' do
with_form_for @user, :name, error: true
assert_select 'span.error', "cannot be blank"
end
test 'input with custom error does not generate the error if there is no error on the attribute' do
with_form_for @user, :active, error: "Super User Active! cannot be blank"
assert_no_select 'span.error'
end
test 'input with custom error works when using full_error component' do
swap_wrapper :default, custom_wrapper_with_full_error do
error_text = "Super User Name! cannot be blank"
with_form_for @user, :name, error: error_text
assert_select 'span.error', error_text
end
end
test 'input with custom error escapes the error text' do
with_form_for @user, :name, error: 'error must not contain markup'
assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end
test 'input with custom error does not escape the error text if it is safe' do
with_form_for @user, :name, error: 'error must contain markup'.html_safe
assert_select 'span.error'
assert_select 'span.error b', 'markup'
end
test 'input with custom error escapes the error text using full_error component' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :name, error: 'error must not contain markup'
assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end
end
test 'input with custom error does not escape the error text if it is safe using full_error component' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :name, error: 'error must contain markup'.html_safe
assert_select 'span.error'
assert_select 'span.error b', 'markup'
end
end
test 'input with custom error when using full_error component does not generate the error if there is no error on the attribute' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :active, error: "Super User Active! can't be blank"
assert_no_select 'span.error'
end
end
end
simple-form-3.2.0/test/form_builder/label_test.rb 0000644 0001750 0001750 00000010472 12623141213 022252 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class LabelTest < ActionView::TestCase
def with_label_for(object, *args, &block)
with_concat_form_for(object) do |f|
f.label(*args, &block)
end
end
test 'builder generates a label for the attribute' do
with_label_for @user, :name
assert_select 'label.string[for=user_name]', /Name/
end
test 'builder generates a label for the boolean attrbiute' do
with_label_for @user, :name, as: :boolean
assert_select 'label.boolean[for=user_name]', /Name/
assert_no_select 'label[as=boolean]'
end
test 'builder generates a label component tag with a clean HTML' do
with_label_for @user, :name
assert_no_select 'label.string[label_html]'
end
test 'builder adds a required class to label if the attribute is required' do
with_label_for @validating_user, :name
assert_select 'label.string.required[for=validating_user_name]', /Name/
end
test 'builder adds a disabled class to label if the attribute is disabled' do
with_label_for @validating_user, :name, disabled: true
assert_select 'label.string.disabled[for=validating_user_name]', /Name/
end
test 'builder does not add a disabled class to label if the attribute is not disabled' do
with_label_for @validating_user, :name, disabled: false
assert_no_select 'label.string.disabled[for=validating_user_name]', /Name/
end
test 'builder escapes label text' do
with_label_for @user, :name, label: '', required: false
assert_no_select 'label.string script'
end
test 'builder does not escape label text if it is safe' do
with_label_for @user, :name, label: ''.html_safe, required: false
assert_select 'label.string script', "alert(1337)"
end
test 'builder allows passing options to label tag' do
with_label_for @user, :name, label: 'My label', id: 'name_label'
assert_select 'label.string#name_label', /My label/
end
test 'builder label generates label tag with clean HTML' do
with_label_for @user, :name, label: 'My label', required: true, id: 'name_label'
assert_select 'label.string#name_label', /My label/
assert_no_select 'label[label]'
assert_no_select 'label[required]'
end
test 'builder does not modify the options hash' do
options = { label: 'My label', id: 'name_label' }
with_label_for @user, :name, options
assert_select 'label.string#name_label', /My label/
assert_equal({ label: 'My label', id: 'name_label' }, options)
end
test 'builder fallbacks to default label when string is given' do
with_label_for @user, :name, 'Nome do usuário'
assert_select 'label', 'Nome do usuário'
assert_no_select 'label.string'
end
test 'builder fallbacks to default label when block is given' do
with_label_for @user, :name do
'Nome do usuário'
end
assert_select 'label', 'Nome do usuário'
assert_no_select 'label.string'
end
test 'builder allows label order to be changed' do
swap SimpleForm, label_text: proc { |l, r| "#{l}:" } do
with_label_for @user, :age
assert_select 'label.integer[for=user_age]', "Age:"
end
end
test 'configuration allow set label text for wrappers' do
swap_wrapper :default, custom_wrapper_with_label_text do
with_concat_form_for(@user) do |f|
concat f.input :age
end
assert_select "label.integer[for=user_age]", "**Age**"
end
end
test 'configuration allow set rewrited label tag for wrappers' do
swap_wrapper :default, custom_wrapper_with_custom_label_component do
with_concat_form_for(@user) do |f|
concat f.input :age
end
assert_select "span.integer.user_age", /Age/
end
end
test 'builder allows custom formatting when label is explicitly specified' do
swap SimpleForm, label_text: lambda { |l, r, explicit_label| explicit_label ? l : "#{l.titleize}:" } do
with_label_for @user, :time_zone, 'What is your home time zone?'
assert_select 'label[for=user_time_zone]', 'What is your home time zone?'
end
end
test 'builder allows custom formatting when label is generated' do
swap SimpleForm, label_text: lambda { |l, r, explicit_label| explicit_label ? l : "#{l.titleize}:" } do
with_label_for @user, :time_zone
assert_select 'label[for=user_time_zone]', 'Time Zone:'
end
end
end
simple-form-3.2.0/test/form_builder/hint_test.rb 0000644 0001750 0001750 00000010766 12623141213 022143 0 ustar terceiro terceiro require 'test_helper'
# Tests for f.hint
class HintTest < ActionView::TestCase
def with_hint_for(object, *args)
with_concat_form_for(object) do |f|
f.hint(*args)
end
end
test 'hint does not be generated by default' do
with_hint_for @user, :name
assert_no_select 'span.hint'
end
test 'hint is generated with optional text' do
with_hint_for @user, :name, hint: 'Use with care...'
assert_select 'span.hint', 'Use with care...'
end
test 'hint does not modify the options hash' do
options = { hint: 'Use with care...' }
with_hint_for @user, :name, options
assert_select 'span.hint', 'Use with care...'
assert_equal({ hint: 'Use with care...' }, options)
end
test 'hint is generated cleanly with optional text' do
with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :span
assert_no_select 'span.hint[hint]'
assert_no_select 'span.hint[hint_tag]'
assert_no_select 'span.hint[hint_html]'
end
test 'hint uses the current component tag set' do
with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :p
assert_select 'p.hint', 'Use with care...'
end
test 'hint is able to pass html options' do
with_hint_for @user, :name, hint: 'Yay!', id: 'hint', class: 'yay'
assert_select 'span#hint.hint.yay'
end
test 'hint is output as html_safe' do
with_hint_for @user, :name, hint: 'Bold and not...'.html_safe
assert_select 'span.hint', 'Bold and not...'
assert_select 'span.hint b', 'Bold'
end
test 'builder escapes hint text' do
with_hint_for @user, :name, hint: ''
assert_no_select 'span.hint script'
end
# Without attribute name
test 'hint without attribute name' do
with_hint_for @validating_user, 'Hello World!'
assert_select 'span.hint', 'Hello World!'
end
test 'hint without attribute name generates component tag with a clean HTML' do
with_hint_for @validating_user, 'Hello World!'
assert_no_select 'span.hint[hint]'
assert_no_select 'span.hint[hint_html]'
end
test 'hint without attribute name uses the current component tag set' do
with_hint_for @user, 'Hello World!', hint_tag: :p
assert_no_select 'p.hint[hint]'
assert_no_select 'p.hint[hint_html]'
assert_no_select 'p.hint[hint_tag]'
end
test 'hint without attribute name is able to pass html options' do
with_hint_for @user, 'Yay', id: 'hint', class: 'yay'
assert_select 'span#hint.hint.yay', 'Yay'
end
# I18n
test 'hint uses i18n based on model, action, and attribute to lookup translation' do
store_translations(:en, simple_form: { hints: { user: {
edit: { name: 'Content of this input will be truncated...' }
} } }) do
with_hint_for @user, :name
assert_select 'span.hint', 'Content of this input will be truncated...'
end
end
test 'hint uses i18n with model and attribute to lookup translation' do
store_translations(:en, simple_form: { hints: { user: {
name: 'Content of this input will be capitalized...'
} } }) do
with_hint_for @user, :name
assert_select 'span.hint', 'Content of this input will be capitalized...'
end
end
test 'hint uses i18n under defaults namespace to lookup translation' do
store_translations(:en, simple_form: {
hints: { defaults: { name: 'Content of this input will be downcased...' } }
}) do
with_hint_for @user, :name
assert_select 'span.hint', 'Content of this input will be downcased...'
end
end
test 'hint uses i18n with lookup for association name' do
store_translations(:en, simple_form: { hints: {
user: { company: 'My company!' }
} } ) do
with_hint_for @user, :company_id, as: :string, reflection: Association.new(Company, :company, {})
assert_select 'span.hint', /My company!/
end
end
test 'hint outputs translations as html_safe' do
store_translations(:en, simple_form: { hints: { user: {
edit: { name: 'This is bold and this is not...' }
} } }) do
with_hint_for @user, :name
assert_select 'span.hint', 'This is bold and this is not...'
end
end
# No object
test 'hint generates properly when object is not present' do
with_hint_for :project, :name, hint: 'Test without object'
assert_select 'span.hint', 'Test without object'
end
# Custom wrappers
test 'hint with custom wrappers works' do
swap_wrapper do
with_hint_for @user, :name, hint: "cannot be blank"
assert_select 'div.omg_hint', "cannot be blank"
end
end
end
simple-form-3.2.0/test/form_builder/error_notification_test.rb 0000644 0001750 0001750 00000005755 12623141213 025102 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
# Tests for f.error_notification
class ErrorNotificationTest < ActionView::TestCase
def with_error_notification_for(object, options = {}, &block)
with_concat_form_for(object) do |f|
f.error_notification(options)
end
end
test 'error notification is not generated when the object has no error' do
assert @validating_user.valid?
with_error_notification_for @validating_user
assert_no_select 'p.error_notification'
end
test 'error notification is not generated for forms without objects' do
with_error_notification_for :user
assert_no_select 'p.error_notification'
end
test 'error notification is generated when the object has some error' do
with_error_notification_for @user
assert_select 'p.error_notification', 'Please review the problems below:'
end
test 'error notification uses I18n based on model to generate the notification message' do
store_translations(:en, simple_form: { error_notification: { user:
'Alguns erros foram encontrados para o usuário:'
} }) do
with_error_notification_for @user
assert_select 'p.error_notification', 'Alguns erros foram encontrados para o usuário:'
end
end
test 'error notification uses I18n fallbacking to default message' do
store_translations(:en, simple_form: { error_notification: {
default_message: 'Opa! Alguns erros foram encontrados, poderia verificar?'
} }) do
with_error_notification_for @user
assert_select 'p.error_notification', 'Opa! Alguns erros foram encontrados, poderia verificar?'
end
end
test 'error notification allows passing the notification message' do
with_error_notification_for @user, message: 'Erro encontrado ao criar usuario'
assert_select 'p.error_notification', 'Erro encontrado ao criar usuario'
end
test 'error notification accepts other html options' do
with_error_notification_for @user, id: 'user_error_message', class: 'form_error'
assert_select 'p#user_error_message.form_error.error_notification'
end
test 'error notification allows configuring the wrapper element' do
swap SimpleForm, error_notification_tag: :div do
with_error_notification_for @user
assert_select 'div.error_notification'
end
end
test 'error notification can contain HTML tags' do
with_error_notification_for @user, message: 'Erro encontrado ao criar usuário'
assert_select 'p.error_notification', 'Erro encontrado ao criar usuário'
assert_select 'p.error_notification b', 'usuário'
end
test 'error notification uses I18n based on model to generate the notification message and accepts HTML' do
store_translations(:en, simple_form: { error_notification: { user:
'Alguns erros foram encontrados para o usuário:'
} }) do
with_error_notification_for @user
assert_select 'p.error_notification', 'Alguns erros foram encontrados para o usuário:'
assert_select 'p.error_notification b', 'usuário'
end
end
end
simple-form-3.2.0/test/form_builder/button_test.rb 0000644 0001750 0001750 00000002701 12623141213 022502 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class ButtonTest < ActionView::TestCase
def with_button_for(object, *args)
with_concat_form_for(object) do |f|
f.button(*args)
end
end
test 'builder creates buttons' do
with_button_for :post, :submit
assert_select 'form input.button[type=submit][value="Save Post"]'
end
test 'builder creates buttons with options' do
with_button_for :post, :submit, class: 'my_button'
assert_select 'form input.button.my_button[type=submit][value="Save Post"]'
end
test 'builder does not modify the options hash' do
options = { class: 'my_button' }
with_button_for :post, :submit, options
assert_select 'form input.button.my_button[type=submit][value="Save Post"]'
assert_equal({ class: 'my_button' }, options)
end
test 'builder creates buttons for records' do
@user.new_record!
with_button_for @user, :submit
assert_select 'form input.button[type=submit][value="Create User"]'
end
test "builder uses the default class from the configuration" do
swap SimpleForm, button_class: 'btn' do
with_button_for :post, :submit
assert_select 'form input.btn[type=submit][value="Save Post"]'
end
end
if ActionView::Helpers::FormBuilder.method_defined?(:button)
test "allows to use Rails button helper when available" do
with_button_for :post, :button, 'Save!'
assert_select 'form button.button[type=submit]', 'Save!'
end
end
end
simple-form-3.2.0/test/form_builder/input_field_test.rb 0000644 0001750 0001750 00000011537 12623141213 023500 0 ustar terceiro terceiro require 'test_helper'
# Tests for f.input_field
class InputFieldTest < ActionView::TestCase
def with_input_field_for(object, *args)
with_concat_form_for(object) do |f|
f.input_field(*args)
end
end
test "builder input_field only renders the input tag, nothing else" do
with_input_field_for @user, :name
assert_select 'form > input.required.string'
assert_no_select 'div.string'
assert_no_select 'label'
assert_no_select '.hint'
end
test 'builder input_field allows overriding default input type' do
with_input_field_for @user, :name, as: :text
assert_no_select 'input#user_name'
assert_select 'textarea#user_name.text'
end
test 'builder input_field generates input type based on column type' do
with_input_field_for @user, :age
assert_select 'input[type=number].integer#user_age'
end
test 'builder input_field is able to disable any component' do
with_input_field_for @user, :age, html5: false
assert_no_select 'input[html5=false]#user_age'
assert_select 'input[type=text].integer#user_age'
end
test 'builder input_field allows passing options to input tag' do
with_input_field_for @user, :name, id: 'name_input', class: 'name'
assert_select 'input.string.name#name_input'
end
test 'builder input_field does not modify the options hash' do
options = { id: 'name_input', class: 'name' }
with_input_field_for @user, :name, options
assert_select 'input.string.name#name_input'
assert_equal({ id: 'name_input', class: 'name' }, options)
end
test 'builder input_field generates an input tag with a clean HTML' do
with_input_field_for @user, :name, as: :integer, class: 'name'
assert_no_select 'input.integer[input_html]'
assert_no_select 'input.integer[as]'
end
test 'builder input_field uses i18n to translate placeholder text' do
store_translations(:en, simple_form: { placeholders: { user: {
name: 'Name goes here'
} } }) do
with_input_field_for @user, :name
assert_select 'input.string[placeholder="Name goes here"]'
end
end
test 'builder input_field uses min_max component' do
with_input_field_for @other_validating_user, :age, as: :integer
assert_select 'input[min="18"]'
end
test 'builder input_field does not use pattern component by default' do
with_input_field_for @other_validating_user, :country, as: :string
assert_no_select 'input[pattern="\w+"]'
end
test 'builder input_field infers pattern from attributes' do
with_input_field_for @other_validating_user, :country, as: :string, pattern: true
assert_select 'input[pattern="\w+"]'
end
test 'builder input_field accepts custom patter' do
with_input_field_for @other_validating_user, :country, as: :string, pattern: '\d+'
assert_select 'input[pattern="\d+"]'
end
test 'builder input_field uses readonly component' do
with_input_field_for @other_validating_user, :age, as: :integer, readonly: true
assert_select 'input.integer.readonly[readonly]'
end
test 'builder input_field uses maxlength component' do
with_input_field_for @validating_user, :name, as: :string
assert_select 'input.string[maxlength="25"]'
end
test 'builder collection input_field generates input tag with a clean HTML' do
with_input_field_for @user, :status, collection: ['Open', 'Closed'],
class: 'status', label_method: :to_s, value_method: :to_s
assert_no_select 'select.status[input_html]'
assert_no_select 'select.status[collection]'
assert_no_select 'select.status[label_method]'
assert_no_select 'select.status[value_method]'
end
test 'build input_field does not treat "boolean_style" as a HTML attribute' do
with_input_field_for @user, :active, boolean_style: :nested
assert_no_select 'input.boolean[boolean_style]'
end
test 'build input_field without pattern component use the pattern string' do
swap_wrapper :default, custom_wrapper_with_html5_components do
with_input_field_for @user, :name, pattern: '\w+'
assert_select 'input[pattern="\w+"]'
end
end
test 'build input_field without placeholder component use the placeholder string' do
swap_wrapper :default, custom_wrapper_with_html5_components do
with_input_field_for @user, :name, placeholder: 'Placeholder'
assert_select 'input[placeholder="Placeholder"]'
end
end
test 'build input_field without maxlength component use the maxlength string' do
swap_wrapper :default, custom_wrapper_with_html5_components do
with_input_field_for @user, :name, maxlength: 5
assert_select 'input[maxlength="5"]'
end
end
test 'build input_field without readonly component use the readonly string' do
swap_wrapper :default, custom_wrapper_with_html5_components do
with_input_field_for @user, :name, readonly: true
assert_select 'input[readonly="readonly"]'
end
end
end
simple-form-3.2.0/test/form_builder/wrapper_test.rb 0000644 0001750 0001750 00000025214 12623141213 022653 0 ustar terceiro terceiro require 'test_helper'
class WrapperTest < ActionView::TestCase
test 'wrapper does not have error class for attribute without errors' do
with_form_for @user, :active
assert_no_select 'div.field_with_errors'
end
test 'wrapper does not have error class when object is not present' do
with_form_for :project, :name
assert_no_select 'div.field_with_errors'
end
test 'wrapper adds the attribute name class' do
with_form_for @user, :name
assert_select 'div.user_name'
end
test 'wrapper adds the attribute name class for nested forms' do
@user.company = Company.new(1, 'Empresa')
with_concat_form_for @user do |f|
concat(f.simple_fields_for(:company) do |company_form|
concat(company_form.input :name)
end)
end
assert_select 'div.user_company_name'
end
test 'wrapper adds the association name class' do
with_form_for @user, :company
assert_select 'div.user_company'
end
test 'wrapper adds error class for attribute with errors' do
with_form_for @user, :name
assert_select 'div.field_with_errors'
end
test 'wrapper adds hint class for attribute with a hint' do
with_form_for @user, :name, hint: 'hint'
assert_select 'div.field_with_hint'
end
test 'wrapper does not have disabled class by default' do
with_form_for @user, :active
assert_no_select 'div.disabled'
end
test 'wrapper has disabled class when input is disabled' do
with_form_for @user, :active, disabled: true
assert_select 'div.disabled'
end
test 'wrapper supports no wrapping when wrapper is false' do
with_form_for @user, :name, wrapper: false
assert_select 'form > label[for=user_name]'
assert_select 'form > input#user_name.string'
end
test 'wrapper supports no wrapping when wrapper tag is false' do
with_form_for @user, :name, wrapper: custom_wrapper_without_top_level
assert_select 'form > label[for=user_name]'
assert_select 'form > input#user_name.string'
end
test 'wrapper wraps tag adds required/optional css classes' do
with_form_for @user, :name
assert_select 'form div.input.required.string'
with_form_for @user, :age, required: false
assert_select 'form div.input.optional.integer'
end
test 'wrapper allows custom options to be given' do
with_form_for @user, :name, wrapper_html: { id: "super_cool", class: 'yay' }
assert_select 'form #super_cool.required.string.yay'
end
test 'wrapper allows tag to be given on demand' do
with_form_for @user, :name, wrapper_tag: :b
assert_select 'form b.required.string'
end
test 'wrapper allows wrapper class to be given on demand' do
with_form_for @user, :name, wrapper_class: :wrapper
assert_select 'form div.wrapper.required.string'
end
test 'wrapper skips additional classes when configured' do
swap SimpleForm, generate_additional_classes_for: [:input, :label] do
with_form_for @user, :name, wrapper_class: :wrapper
assert_select 'form div.wrapper'
assert_no_select 'div.required'
assert_no_select 'div.string'
assert_no_select 'div.user_name'
end
end
test 'wrapper does not generate empty css class' do
swap SimpleForm, generate_additional_classes_for: [:input, :label] do
swap_wrapper :default, custom_wrapper_without_class do
with_form_for @user, :name
assert_no_select 'div#custom_wrapper_without_class[class]'
end
end
end
# Custom wrapper test
test 'custom wrappers works' do
swap_wrapper do
with_form_for @user, :name, hint: "cool"
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
assert_no_select "section.custom_wrapper div.another_wrapper span.omg_error"
assert_select "section.custom_wrapper div.error_wrapper span.omg_error"
assert_select "section.custom_wrapper > div.omg_hint", "cool"
end
end
test 'custom wrappers can be turned off' do
swap_wrapper do
with_form_for @user, :name, another: false
assert_no_select "section.custom_wrapper div.another_wrapper label"
assert_no_select "section.custom_wrapper div.another_wrapper input.string"
assert_select "section.custom_wrapper div.error_wrapper span.omg_error"
end
end
test 'custom wrappers can have additional attributes' do
swap_wrapper :default, custom_wrapper_with_additional_attributes do
with_form_for @user, :name
assert_select "div.custom_wrapper[title='some title'][data-wrapper='test']"
end
end
test 'custom wrappers can have full error message on attributes' do
swap_wrapper :default, custom_wrapper_with_full_error do
with_form_for @user, :name
assert_select 'span.error', "Name cannot be blank"
end
end
test 'custom wrappers on a form basis' do
swap_wrapper :another do
with_concat_form_for(@user) do |f|
f.input :name
end
assert_no_select "section.custom_wrapper div.another_wrapper label"
assert_no_select "section.custom_wrapper div.another_wrapper input.string"
with_concat_form_for(@user, wrapper: :another) do |f|
f.input :name
end
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
end
test 'custom wrappers on input basis' do
swap_wrapper :another do
with_form_for @user, :name
assert_no_select "section.custom_wrapper div.another_wrapper label"
assert_no_select "section.custom_wrapper div.another_wrapper input.string"
output_buffer.replace ""
with_form_for @user, :name, wrapper: :another
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
output_buffer.replace ""
end
with_form_for @user, :name, wrapper: custom_wrapper
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
test 'access wrappers with indifferent access' do
swap_wrapper :another do
with_form_for @user, :name, wrapper: "another"
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
end
test 'does not duplicate label classes for different inputs' do
swap_wrapper :default, custom_wrapper_with_label_html_option do
with_concat_form_for(@user) do |f|
concat f.input :name, required: false
concat f.input :email, as: :email, required: true
end
assert_select "label.string.optional.extra-label-class[for='user_name']"
assert_select "label.email.required.extra-label-class[for='user_email']"
assert_no_select "label.string.optional.extra-label-class[for='user_email']"
end
end
test 'raise error when wrapper not found' do
assert_raise SimpleForm::WrapperNotFound do
with_form_for @user, :name, wrapper: :not_found
end
end
test 'uses wrapper for specified in config mapping' do
swap_wrapper :another do
swap SimpleForm, wrapper_mappings: { string: :another } do
with_form_for @user, :name
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
end
end
test 'uses custom wrapper mapping per form basis' do
swap_wrapper :another do
with_concat_form_for @user, wrapper_mappings: { string: :another } do |f|
concat f.input :name
end
end
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
test 'simple_fields_form reuses custom wrapper mapping per form basis' do
@user.company = Company.new(1, 'Empresa')
swap_wrapper :another do
with_concat_form_for @user, wrapper_mappings: { string: :another } do |f|
concat(f.simple_fields_for(:company) do |company_form|
concat(company_form.input(:name))
end)
end
end
assert_select "section.custom_wrapper div.another_wrapper label"
assert_select "section.custom_wrapper div.another_wrapper input.string"
end
test 'input accepts attributes in the DSL' do
swap_wrapper :default, custom_wrapper_with_input_class do
with_concat_form_for @user do |f|
concat f.input :name
end
end
assert_select "div.custom_wrapper input.string.inline-class"
end
test 'label accepts attributes in the DSL' do
swap_wrapper :default, custom_wrapper_with_label_class do
with_concat_form_for @user do |f|
concat f.input :name
end
end
assert_select "div.custom_wrapper label.string.inline-class"
end
test 'label_input accepts attributes in the DSL' do
swap_wrapper :default, custom_wrapper_with_label_input_class do
with_concat_form_for @user do |f|
concat f.input :name
end
end
assert_select "div.custom_wrapper label.string.inline-class"
assert_select "div.custom_wrapper input.string.inline-class"
end
test 'input accepts data attributes in the DSL' do
swap_wrapper :default, custom_wrapper_with_input_attributes do
with_concat_form_for @user do |f|
concat f.input :name
end
end
assert_select "div.custom_wrapper input.string[data-modal=true]"
end
test 'inline wrapper displays when there is content' do
swap_wrapper :default, custom_wrapper_with_wrapped_optional_component do
with_form_for @user, :name, hint: "cannot be blank"
assert_select 'section.custom_wrapper div.no_output_wrapper p.omg_hint', "cannot be blank"
assert_select 'p.omg_hint'
end
end
test 'inline wrapper does not display when there is no content' do
swap_wrapper :default, custom_wrapper_with_wrapped_optional_component do
with_form_for @user, :name
assert_select 'section.custom_wrapper div.no_output_wrapper'
assert_no_select 'p.omg_hint'
end
end
test 'optional wrapper does not display when there is content' do
swap_wrapper :default, custom_wrapper_with_unless_blank do
with_form_for @user, :name, hint: "can't be blank"
assert_select 'section.custom_wrapper div.no_output_wrapper'
assert_select 'div.no_output_wrapper'
assert_select 'p.omg_hint'
end
end
test 'optional wrapper does not display when there is no content' do
swap_wrapper :default, custom_wrapper_with_unless_blank do
with_form_for @user, :name
assert_no_select 'section.custom_wrapper div.no_output_wrapper'
assert_no_select 'div.no_output_wrapper'
assert_no_select 'p.omg_hint'
end
end
end
simple-form-3.2.0/test/form_builder/association_test.rb 0000644 0001750 0001750 00000020453 12623141213 023507 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class AssociationTest < ActionView::TestCase
def with_association_for(object, *args)
with_concat_form_for(object) do |f|
f.association(*args)
end
end
test 'builder does not allow creating an association input when no object exists' do
assert_raise ArgumentError do
with_association_for :post, :author
end
end
test 'builder association with a block calls simple_fields_for' do
simple_form_for @user do |f|
f.association :posts do |posts_form|
assert posts_form.instance_of?(SimpleForm::FormBuilder)
end
end
end
test 'builder association forwards collection to simple_fields_for' do
calls = 0
simple_form_for @user do |f|
f.association :company, collection: Company.all do |c|
calls += 1
end
end
assert_equal 3, calls
end
test 'builder association marks input as required based on both association and attribute' do
swap SimpleForm, required_by_default: false do
with_association_for @validating_user, :company, collection: []
assert_select 'label.required'
end
end
test 'builder preloads collection association' do
value = @user.tags = MiniTest::Mock.new
value.expect(:to_a, value)
with_association_for @user, :tags
assert_select 'form select.select#user_tag_ids'
assert_select 'form select option[value="1"]', 'Tag 1'
assert_select 'form select option[value="2"]', 'Tag 2'
assert_select 'form select option[value="3"]', 'Tag 3'
value.verify
end
test 'builder does not preload collection association if preload is false' do
value = @user.tags = MiniTest::Mock.new
value.expect(:to_a, nil)
with_association_for @user, :tags, preload: false
assert_select 'form select.select#user_tag_ids'
assert_select 'form select option[value="1"]', 'Tag 1'
assert_select 'form select option[value="2"]', 'Tag 2'
assert_select 'form select option[value="3"]', 'Tag 3'
assert_raises MockExpectationError do
value.verify
end
end
test 'builder does not preload non-collection association' do
value = @user.company = MiniTest::Mock.new
value.expect(:to_a, nil)
with_association_for @user, :company
assert_select 'form select.select#user_company_id'
assert_select 'form select option[value="1"]', 'Company 1'
assert_select 'form select option[value="2"]', 'Company 2'
assert_select 'form select option[value="3"]', 'Company 3'
assert_raises MockExpectationError do
value.verify
end
end
# ASSOCIATIONS - BELONGS TO
test 'builder creates a select for belongs_to associations' do
with_association_for @user, :company
assert_select 'form select.select#user_company_id'
assert_select 'form select option[value="1"]', 'Company 1'
assert_select 'form select option[value="2"]', 'Company 2'
assert_select 'form select option[value="3"]', 'Company 3'
end
test 'builder creates blank select if collection is nil' do
with_association_for @user, :company, collection: nil
assert_select 'form select.select#user_company_id'
assert_no_select 'form select option[value="1"]', 'Company 1'
end
test 'builder allows collection radio for belongs_to associations' do
with_association_for @user, :company, as: :radio_buttons
assert_select 'form input.radio_buttons#user_company_id_1'
assert_select 'form input.radio_buttons#user_company_id_2'
assert_select 'form input.radio_buttons#user_company_id_3'
end
test 'builder allows collection to have a proc as a condition' do
with_association_for @user, :extra_special_company
assert_select 'form select.select#user_extra_special_company_id'
assert_select 'form select option[value="1"]'
assert_no_select 'form select option[value="2"]'
assert_no_select 'form select option[value="3"]'
end
test 'builder allows collection to have a scope' do
with_association_for @user, :special_pictures
assert_select 'form select.select#user_special_picture_ids'
assert_select 'form select option[value="3"]', '3'
assert_no_select 'form select option[value="1"]'
assert_no_select 'form select option[value="2"]'
end
test 'builder marks the record which already belongs to the user' do
@user.company_id = 2
with_association_for @user, :company, as: :radio_buttons
assert_no_select 'form input.radio_buttons#user_company_id_1[checked=checked]'
assert_select 'form input.radio_buttons#user_company_id_2[checked=checked]'
assert_no_select 'form input.radio_buttons#user_company_id_3[checked=checked]'
end
# ASSOCIATIONS - FINDERS
test 'builder uses reflection conditions to find collection' do
with_association_for @user, :special_company
assert_select 'form select.select#user_special_company_id'
assert_select 'form select option[value="1"]'
assert_no_select 'form select option[value="2"]'
assert_no_select 'form select option[value="3"]'
end
test 'builder allows overriding collection to association input' do
with_association_for @user, :company, include_blank: false,
collection: [Company.new(999, 'Teste')]
assert_select 'form select.select#user_company_id'
assert_no_select 'form select option[value="1"]'
assert_select 'form select option[value="999"]', 'Teste'
assert_select 'form select option', count: 1
end
# ASSOCIATIONS - has_*
test 'builder does not allow has_one associations' do
assert_raise ArgumentError do
with_association_for @user, :first_company, as: :radio_buttons
end
end
test 'builder does not call order if the given association does not respond to it' do
with_association_for @user, :pictures
assert_select 'form select.select#user_picture_ids'
assert_select 'form select[multiple=multiple]'
assert_select 'form select option[value="1"]', 'Picture 1'
assert_select 'form select option[value="2"]', 'Picture 2'
assert_select 'form select option[value="3"]', 'Picture 3'
end
test 'builder creates a select with multiple options for collection associations' do
with_association_for @user, :tags
assert_select 'form select.select#user_tag_ids'
assert_select 'form select[multiple=multiple]'
assert_select 'form select option[value="1"]', 'Tag 1'
assert_select 'form select option[value="2"]', 'Tag 2'
assert_select 'form select option[value="3"]', 'Tag 3'
end
test 'builder allows size to be overwritten for collection associations' do
with_association_for @user, :tags, input_html: { size: 10 }
assert_select 'form select[multiple=multiple][size="10"]'
end
test 'builder marks all selected records which already belongs to user' do
@user.tag_ids = [1, 2]
with_association_for @user, :tags
assert_select 'form select option[value="1"][selected=selected]'
assert_select 'form select option[value="2"][selected=selected]'
assert_no_select 'form select option[value="3"][selected=selected]'
end
test 'builder allows a collection of check boxes for collection associations' do
@user.tag_ids = [1, 2]
with_association_for @user, :tags, as: :check_boxes
assert_select 'form input#user_tag_ids_1[type=checkbox]'
assert_select 'form input#user_tag_ids_2[type=checkbox]'
assert_select 'form input#user_tag_ids_3[type=checkbox]'
end
test 'builder marks all selected records for collection boxes' do
@user.tag_ids = [1, 2]
with_association_for @user, :tags, as: :check_boxes
assert_select 'form input[type=checkbox][value="1"][checked=checked]'
assert_select 'form input[type=checkbox][value="2"][checked=checked]'
assert_no_select 'form input[type=checkbox][value="3"][checked=checked]'
end
test 'builder with collection support giving collection and item wrapper tags' do
with_association_for @user, :tags, as: :check_boxes,
collection_wrapper_tag: :ul, item_wrapper_tag: :li
assert_select 'form ul', count: 1
assert_select 'form ul li', count: 3
end
test 'builder with collection support does not change the options hash' do
options = { as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li}
with_association_for @user, :tags, options
assert_select 'form ul', count: 1
assert_select 'form ul li', count: 3
assert_equal({ as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li},
options)
end
end
simple-form-3.2.0/test/form_builder/general_test.rb 0000644 0001750 0001750 00000040710 12623141213 022606 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
class FormBuilderTest < ActionView::TestCase
def with_custom_form_for(object, *args, &block)
with_concat_custom_form_for(object) do |f|
f.input(*args, &block)
end
end
test 'nested simple fields yields an instance of FormBuilder' do
simple_form_for :user do |f|
f.simple_fields_for :posts do |posts_form|
assert posts_form.instance_of?(SimpleForm::FormBuilder)
end
end
end
test 'builder input is html safe' do
simple_form_for @user do |f|
assert f.input(:name).html_safe?
end
end
test 'builder works without controller' do
stub_any_instance ActionView::TestCase, :controller, nil do
simple_form_for @user do |f|
assert f.input(:name)
end
end
end
test 'builder input allows a block to configure input' do
with_form_for @user, :name do
text_field_tag :foo, :bar, id: :cool
end
assert_no_select 'input.string'
assert_select 'input#cool'
end
test 'builder allows adding custom input mappings for default input types' do
swap SimpleForm, input_mappings: { /count$/ => :integer } do
with_form_for @user, :post_count
assert_no_select 'form input#user_post_count.string'
assert_select 'form input#user_post_count.numeric.integer'
end
end
test 'builder does not override custom input mappings for custom collection' do
swap SimpleForm, input_mappings: { /gender$/ => :check_boxes } do
with_concat_form_for @user do |f|
f.input :gender, collection: [:male, :female]
end
assert_no_select 'select option', 'Male'
assert_select 'input[type=checkbox][value=male]'
end
end
test 'builder allows to skip input_type class' do
swap SimpleForm, generate_additional_classes_for: [:label, :wrapper] do
with_form_for @user, :post_count
assert_no_select "form input#user_post_count.integer"
assert_select "form input#user_post_count"
end
end
test 'builder allows to add additional classes only for wrapper' do
swap SimpleForm, generate_additional_classes_for: [:wrapper] do
with_form_for @user, :post_count
assert_no_select "form input#user_post_count.string"
assert_no_select "form label#user_post_count.string"
assert_select "form div.input.string"
end
end
test 'builder allows adding custom input mappings for integer input types' do
swap SimpleForm, input_mappings: { /lock_version/ => :hidden } do
with_form_for @user, :lock_version
assert_no_select 'form input#user_lock_version.integer'
assert_select 'form input#user_lock_version.hidden'
end
end
test 'builder uses the first matching custom input map when more than one matches' do
swap SimpleForm, input_mappings: { /count$/ => :integer, /^post_/ => :password } do
with_form_for @user, :post_count
assert_no_select 'form input#user_post_count.password'
assert_select 'form input#user_post_count.numeric.integer'
end
end
test 'builder uses the custom map only for matched attributes' do
swap SimpleForm, input_mappings: { /lock_version/ => :hidden } do
with_form_for @user, :post_count
assert_no_select 'form input#user_post_count.hidden'
assert_select 'form input#user_post_count.string'
end
end
test 'builder allow to use numbers in the model name' do
user = UserNumber1And2.build(tags: [Tag.new(nil, 'Tag1')])
with_concat_form_for(user, url: '/') do |f|
f.simple_fields_for(:tags) do |tags|
tags.input :name
end
end
assert_select 'form .user_number1_and2_tags_name'
assert_no_select 'form .user_number1_and2_tags_1_name'
end
# INPUT TYPES
test 'builder generates text fields for string columns' do
with_form_for @user, :name
assert_select 'form input#user_name.string'
end
test 'builder generates text areas for text columns' do
with_form_for @user, :description
assert_select 'form textarea#user_description.text'
end
test 'builder generates a checkbox for boolean columns' do
with_form_for @user, :active
assert_select 'form input[type=checkbox]#user_active.boolean'
end
test 'builder uses integer text field for integer columns' do
with_form_for @user, :age
assert_select 'form input#user_age.numeric.integer'
end
test 'builder generates decimal text field for decimal columns' do
with_form_for @user, :credit_limit
assert_select 'form input#user_credit_limit.numeric.decimal'
end
test 'builder generates uuid fields for uuid columns' do
with_form_for @user, :uuid
assert_select 'form input#user_uuid.string.uuid'
end
test 'builder generates password fields for columns that matches password' do
with_form_for @user, :password
assert_select 'form input#user_password.password'
end
test 'builder generates country fields for columns that matches country' do
with_form_for @user, :residence_country
assert_select 'form select#user_residence_country.country'
end
test 'builder generates time_zone fields for columns that matches time_zone' do
with_form_for @user, :time_zone
assert_select 'form select#user_time_zone.time_zone'
end
test 'builder generates email fields for columns that matches email' do
with_form_for @user, :email
assert_select 'form input#user_email.string.email'
end
test 'builder generates tel fields for columns that matches phone' do
with_form_for @user, :phone_number
assert_select 'form input#user_phone_number.string.tel'
end
test 'builder generates url fields for columns that matches url' do
with_form_for @user, :url
assert_select 'form input#user_url.string.url'
end
test 'builder generates date select for date columns' do
with_form_for @user, :born_at
assert_select 'form select#user_born_at_1i.date'
end
test 'builder generates time select for time columns' do
with_form_for @user, :delivery_time
assert_select 'form select#user_delivery_time_4i.time'
end
test 'builder generates datetime select for datetime columns' do
with_form_for @user, :created_at
assert_select 'form select#user_created_at_1i.datetime'
end
test 'builder generates datetime select for timestamp columns' do
with_form_for @user, :updated_at
assert_select 'form select#user_updated_at_1i.datetime'
end
test 'builder generates file for file columns' do
@user.avatar = MiniTest::Mock.new
@user.avatar.expect(:public_filename, true)
with_form_for @user, :avatar
assert_select 'form input#user_avatar.file'
end
test 'builder generates file for attributes that are real db columns but have file methods' do
@user.home_picture = MiniTest::Mock.new
@user.home_picture.expect(:mounted_as, true)
with_form_for @user, :home_picture
assert_select 'form input#user_home_picture.file'
end
test 'build generates select if a collection is given' do
with_form_for @user, :age, collection: 1..60
assert_select 'form select#user_age.select'
end
test 'builder allows overriding default input type for text' do
with_form_for @user, :name, as: :text
assert_no_select 'form input#user_name'
assert_select 'form textarea#user_name.text'
with_form_for @user, :active, as: :radio_buttons
assert_no_select 'form input[type=checkbox]'
assert_select 'form input.radio_buttons[type=radio]', count: 2
with_form_for @user, :born_at, as: :string
assert_no_select 'form select'
assert_select 'form input#user_born_at.string'
end
# COMMON OPTIONS
# Remove this test when SimpleForm.form_class is removed in 4.x
test 'builder adds chosen form class' do
ActiveSupport::Deprecation.silence do
swap SimpleForm, form_class: :my_custom_class do
with_form_for @user, :name
assert_select 'form.my_custom_class'
end
end
end
# Remove this test when SimpleForm.form_class is removed in 4.x
test 'builder adds chosen form class and default form class' do
ActiveSupport::Deprecation.silence do
swap SimpleForm, form_class: "my_custom_class", default_form_class: "my_default_class" do
with_form_for @user, :name
assert_select 'form.my_custom_class.my_default_class'
end
end
end
test 'builder adds default form class' do
swap SimpleForm, default_form_class: "default_class" do
with_form_for @user, :name
assert_select 'form.default_class'
end
end
test 'builder allows passing options to input' do
with_form_for @user, :name, input_html: { class: 'my_input', id: 'my_input' }
assert_select 'form input#my_input.my_input.string'
end
test 'builder does not propagate input options to wrapper' do
with_form_for @user, :name, input_html: { class: 'my_input', id: 'my_input' }
assert_no_select 'form div.input.my_input.string'
assert_select 'form input#my_input.my_input.string'
end
test 'builder does not propagate input options to wrapper with custom wrapper' do
swap_wrapper :default, custom_wrapper_with_wrapped_input do
with_form_for @user, :name, input_html: { class: 'my_input' }
assert_no_select 'form div.input.my_input'
assert_select 'form input.my_input.string'
end
end
test 'builder does not propagate label options to wrapper with custom wrapper' do
swap_wrapper :default, custom_wrapper_with_wrapped_label do
with_form_for @user, :name, label_html: { class: 'my_label' }
assert_no_select 'form div.label.my_label'
assert_select 'form label.my_label.string'
end
end
test 'builder generates an input with label' do
with_form_for @user, :name
assert_select 'form label.string[for=user_name]', /Name/
end
test 'builder is able to disable the label for an input' do
with_form_for @user, :name, label: false
assert_no_select 'form label'
end
test 'builder is able to disable the label for an input and return a html safe string' do
with_form_for @user, :name, label: false, wrapper: custom_wrapper_with_wrapped_label_input
assert_select 'form input#user_name'
end
test 'builder uses custom label' do
with_form_for @user, :name, label: 'Yay!'
assert_select 'form label', /Yay!/
end
test 'builder passes options to label' do
with_form_for @user, :name, label_html: { id: "cool" }
assert_select 'form label#cool', /Name/
end
test 'builder does not generate hints for an input' do
with_form_for @user, :name
assert_no_select 'span.hint'
end
test 'builder is able to add a hint for an input' do
with_form_for @user, :name, hint: 'test'
assert_select 'span.hint', 'test'
end
test 'builder is able to disable a hint even if it exists in i18n' do
store_translations(:en, simple_form: { hints: { name: 'Hint test' } }) do
stub_any_instance(SimpleForm::Inputs::Base, :hint, -> { raise 'Never' }) do
with_form_for @user, :name, hint: false
assert_no_select 'span.hint'
end
end
end
test 'builder passes options to hint' do
with_form_for @user, :name, hint: 'test', hint_html: { id: "cool" }
assert_select 'span.hint#cool', 'test'
end
test 'builder generates errors for attribute without errors' do
with_form_for @user, :credit_limit
assert_no_select 'span.errors'
end
test 'builder generates errors for attribute with errors' do
with_form_for @user, :name
assert_select 'span.error', "cannot be blank"
end
test 'builder is able to disable showing errors for an input' do
with_form_for @user, :name, error: false
assert_no_select 'span.error'
end
test 'builder passes options to errors' do
with_form_for @user, :name, error_html: { id: "cool" }
assert_select 'span.error#cool', "cannot be blank"
end
test 'placeholder does not be generated when set to false' do
store_translations(:en, simple_form: { placeholders: { user: {
name: 'Name goes here'
} } }) do
with_form_for @user, :name, placeholder: false
assert_no_select 'input[placeholder]'
end
end
# DEFAULT OPTIONS
[:input, :input_field].each do |method|
test "builder receives a default argument and pass it to the inputs when calling '#{method}'" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
f.public_send(method, :name)
end
assert_select 'input.default_class'
end
test "builder receives a default argument and pass it to the inputs without changing the defaults when calling '#{method}'" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class', id: 'default_id' } } do |f|
concat(f.public_send(method, :name))
concat(f.public_send(method, :credit_limit))
end
assert_select "input.string.default_class[name='user[name]']"
assert_no_select "input.string[name='user[credit_limit]']"
end
test "builder receives a default argument and pass it to the inputs and nested form when calling '#{method}'" do
@user.company = Company.new(1, 'Empresa')
with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
concat(f.public_send(method, :name))
concat(f.simple_fields_for(:company) do |company_form|
concat(company_form.public_send(method, :name))
end)
end
assert_select "input.string.default_class[name='user[name]']"
assert_select "input.string.default_class[name='user[company_attributes][name]']"
end
end
test "builder receives a default argument and pass it to the inputs when calling 'input', respecting the specific options" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
f.input :name, input_html: { id: 'specific_id' }
end
assert_select 'input.default_class#specific_id'
end
test "builder receives a default argument and pass it to the inputs when calling 'input_field', respecting the specific options" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
f.input_field :name, id: 'specific_id'
end
assert_select 'input.default_class#specific_id'
end
test "builder receives a default argument and pass it to the inputs when calling 'input', overwriting the defaults with specific options" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class', id: 'default_id' } } do |f|
f.input :name, input_html: { id: 'specific_id' }
end
assert_select 'input.default_class#specific_id'
end
test "builder receives a default argument and pass it to the inputs when calling 'input_field', overwriting the defaults with specific options" do
with_concat_form_for @user, defaults: { input_html: { class: 'default_class', id: 'default_id' } } do |f|
f.input_field :name, id: 'specific_id'
end
assert_select 'input.default_class#specific_id'
end
# WITHOUT OBJECT
test 'builder generates properly when object is not present' do
with_form_for :project, :name
assert_select 'form input.string#project_name'
end
test 'builder generates password fields based on attribute name when object is not present' do
with_form_for :project, :password_confirmation
assert_select 'form input[type=password].password#project_password_confirmation'
end
test 'builder generates text fields by default for all attributes when object is not present' do
with_form_for :project, :created_at
assert_select 'form input.string#project_created_at'
with_form_for :project, :budget
assert_select 'form input.string#project_budget'
end
test 'builder allows overriding input type when object is not present' do
with_form_for :project, :created_at, as: :datetime
assert_select 'form select.datetime#project_created_at_1i'
with_form_for :project, :budget, as: :decimal
assert_select 'form input.decimal#project_budget'
end
# CUSTOM FORM BUILDER
test 'custom builder inherits mappings' do
with_custom_form_for @user, :email
assert_select 'form input[type=email]#user_email.custom'
end
test 'form with CustomMapTypeFormBuilder uses custom map type builder' do
with_concat_custom_mapping_form_for(:user) do |user|
assert user.instance_of?(CustomMapTypeFormBuilder)
end
end
test 'form with CustomMapTypeFormBuilder uses custom mapping' do
with_concat_custom_mapping_form_for(:user) do |user|
assert_equal SimpleForm::Inputs::StringInput, user.class.mappings[:custom_type]
end
end
test 'form without CustomMapTypeFormBuilder does not use custom mapping' do
with_concat_form_for(:user) do |user|
assert_nil user.class.mappings[:custom_type]
end
end
end
simple-form-3.2.0/test/components/ 0000755 0001750 0001750 00000000000 12623141213 017317 5 ustar terceiro terceiro simple-form-3.2.0/test/components/label_test.rb 0000644 0001750 0001750 00000026741 12623141213 021774 0 ustar terceiro terceiro # encoding: UTF-8
require 'test_helper'
# Isolated tests for label without triggering f.label.
class IsolatedLabelTest < ActionView::TestCase
setup do
SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
end
def with_label_for(object, attribute_name, type, options = {})
with_concat_form_for(object) do |f|
options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association)
SimpleForm::Inputs::Base.new(f, attribute_name, nil, type, options).label
end
end
test 'label generates a default humanized description' do
with_label_for @user, :name, :string
assert_select 'label[for=user_name]', /Name/
end
test 'label allows a customized description' do
with_label_for @user, :name, :string, label: 'My label!'
assert_select 'label[for=user_name]', /My label!/
end
test 'label uses human attribute name from object when available' do
with_label_for @user, :description, :text
assert_select 'label[for=user_description]', /User Description!/
end
test 'label uses human attribute name based on association name' do
with_label_for @user, :company_id, :string, setup_association: true
assert_select 'label', /Company Human Name!/
end
test 'label uses i18n based on model, action, and attribute to lookup translation' do
@controller.action_name = "new"
store_translations(:en, simple_form: { labels: { user: {
new: { description: 'Nova descrição' }
} } }) do
with_label_for @user, :description, :text
assert_select 'label[for=user_description]', /Nova descrição/
end
end
test 'label fallbacks to new when action is create' do
@controller.action_name = "create"
store_translations(:en, simple_form: { labels: { user: {
new: { description: 'Nova descrição' }
} } }) do
with_label_for @user, :description, :text
assert_select 'label[for=user_description]', /Nova descrição/
end
end
test 'label does not explode while looking for i18n translation when action is not set' do
def @controller.action_name; nil; end
assert_nothing_raised do
with_label_for @user, :description, :text
end
assert_select 'label[for=user_description]'
end
test 'label uses i18n based on model and attribute to lookup translation' do
store_translations(:en, simple_form: { labels: { user: {
description: 'Descrição'
} } }) do
with_label_for @user, :description, :text
assert_select 'label[for=user_description]', /Descrição/
end
end
test 'label uses i18n under defaults to lookup translation' do
store_translations(:en, simple_form: { labels: { defaults: { age: 'Idade' } } }) do
with_label_for @user, :age, :integer
assert_select 'label[for=user_age]', /Idade/
end
end
test 'label does not use i18n label if translate is false' do
swap SimpleForm, translate_labels: false do
store_translations(:en, simple_form: { labels: { defaults: { age: 'Idade' } } }) do
with_label_for @user, :age, :integer
assert_select 'label[for=user_age]', /Age/
end
end
end
test 'label uses i18n with lookup for association name' do
store_translations(:en, simple_form: { labels: {
user: { company: 'My company!' }
} }) do
with_label_for @user, :company_id, :string, setup_association: true
assert_select 'label[for=user_company_id]', /My company!/
end
end
test 'label uses i18n under defaults namespace to lookup for association name' do
store_translations(:en, simple_form: { labels: {
defaults: { company: 'Plataformatec' }
} }) do
with_label_for @user, :company, :string, setup_association: true
assert_select 'form label', /Plataformatec/
end
end
test 'label does correct i18n lookup for nested models with nested translation' do
@user.company = Company.new(1, 'Empresa')
store_translations(:en, simple_form: { labels: {
user: { name: 'Usuario', company: { name: 'Nome da empresa' } }
} }) do
with_concat_form_for @user do |f|
concat f.input :name
concat(f.simple_fields_for(:company) do |company_form|
concat(company_form.input :name)
end)
end
assert_select 'label[for=user_name]', /Usuario/
assert_select 'label[for=user_company_attributes_name]', /Nome da empresa/
end
end
test 'label does correct i18n lookup for nested models with no nested translation' do
@user.company = Company.new(1, 'Empresa')
store_translations(:en, simple_form: { labels: {
user: { name: 'Usuario' },
company: { name: 'Nome da empresa' }
} }) do
with_concat_form_for @user do |f|
concat f.input :name
concat(f.simple_fields_for(:company) do |company_form|
concat(company_form.input :name)
end)
end
assert_select 'label[for=user_name]', /Usuario/
assert_select 'label[for=user_company_attributes_name]', /Nome da empresa/
end
end
test 'label does correct i18n lookup for nested has_many models with no nested translation' do
@user.tags = [Tag.new(1, 'Empresa')]
store_translations(:en, simple_form: { labels: {
user: { name: 'Usuario' },
tags: { name: 'Nome da empresa' }
} }) do
with_concat_form_for @user do |f|
concat f.input :name
concat(f.simple_fields_for(:tags, child_index: "new_index") do |tags_form|
concat(tags_form.input :name)
end)
end
assert_select 'label[for=user_name]', /Usuario/
assert_select 'label[for=user_tags_attributes_new_index_name]', /Nome da empresa/
end
end
test 'label has css class from type' do
with_label_for @user, :name, :string
assert_select 'label.string'
with_label_for @user, :description, :text
assert_select 'label.text'
with_label_for @user, :age, :integer
assert_select 'label.integer'
with_label_for @user, :born_at, :date
assert_select 'label.date'
with_label_for @user, :created_at, :datetime
assert_select 'label.datetime'
end
test 'label does not have css class from type when generate_additional_classes_for does not include :label' do
swap SimpleForm, generate_additional_classes_for: [:wrapper, :input] do
with_label_for @user, :name, :string
assert_no_select 'label.string'
with_label_for @user, :description, :text
assert_no_select 'label.text'
with_label_for @user, :age, :integer
assert_no_select 'label.integer'
with_label_for @user, :born_at, :date
assert_no_select 'label.date'
with_label_for @user, :created_at, :datetime
assert_no_select 'label.datetime'
end
end
test 'label does not generate empty css class' do
swap SimpleForm, generate_additional_classes_for: [:wrapper, :input] do
with_label_for @user, :name, :string
assert_no_select 'label[class]'
end
end
test 'label obtains required from ActiveModel::Validations when it is included' do
with_label_for @validating_user, :name, :string
assert_select 'label.required'
with_label_for @validating_user, :status, :string
assert_select 'label.optional'
end
test 'label does not obtain required from ActiveModel::Validations when generate_additional_classes_for does not include :label' do
swap SimpleForm, generate_additional_classes_for: [:wrapper, :input] do
with_label_for @validating_user, :name, :string
assert_no_select 'label.required'
with_label_for @validating_user, :status, :string
assert_no_select 'label.optional'
end
end
test 'label allows overriding required when ActiveModel::Validations is included' do
with_label_for @validating_user, :name, :string, required: false
assert_select 'label.optional'
with_label_for @validating_user, :status, :string, required: true
assert_select 'label.required'
end
test 'label is required by default when ActiveModel::Validations is not included' do
with_label_for @user, :name, :string
assert_select 'label.required'
end
test 'label is able to disable required when ActiveModel::Validations is not included' do
with_label_for @user, :name, :string, required: false
assert_no_select 'label.required'
end
test 'label adds required text when required' do
with_label_for @user, :name, :string
assert_select 'label.required abbr[title=required]', '*'
end
test 'label does not have required text in no required inputs' do
with_label_for @user, :name, :string, required: false
assert_no_select 'form label abbr'
end
test 'label uses i18n to find required text' do
store_translations(:en, simple_form: { required: { text: 'campo requerido' } }) do
with_label_for @user, :name, :string
assert_select 'form label abbr[title="campo requerido"]', '*'
end
end
test 'label uses i18n to find required mark' do
store_translations(:en, simple_form: { required: { mark: '*-*' } }) do
with_label_for @user, :name, :string
assert_select 'form label abbr', '*-*'
end
end
test 'label uses i18n to find required string tag' do
store_translations(:en, simple_form: { required: { html: '*' } }) do
with_label_for @user, :name, :string
assert_no_select 'form label abbr'
assert_select 'form label span.required[title=requerido]', '*'
end
end
test 'label allows overwriting input id' do
with_label_for @user, :name, :string, input_html: { id: 'my_new_id' }
assert_select 'label[for=my_new_id]'
end
test 'label allows overwriting of for attribute' do
with_label_for @user, :name, :string, label_html: { for: 'my_new_id' }
assert_select 'label[for=my_new_id]'
end
test 'label allows overwriting of for attribute with input_html not containing id' do
with_label_for @user, :name, :string, label_html: { for: 'my_new_id' }, input_html: { class: 'foo' }
assert_select 'label[for=my_new_id]'
end
test 'label uses default input id when it was not overridden' do
with_label_for @user, :name, :string, input_html: { class: 'my_new_id' }
assert_select 'label[for=user_name]'
end
test 'label is generated properly when object is not present' do
with_label_for :project, :name, :string
assert_select 'label[for=project_name]', /Name/
end
test 'label includes for attribute for select collection' do
with_label_for @user, :sex, :select, collection: [:male, :female]
assert_select 'label[for=user_sex]'
end
test 'label uses i18n properly when object is not present' do
store_translations(:en, simple_form: { labels: {
project: { name: 'Nome' }
} }) do
with_label_for :project, :name, :string
assert_select 'label[for=project_name]', /Nome/
end
end
test 'label adds required by default when object is not present' do
with_label_for :project, :name, :string
assert_select 'label.required[for=project_name]'
with_label_for :project, :description, :string, required: false
assert_no_select 'label.required[for=project_description]'
end
test 'label adds chosen label class' do
swap SimpleForm, label_class: :my_custom_class do
with_label_for @user, :name, :string
assert_select 'label.my_custom_class'
end
end
test 'label strips extra classes even when label_class is nil' do
swap SimpleForm, label_class: nil do
with_label_for @user, :name, :string
assert_select "label[class='string required']"
assert_no_select "label[class='string required ']"
assert_no_select "label[class=' string required']"
end
end
end
simple-form-3.2.0/lib/ 0000755 0001750 0001750 00000000000 12623141213 014721 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form.rb 0000644 0001750 0001750 00000021544 12623141213 017570 0 ustar terceiro terceiro require 'action_view'
require 'simple_form/action_view_extensions/form_helper'
require 'simple_form/action_view_extensions/builder'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/reverse_merge'
module SimpleForm
extend ActiveSupport::Autoload
autoload :Helpers
autoload :Wrappers
eager_autoload do
autoload :Components
autoload :ErrorNotification
autoload :FormBuilder
autoload :Inputs
end
def self.eager_load!
super
SimpleForm::Inputs.eager_load!
SimpleForm::Components.eager_load!
end
CUSTOM_INPUT_DEPRECATION_WARN = <<-WARN
%{name} method now accepts a `wrapper_options` argument. The method definition without the argument is deprecated and will be removed in the next Simple Form version. Change your code from:
def %{name}
to
def %{name}(wrapper_options)
See https://github.com/plataformatec/simple_form/pull/997 for more information.
WARN
@@configured = false
def self.configured? #:nodoc:
@@configured
end
## CONFIGURATION OPTIONS
# Method used to tidy up errors.
mattr_accessor :error_method
@@error_method = :first
# Default tag used for error notification helper.
mattr_accessor :error_notification_tag
@@error_notification_tag = :p
# CSS class to add for error notification helper.
mattr_accessor :error_notification_class
@@error_notification_class = :error_notification
# Series of attemps to detect a default label method for collection.
mattr_accessor :collection_label_methods
@@collection_label_methods = [:to_label, :name, :title, :to_s]
# Series of attemps to detect a default value method for collection.
mattr_accessor :collection_value_methods
@@collection_value_methods = [:id, :to_s]
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
mattr_accessor :collection_wrapper_tag
@@collection_wrapper_tag = nil
# You can define the class to use on all collection wrappers, defaulting to none.
mattr_accessor :collection_wrapper_class
@@collection_wrapper_class = nil
# You can wrap each item in a collection of radio/check boxes with a tag,
# defaulting to span. Please note that when using :boolean_style = :nested,
# SimpleForm will force this option to be a :label.
mattr_accessor :item_wrapper_tag
@@item_wrapper_tag = :span
# You can define the class to use on all item wrappers, defaulting to none.
mattr_accessor :item_wrapper_class
@@item_wrapper_class = nil
# How the label text should be generated altogether with the required text.
mattr_accessor :label_text
@@label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
# You can define the class to be used on all labels. Defaults to none.
mattr_accessor :label_class
@@label_class = nil
# Define the way to render check boxes / radio buttons with labels.
# inline: input + label (default)
# nested: label > input
mattr_accessor :boolean_style
@@boolean_style = :inline
# DEPRECATED: You can define the class to be used on all forms. Default is
# simple_form.
mattr_reader :form_class
@@form_class = :simple_form
# You can define the default class to be used on all forms. Can be overriden
# with `html: { :class }`. Defaults to none.
mattr_accessor :default_form_class
@@default_form_class = nil
# You can define which elements should obtain additional classes.
mattr_accessor :generate_additional_classes_for
@@generate_additional_classes_for = [:wrapper, :label, :input]
# Whether attributes are required by default or not.
mattr_accessor :required_by_default
@@required_by_default = true
# Tell browsers whether to use default HTML5 validations (novalidate option).
mattr_accessor :browser_validations
@@browser_validations = true
# Collection of methods to detect if a file type was given.
mattr_accessor :file_methods
@@file_methods = [:mounted_as, :file?, :public_filename]
# Custom mappings for input types. This should be a hash containing a regexp
# to match as key, and the input type that will be used when the field name
# matches the regexp as value, such as { /count/ => :integer }.
mattr_accessor :input_mappings
@@input_mappings = nil
# Custom wrappers for input types. This should be a hash containing an input
# type as key and the wrapper that will be used for all inputs with specified type.
# e.g { string: :string_wrapper, boolean: :boolean_wrapper }
# You can also set a wrapper mapping per form basis.
# e.g simple_form_for(@foo, wrapper_mappings: { check_boxes: :bootstrap_checkbox })
mattr_accessor :wrapper_mappings
@@wrapper_mappings = nil
# Namespaces where SimpleForm should look for custom input classes that override
# default inputs. Namespaces are given as string to allow lazy loading inputs.
# e.g. config.custom_inputs_namespaces << "CustomInputs"
# will try to find CustomInputs::NumericInput when an :integer
# field is called.
mattr_accessor :custom_inputs_namespaces
@@custom_inputs_namespaces = []
# Default priority for time_zone inputs.
mattr_accessor :time_zone_priority
@@time_zone_priority = nil
# Default priority for country inputs.
mattr_accessor :country_priority
@@country_priority = nil
# DEPRECATED: Maximum size allowed for inputs.
mattr_accessor :default_input_size
@@default_input_size = nil
# When off, do not use translations in labels. Disabling translation in
# hints and placeholders can be done manually in the wrapper API.
mattr_accessor :translate_labels
@@translate_labels = true
# Automatically discover new inputs in Rails' autoload path.
mattr_accessor :inputs_discovery
@@inputs_discovery = true
# Cache SimpleForm inputs discovery.
mattr_accessor :cache_discovery
@@cache_discovery = defined?(Rails) && !Rails.env.development?
# Adds a class to each generated button, mostly for compatiblity.
mattr_accessor :button_class
@@button_class = 'button'
# Override the default ActiveModelHelper behaviour of wrapping the input.
# This gets taken care of semantically by adding an error class to the wrapper tag
# containing the input.
mattr_accessor :field_error_proc
@@field_error_proc = proc do |html_tag, instance_tag|
html_tag
end
# Adds a class to each generated inputs
mattr_accessor :input_class
@@input_class = nil
# Defines if an input wrapper class should be included or not
mattr_accessor :include_default_input_wrapper_class
@@include_default_input_wrapper_class = true
# Define the default class of the input wrapper of the boolean input.
mattr_accessor :boolean_label_class
@@boolean_label_class = 'checkbox'
## WRAPPER CONFIGURATION
# The default wrapper to be used by the FormBuilder.
mattr_accessor :default_wrapper
@@default_wrapper = :default
@@wrappers = {} #:nodoc:
mattr_accessor :i18n_scope
@@i18n_scope = 'simple_form'
# Retrieves a given wrapper
def self.wrapper(name)
@@wrappers[name.to_s] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
end
# Raised when fails to find a given wrapper name
class WrapperNotFound < StandardError
end
# Define a new wrapper using SimpleForm::Wrappers::Builder
# and store it in the given name.
def self.wrappers(*args, &block)
if block_given?
options = args.extract_options!
name = args.first || :default
@@wrappers[name.to_s] = build(options, &block)
else
@@wrappers
end
end
# Builds a new wrapper using SimpleForm::Wrappers::Builder.
def self.build(options = {})
options[:tag] = :div if options[:tag].nil?
builder = SimpleForm::Wrappers::Builder.new(options)
yield builder
SimpleForm::Wrappers::Root.new(builder.to_a, options)
end
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
b.use :html5
b.use :min_max
b.use :maxlength
b.use :placeholder
b.optional :pattern
b.optional :readonly
b.use :label_input
b.use :hint, wrap_with: { tag: :span, class: :hint }
b.use :error, wrap_with: { tag: :span, class: :error }
end
def self.additional_classes_for(component)
generate_additional_classes_for.include?(component) ? yield : []
end
## SETUP
def self.default_input_size=(*)
ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.default_input_size= is deprecated and has no effect", caller
end
def self.form_class=(value)
ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.form_class= is deprecated and will be removed in 4.x. Use SimpleForm.default_form_class= instead", caller
@@form_class = value
end
# Default way to setup Simple Form. Run rails generate simple_form:install
# to create a fresh initializer with all configuration values.
def self.setup
@@configured = true
yield self
end
end
require 'simple_form/railtie' if defined?(Rails)
simple-form-3.2.0/lib/generators/ 0000755 0001750 0001750 00000000000 12623141213 017072 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/ 0000755 0001750 0001750 00000000000 12623141213 021406 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/templates/ 0000755 0001750 0001750 00000000000 12623141213 023404 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/templates/_form.html.haml 0000644 0001750 0001750 00000000421 12623141213 026311 0 ustar terceiro terceiro = simple_form_for(@<%= singular_table_name %>) do |f|
= f.error_notification
.form-inputs
<%- attributes.each do |attribute| -%>
= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %>
<%- end -%>
.form-actions
= f.button :submit
simple-form-3.2.0/lib/generators/simple_form/templates/_form.html.erb 0000644 0001750 0001750 00000000540 12623141213 026142 0 ustar terceiro terceiro <%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
<%%= f.error_notification %>
<%- attributes.each do |attribute| -%>
<%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
<%- end -%>
<%%= f.button :submit %>
<%% end %>
simple-form-3.2.0/lib/generators/simple_form/templates/_form.html.slim 0000644 0001750 0001750 00000000415 12623141213 026337 0 ustar terceiro terceiro = simple_form_for(@<%= singular_table_name %>) do |f|
= f.error_notification
.form-inputs
<%- attributes.each do |attribute| -%>
= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %>
<%- end -%>
.form-actions
= f.button :submit
simple-form-3.2.0/lib/generators/simple_form/templates/config/ 0000755 0001750 0001750 00000000000 12623141213 024651 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/templates/config/initializers/ 0000755 0001750 0001750 00000000000 12623141213 027357 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/templates/config/initializers/simple_form.rb 0000644 0001750 0001750 00000014376 12623141213 032233 0 ustar terceiro terceiro # Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
# Wrappers are used by the form builder to generate a
# complete input. You can remove any component from the
# wrapper, change the order or even add your own to the
# stack. The options given below are used to wrap the
# whole input.
config.wrappers :default, class: :input,
hint_class: :field_with_hint, error_class: :field_with_errors do |b|
## Extensions enabled by default
# Any of these extensions can be disabled for a
# given input by passing: `f.input EXTENSION_NAME => false`.
# You can make any of these extensions optional by
# renaming `b.use` to `b.optional`.
# Determines whether to use HTML5 (:email, :url, ...)
# and required attributes
b.use :html5
# Calculates placeholders automatically from I18n
# You can also pass a string as f.input placeholder: "Placeholder"
b.use :placeholder
## Optional extensions
# They are disabled unless you pass `f.input EXTENSION_NAME => true`
# to the input. If so, they will retrieve the values from the model
# if any exists. If you want to enable any of those
# extensions by default, you can change `b.optional` to `b.use`.
# Calculates maxlength from length validations for string inputs
b.optional :maxlength
# Calculates pattern from format validations for string inputs
b.optional :pattern
# Calculates min and max from length validations for numeric inputs
b.optional :min_max
# Calculates readonly automatically from readonly attributes
b.optional :readonly
## Inputs
b.use :label_input
b.use :hint, wrap_with: { tag: :span, class: :hint }
b.use :error, wrap_with: { tag: :span, class: :error }
## full_messages_for
# If you want to display the full error message for the attribute, you can
# use the component :full_error, like:
#
# b.use :full_error, wrap_with: { tag: :span, class: :error }
end
# The default wrapper to be used by the FormBuilder.
config.default_wrapper = :default
# Define the way to render check boxes / radio buttons with labels.
# Defaults to :nested for bootstrap config.
# inline: input + label
# nested: label > input
config.boolean_style = :nested
# Default class for buttons
config.button_class = 'btn'
# Method used to tidy up errors. Specify any Rails Array method.
# :first lists the first message for each field.
# Use :to_sentence to list all errors for each field.
# config.error_method = :first
# Default tag used for error notification helper.
config.error_notification_tag = :div
# CSS class to add for error notification helper.
config.error_notification_class = 'error_notification'
# ID to add for error notification helper.
# config.error_notification_id = nil
# Series of attempts to detect a default label method for collection.
# config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
# Series of attempts to detect a default value method for collection.
# config.collection_value_methods = [ :id, :to_s ]
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
# config.collection_wrapper_tag = nil
# You can define the class to use on all collection wrappers. Defaulting to none.
# config.collection_wrapper_class = nil
# You can wrap each item in a collection of radio/check boxes with a tag,
# defaulting to :span.
# config.item_wrapper_tag = :span
# You can define a class to use in all item wrappers. Defaulting to none.
# config.item_wrapper_class = nil
# How the label text should be generated altogether with the required text.
# config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
# You can define the class to use on all labels. Default is nil.
# config.label_class = nil
# You can define the default class to be used on forms. Can be overriden
# with `html: { :class }`. Defaulting to none.
# config.default_form_class = nil
# You can define which elements should obtain additional classes
# config.generate_additional_classes_for = [:wrapper, :label, :input]
# Whether attributes are required by default (or not). Default is true.
# config.required_by_default = true
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
# These validations are enabled in SimpleForm's internal config but disabled by default
# in this configuration, which is recommended due to some quirks from different browsers.
# To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
# change this configuration to true.
config.browser_validations = false
# Collection of methods to detect if a file type was given.
# config.file_methods = [ :mounted_as, :file?, :public_filename ]
# Custom mappings for input types. This should be a hash containing a regexp
# to match as key, and the input type that will be used when the field name
# matches the regexp as value.
# config.input_mappings = { /count/ => :integer }
# Custom wrappers for input types. This should be a hash containing an input
# type as key and the wrapper that will be used for all inputs with specified type.
# config.wrapper_mappings = { string: :prepend }
# Namespaces where SimpleForm should look for custom input classes that
# override default inputs.
# config.custom_inputs_namespaces << "CustomInputs"
# Default priority for time_zone inputs.
# config.time_zone_priority = nil
# Default priority for country inputs.
# config.country_priority = nil
# When false, do not use translations for labels.
# config.translate_labels = true
# Automatically discover new inputs in Rails' autoload path.
# config.inputs_discovery = true
# Cache SimpleForm inputs discovery
# config.cache_discovery = !Rails.env.development?
# Default class for inputs
# config.input_class = nil
# Define the default class of the input wrapper of the boolean input.
config.boolean_label_class = 'checkbox'
# Defines if the default input wrapper class should be included in radio
# collection wrappers.
# config.include_default_input_wrapper_class = true
# Defines which i18n scope will be used in Simple Form.
# config.i18n_scope = 'simple_form'
end
simple-form-3.2.0/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb 0000755 0001750 0001750 00000011770 12623141213 034326 0 ustar terceiro terceiro # Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
config.error_notification_class = 'alert alert-danger'
config.button_class = 'btn btn-default'
config.boolean_label_class = nil
config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.use :label, class: 'control-label'
b.use :input, class: 'form-control'
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :readonly
b.use :label, class: 'control-label'
b.use :input
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.wrapper tag: 'div', class: 'checkbox' do |ba|
ba.use :label_input
end
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.use :label, class: 'control-label'
b.use :input
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.use :label, class: 'col-sm-3 control-label'
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
ba.use :input, class: 'form-control'
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :readonly
b.use :label, class: 'col-sm-3 control-label'
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
ba.use :input
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
wr.wrapper tag: 'div', class: 'checkbox' do |ba|
ba.use :label_input
end
wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.use :label, class: 'col-sm-3 control-label'
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
ba.use :input
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.use :label, class: 'sr-only'
b.use :input, class: 'form-control'
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.use :label, class: 'control-label'
b.wrapper tag: 'div', class: 'form-inline' do |ba|
ba.use :input, class: 'form-control'
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
end
# Wrappers for forms and inputs using the Bootstrap toolkit.
# Check the Bootstrap docs (http://getbootstrap.com)
# to learn about the different styles for forms and inputs,
# buttons and other elements.
config.default_wrapper = :vertical_form
config.wrapper_mappings = {
check_boxes: :vertical_radio_and_checkboxes,
radio_buttons: :vertical_radio_and_checkboxes,
file: :vertical_file_input,
boolean: :vertical_boolean,
datetime: :multi_select,
date: :multi_select,
time: :multi_select
}
end
simple-form-3.2.0/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb0000644 0001750 0001750 00000007177 12623141213 034462 0 ustar terceiro terceiro # Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
# Don't forget to edit this file to adapt it to your needs (specially
# all the grid-related classes)
#
# Please note that hints are commented out by default since Foundation
# does't provide styles for hints. You will need to provide your own CSS styles for hints.
# Uncomment them to enable hints.
config.wrappers :vertical_form, class: :input, hint_class: :field_with_hint, error_class: :error do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.use :label_input
b.use :error, wrap_with: { tag: :small, class: :error }
# b.use :hint, wrap_with: { tag: :span, class: :hint }
end
config.wrappers :horizontal_form, tag: 'div', class: 'row', hint_class: :field_with_hint, error_class: :error do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.wrapper :label_wrapper, tag: :div, class: 'small-3 columns' do |ba|
ba.use :label, class: 'right inline'
end
b.wrapper :right_input_wrapper, tag: :div, class: 'small-9 columns' do |ba|
ba.use :input
ba.use :error, wrap_with: { tag: :small, class: :error }
# ba.use :hint, wrap_with: { tag: :span, class: :hint }
end
end
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'row' do |b|
b.use :html5
b.optional :readonly
b.wrapper :container_wrapper, tag: 'div', class: 'small-offset-3 small-9 columns' do |ba|
ba.wrapper :tag => 'label', :class => 'checkbox' do |bb|
bb.use :input
bb.use :label_text
end
ba.use :error, wrap_with: { tag: :small, class: :error }
# ba.use :hint, wrap_with: { tag: :span, class: :hint }
end
end
# Foundation does not provide a way to handle inline forms
# This wrapper can be used to create an inline form
# by hiding that labels on every screen sizes ('hidden-for-small-up').
#
# Note that you need to adapt this wrapper to your needs. If you need a 4
# columns form then change the wrapper class to 'small-3', if you need
# only two use 'small-6' and so on.
config.wrappers :inline_form, tag: 'div', class: 'column small-4', hint_class: :field_with_hint, error_class: :error do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.use :label, class: 'hidden-for-small-up'
b.use :input
b.use :error, wrap_with: { tag: :small, class: :error }
# b.use :hint, wrap_with: { tag: :span, class: :hint }
end
# Examples of use:
# - wrapper_html: {class: 'row'}, custom_wrapper_html: {class: 'column small-12'}
# - custom_wrapper_html: {class: 'column small-3 end'}
config.wrappers :customizable_wrapper, tag: 'div', error_class: :error do |b|
b.use :html5
b.optional :readonly
b.wrapper :custom_wrapper, tag: :div do |ba|
ba.use :label_input
end
b.use :error, wrap_with: { tag: :small, class: :error }
# b.use :hint, wrap_with: { tag: :span, class: :hint }
end
# CSS class for buttons
config.button_class = 'button'
# Set this to div to make the checkbox and radio properly work
# otherwise simple_form adds a label tag instead of a div arround
# the nested label
config.item_wrapper_tag = :div
# CSS class to add for error notification helper.
config.error_notification_class = 'alert-box alert'
# The default wrapper to be used by the FormBuilder.
config.default_wrapper = :vertical_form
end
simple-form-3.2.0/lib/generators/simple_form/templates/config/locales/ 0000755 0001750 0001750 00000000000 12623141213 026273 5 ustar terceiro terceiro simple-form-3.2.0/lib/generators/simple_form/templates/config/locales/simple_form.en.yml 0000644 0001750 0001750 00000001506 12623141213 031735 0 ustar terceiro terceiro en:
simple_form:
"yes": 'Yes'
"no": 'No'
required:
text: 'required'
mark: '*'
# You can uncomment the line below if you need to overwrite the whole required html.
# When using html, text and mark won't be used.
# html: '*'
error_notification:
default_message: "Please review the problems below:"
# Examples
# labels:
# defaults:
# password: 'Password'
# user:
# new:
# email: 'E-mail to sign in.'
# edit:
# email: 'E-mail.'
# hints:
# defaults:
# username: 'User name to sign in.'
# password: 'No special characters, please.'
# include_blanks:
# defaults:
# age: 'Rather not say'
# prompts:
# defaults:
# age: 'Select your age'
simple-form-3.2.0/lib/generators/simple_form/templates/README 0000644 0001750 0001750 00000001002 12623141213 024255 0 ustar terceiro terceiro ===============================================================================
Be sure to have a copy of the Bootstrap stylesheet available on your
application, you can get it on http://getbootstrap.com/.
Inside your views, use the 'simple_form_for' with one of the Bootstrap form
classes, '.form-horizontal' or '.form-inline', as the following:
= simple_form_for(@user, html: { class: 'form-horizontal' }) do |form|
===============================================================================
simple-form-3.2.0/lib/generators/simple_form/install_generator.rb 0000644 0001750 0001750 00000003005 12623141213 025445 0 ustar terceiro terceiro module SimpleForm
module Generators
class InstallGenerator < Rails::Generators::Base
desc "Copy SimpleForm default files"
source_root File.expand_path('../templates', __FILE__)
class_option :template_engine, desc: 'Template engine to be invoked (erb, haml or slim).'
class_option :bootstrap, type: :boolean, desc: 'Add the Bootstrap wrappers to the SimpleForm initializer.'
class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 5 wrappers to the SimpleForm initializer.'
def info_bootstrap
return if options.bootstrap? || options.foundation?
puts "SimpleForm 3 supports Bootstrap and Zurb Foundation 5. If you want "\
"a configuration that is compatible with one of these frameworks, then please " \
"re-run this generator with --bootstrap or --foundation as an option."
end
def copy_config
template "config/initializers/simple_form.rb"
if options[:bootstrap]
template "config/initializers/simple_form_bootstrap.rb"
elsif options[:foundation]
template "config/initializers/simple_form_foundation.rb"
end
directory 'config/locales'
end
def copy_scaffold_template
engine = options[:template_engine]
copy_file "_form.html.#{engine}", "lib/templates/#{engine}/scaffold/_form.html.#{engine}"
end
def show_readme
if behavior == :invoke && options.bootstrap?
readme "README"
end
end
end
end
end
simple-form-3.2.0/lib/generators/simple_form/USAGE 0000644 0001750 0001750 00000000205 12623141213 022172 0 ustar terceiro terceiro To copy a SimpleForm initializer to your Rails App, with some configuration values, just do:
rails generate simple_form:install
simple-form-3.2.0/lib/simple_form/ 0000755 0001750 0001750 00000000000 12623141213 017235 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/error_notification.rb 0000644 0001750 0001750 00000002143 12623141213 023461 0 ustar terceiro terceiro module SimpleForm
class ErrorNotification
delegate :object, :object_name, :template, to: :@builder
def initialize(builder, options)
@builder = builder
@message = options.delete(:message)
@options = options
end
def render
if has_errors?
template.content_tag(error_notification_tag, error_message, html_options)
end
end
protected
def errors
object.errors
end
def has_errors?
object && object.respond_to?(:errors) && errors.present?
end
def error_message
(@message || translate_error_notification).html_safe
end
def error_notification_tag
SimpleForm.error_notification_tag
end
def html_options
@options[:class] = "#{SimpleForm.error_notification_class} #{@options[:class]}".strip
@options
end
def translate_error_notification
lookups = []
lookups << :"#{object_name}"
lookups << :default_message
lookups << "Please review the problems below:"
I18n.t(lookups.shift, scope: :"simple_form.error_notification", default: lookups)
end
end
end
simple-form-3.2.0/lib/simple_form/railtie.rb 0000644 0001750 0001750 00000000655 12623141213 021221 0 ustar terceiro terceiro require 'rails/railtie'
module SimpleForm
class Railtie < Rails::Railtie
config.eager_load_namespaces << SimpleForm
config.after_initialize do
unless SimpleForm.configured?
warn '[Simple Form] Simple Form is not configured in the application and will use the default values.' +
' Use `rails generate simple_form:install` to generate the Simple Form configuration.'
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs.rb 0000644 0001750 0001750 00000001102 12623141213 021076 0 ustar terceiro terceiro module SimpleForm
module Inputs
extend ActiveSupport::Autoload
autoload :Base
autoload :BlockInput
autoload :BooleanInput
autoload :CollectionCheckBoxesInput
autoload :CollectionInput
autoload :CollectionRadioButtonsInput
autoload :CollectionSelectInput
autoload :DateTimeInput
autoload :FileInput
autoload :GroupedCollectionSelectInput
autoload :HiddenInput
autoload :NumericInput
autoload :PasswordInput
autoload :PriorityInput
autoload :RangeInput
autoload :StringInput
autoload :TextInput
end
end
simple-form-3.2.0/lib/simple_form/action_view_extensions/ 0000755 0001750 0001750 00000000000 12623141213 024023 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/action_view_extensions/form_helper.rb 0000644 0001750 0001750 00000004366 12623141213 026663 0 ustar terceiro terceiro module SimpleForm
module ActionViewExtensions
# This module creates SimpleForm wrappers around default form_for and fields_for.
#
# Example:
#
# simple_form_for @user do |f|
# f.input :name, hint: 'My hint'
# end
#
module FormHelper
def simple_form_for(record, options = {}, &block)
options[:builder] ||= SimpleForm::FormBuilder
options[:html] ||= {}
unless options[:html].key?(:novalidate)
options[:html][:novalidate] = !SimpleForm.browser_validations
end
if options[:html].key?(:class)
options[:html][:class] = [SimpleForm.form_class, options[:html][:class]].compact
else
options[:html][:class] = [SimpleForm.form_class, SimpleForm.default_form_class, simple_form_css_class(record, options)].compact
end
with_simple_form_field_error_proc do
form_for(record, options, &block)
end
end
def simple_fields_for(record_name, record_object = nil, options = {}, &block)
options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
options[:builder] ||= SimpleForm::FormBuilder
with_simple_form_field_error_proc do
fields_for(record_name, record_object, options, &block)
end
end
private
def with_simple_form_field_error_proc
default_field_error_proc = ::ActionView::Base.field_error_proc
begin
::ActionView::Base.field_error_proc = SimpleForm.field_error_proc
yield
ensure
::ActionView::Base.field_error_proc = default_field_error_proc
end
end
def simple_form_css_class(record, options)
html_options = options[:html]
as = options[:as]
if html_options.key?(:class)
html_options[:class]
elsif record.is_a?(String) || record.is_a?(Symbol)
as || record
else
record = record.last if record.is_a?(Array)
action = record.respond_to?(:persisted?) && record.persisted? ? :edit : :new
as ? "#{action}_#{as}" : dom_class(record, action)
end
end
end
end
end
ActionView::Base.send :include, SimpleForm::ActionViewExtensions::FormHelper
simple-form-3.2.0/lib/simple_form/action_view_extensions/builder.rb 0000644 0001750 0001750 00000002250 12623141213 025775 0 ustar terceiro terceiro module SimpleForm
module ActionViewExtensions
# A collection of methods required by simple_form but added to rails default form.
# This means that you can use such methods outside simple_form context.
module Builder
# Wrapper for using SimpleForm inside a default rails form.
# Example:
#
# form_for @user do |f|
# f.simple_fields_for :posts do |posts_form|
# # Here you have all simple_form methods available
# posts_form.input :title
# end
# end
def simple_fields_for(*args, &block)
options = args.extract_options!
options[:wrapper] = self.options[:wrapper] if options[:wrapper].nil?
options[:defaults] ||= self.options[:defaults]
options[:wrapper_mappings] ||= self.options[:wrapper_mappings]
if self.class < ActionView::Helpers::FormBuilder
options[:builder] ||= self.class
else
options[:builder] ||= SimpleForm::FormBuilder
end
fields_for(*args, options, &block)
end
end
end
end
module ActionView::Helpers
class FormBuilder
include SimpleForm::ActionViewExtensions::Builder
end
end
simple-form-3.2.0/lib/simple_form/wrappers/ 0000755 0001750 0001750 00000000000 12623141213 021100 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/wrappers/leaf.rb 0000644 0001750 0001750 00000001077 12623141213 022341 0 ustar terceiro terceiro module SimpleForm
module Wrappers
class Leaf
attr_reader :namespace
def initialize(namespace, options = {})
@namespace = namespace
@options = options
end
def render(input)
method = input.method(@namespace)
if method.arity == 0
ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: @namespace })
method.call
else
method.call(@options)
end
end
def find(name)
self if @namespace == name
end
end
end
end
simple-form-3.2.0/lib/simple_form/wrappers/builder.rb 0000644 0001750 0001750 00000005136 12623141213 023060 0 ustar terceiro terceiro module SimpleForm
module Wrappers
# Provides the builder syntax for components. The builder provides
# three methods `use`, `optional` and `wrapper` and they allow the following invocations:
#
# config.wrappers do |b|
# # Use a single component
# b.use :html5
#
# # Use the component, but do not automatically lookup. It will only be triggered when
# # :placeholder is explicitly set.
# b.optional :placeholder
#
# # Use a component with specific wrapper options
# b.use :error, wrap_with: { tag: "span", class: "error" }
#
# # Use a set of components by wrapping them in a tag+class.
# b.wrapper tag: "div", class: "another" do |ba|
# ba.use :label
# ba.use :input
# end
#
# # Use a set of components by wrapping them in a tag+class.
# # This wrapper is identified by :label_input, which means it can
# # be turned off on demand with `f.input :name, label_input: false`
# b.wrapper :label_input, tag: "div", class: "another" do |ba|
# ba.use :label
# ba.use :input
# end
# end
#
# The builder also accepts default options at the root level. This is usually
# used if you want a component to be disabled by default:
#
# config.wrappers hint: false do |b|
# b.use :hint
# b.use :label_input
# end
#
# In the example above, hint defaults to false, which means it won't automatically
# do the lookup anymore. It will only be triggered when :hint is explicitly set.
class Builder
def initialize(options)
@options = options
@components = []
end
def use(name, options = {})
if options && wrapper = options[:wrap_with]
@components << Single.new(name, wrapper, options.except(:wrap_with))
else
@components << Leaf.new(name, options)
end
end
def optional(name, options = {}, &block)
@options[name] = false
use(name, options)
end
def wrapper(name, options = nil)
if block_given?
name, options = nil, name if name.is_a?(Hash)
builder = self.class.new(@options)
options ||= {}
options[:tag] = :div if options[:tag].nil?
yield builder
@components << Many.new(name, builder.to_a, options)
else
raise ArgumentError, "A block is required as argument to wrapper"
end
end
def to_a
@components
end
end
end
end
simple-form-3.2.0/lib/simple_form/wrappers/single.rb 0000644 0001750 0001750 00000001217 12623141213 022707 0 ustar terceiro terceiro module SimpleForm
module Wrappers
# `Single` is an optimization for a wrapper that has only one component.
class Single < Many
def initialize(name, wrapper_options = {}, options = {})
@component = Leaf.new(name, options)
super(name, [@component], wrapper_options)
end
def render(input)
options = input.options
if options[namespace] != false
content = @component.render(input)
wrap(input, options, content) if content
end
end
private
def html_options(options)
[:label, :input].include?(namespace) ? {} : super
end
end
end
end
simple-form-3.2.0/lib/simple_form/wrappers/many.rb 0000644 0001750 0001750 00000004245 12623141213 022376 0 ustar terceiro terceiro module SimpleForm
module Wrappers
# A wrapper is an object that holds several components and render them.
# A component may be any object that responds to `render`.
# This API allows inputs/components to be easily wrapped, removing the
# need to modify the code only to wrap input in an extra tag.
#
# `Many` represents a wrapper around several components at the same time.
# It may optionally receive a namespace, allowing it to be configured
# on demand on input generation.
class Many
attr_reader :namespace, :defaults, :components
def initialize(namespace, components, defaults = {})
@namespace = namespace
@components = components
@defaults = defaults
@defaults[:tag] = :div unless @defaults.key?(:tag)
@defaults[:class] = Array(@defaults[:class])
end
def render(input)
content = "".html_safe
options = input.options
components.each do |component|
next if options[component.namespace] == false
rendered = component.render(input)
content.safe_concat rendered.to_s if rendered
end
wrap(input, options, content)
end
def find(name)
return self if namespace == name
@components.each do |c|
if c.is_a?(Symbol)
return nil if c == namespace
elsif value = c.find(name)
return value
end
end
nil
end
private
def wrap(input, options, content)
return content if options[namespace] == false
return if defaults[:unless_blank] && content.empty?
tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
return content unless tag
klass = html_classes(input, options)
opts = html_options(options)
opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
input.template.content_tag(tag, content, opts)
end
def html_options(options)
(@defaults[:html] || {}).merge(options[:"#{namespace}_html"] || {})
end
def html_classes(input, options)
@defaults[:class].dup
end
end
end
end
simple-form-3.2.0/lib/simple_form/wrappers/root.rb 0000644 0001750 0001750 00000002156 12623141213 022414 0 ustar terceiro terceiro module SimpleForm
module Wrappers
# `Root` is the root wrapper for all components. It is special cased to
# always have a namespace and to add special html classes.
class Root < Many
attr_reader :options
def initialize(*args)
super(:wrapper, *args)
@options = @defaults.except(:tag, :class, :error_class, :hint_class)
end
def render(input)
input.options.reverse_merge!(@options)
super
end
# Provide a fallback if name cannot be found.
def find(name)
super || SimpleForm::Wrappers::Many.new(name, [Leaf.new(name)])
end
private
def html_classes(input, options)
css = options[:wrapper_class] ? Array(options[:wrapper_class]) : @defaults[:class]
css += SimpleForm.additional_classes_for(:wrapper) do
input.additional_classes + [input.input_class]
end
css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
css.compact
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/ 0000755 0001750 0001750 00000000000 12623141213 020557 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/inputs/file_input.rb 0000644 0001750 0001750 00000000435 12623141213 023244 0 ustar terceiro terceiro module SimpleForm
module Inputs
class FileInput < Base
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.file_field(attribute_name, merged_input_options)
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/collection_input.rb 0000644 0001750 0001750 00000010016 12623141213 024454 0 ustar terceiro terceiro module SimpleForm
module Inputs
class CollectionInput < Base
# Default boolean collection for use with selects/radios when no
# collection is given. Always fallback to this boolean collection.
# Texts can be translated using i18n in "simple_form.yes" and
# "simple_form.no" keys. See the example locale file.
def self.boolean_collection
i18n_cache :boolean_collection do
[ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
[I18n.t(:"simple_form.no", default: 'No'), false] ]
end
end
def input(wrapper_options = nil)
raise NotImplementedError,
"input should be implemented by classes inheriting from CollectionInput"
end
def input_options
options = super
options[:include_blank] = true unless skip_include_blank?
translate_option options, :prompt
translate_option options, :include_blank
options
end
private
def collection
@collection ||= begin
collection = options.delete(:collection) || self.class.boolean_collection
collection.respond_to?(:call) ? collection.call : collection.to_a
end
end
def has_required?
super && (input_options[:include_blank] || input_options[:prompt] || multiple?)
end
# Check if :include_blank must be included by default.
def skip_include_blank?
(options.keys & [:prompt, :include_blank, :default, :selected]).any? || multiple?
end
def multiple?
!!options[:input_html].try(:[], :multiple)
end
# Detect the right method to find the label and value for a collection.
# If no label or value method are defined, will attempt to find them based
# on default label and value methods that can be configured through
# SimpleForm.collection_label_methods and
# SimpleForm.collection_value_methods.
def detect_collection_methods
label, value = options.delete(:label_method), options.delete(:value_method)
unless label && value
common_method_for = detect_common_display_methods
label ||= common_method_for[:label]
value ||= common_method_for[:value]
end
[label, value]
end
def detect_common_display_methods(collection_classes = detect_collection_classes)
collection_translated = translate_collection if collection_classes == [Symbol]
if collection_translated || collection_classes.include?(Array)
{ label: :first, value: :second }
elsif collection_includes_basic_objects?(collection_classes)
{ label: :to_s, value: :to_s }
else
detect_method_from_class(collection_classes)
end
end
def detect_method_from_class(collection_classes)
sample = collection.first || collection.last
{ label: SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
value: SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
end
def detect_collection_classes(some_collection = collection)
some_collection.map { |e| e.class }.uniq
end
def collection_includes_basic_objects?(collection_classes)
(collection_classes & [
String, Integer, Fixnum, Bignum, Float, NilClass, Symbol, TrueClass, FalseClass
]).any?
end
def translate_collection
if translated_collection = translate_from_namespace(:options)
@collection = collection.map do |key|
html_key = "#{key}_html".to_sym
if translated_collection[html_key]
[translated_collection[html_key].html_safe || key, key.to_s]
else
[translated_collection[key] || key, key.to_s]
end
end
true
end
end
def translate_option(options, key)
if options[key] == :translate
namespace = key.to_s.pluralize
options[key] = translate_from_namespace(namespace, true)
end
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/priority_input.rb 0000644 0001750 0001750 00000001173 12623141213 024206 0 ustar terceiro terceiro module SimpleForm
module Inputs
class PriorityInput < CollectionSelectInput
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.send(:"#{input_type}_select", attribute_name, input_priority,
input_options, merged_input_options)
end
def input_priority
options[:priority] || SimpleForm.send(:"#{input_type}_priority")
end
protected
def has_required?
false
end
def skip_include_blank?
super || input_priority.present?
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/collection_select_input.rb 0000644 0001750 0001750 00000000720 12623141213 026014 0 ustar terceiro terceiro module SimpleForm
module Inputs
class CollectionSelectInput < CollectionInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.collection_select(
attribute_name, collection, value_method, label_method,
input_options, merged_input_options
)
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/text_input.rb 0000644 0001750 0001750 00000000503 12623141213 023305 0 ustar terceiro terceiro module SimpleForm
module Inputs
class TextInput < Base
enable :placeholder, :maxlength
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.text_area(attribute_name, merged_input_options)
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/date_time_input.rb 0000644 0001750 0001750 00000001760 12623141213 024262 0 ustar terceiro terceiro module SimpleForm
module Inputs
class DateTimeInput < Base
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
if use_html5_inputs?
@builder.send(:"#{input_type}_field", attribute_name, merged_input_options)
else
@builder.send(:"#{input_type}_select", attribute_name, input_options, merged_input_options)
end
end
private
def label_target
if use_html5_inputs?
attribute_name
else
position = case input_type
when :date, :datetime
date_order = input_options[:order] || I18n.t('date.order')
date_order.first.to_sym
else
:hour
end
position = ActionView::Helpers::DateTimeSelector::POSITION[position]
"#{attribute_name}_#{position}i"
end
end
def use_html5_inputs?
input_options[:html5]
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/block_input.rb 0000644 0001750 0001750 00000000367 12623141213 023423 0 ustar terceiro terceiro module SimpleForm
module Inputs
class BlockInput < Base
def initialize(*args, &block)
super
@block = block
end
def input(wrapper_options = nil)
template.capture(&@block)
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/base.rb 0000644 0001750 0001750 00000015427 12623141213 022027 0 ustar terceiro terceiro require 'simple_form/i18n_cache'
require 'active_support/core_ext/string/output_safety'
require 'action_view/helpers'
module SimpleForm
module Inputs
class Base
include ERB::Util
include ActionView::Helpers::TranslationHelper
extend I18nCache
include SimpleForm::Helpers::Autofocus
include SimpleForm::Helpers::Disabled
include SimpleForm::Helpers::Readonly
include SimpleForm::Helpers::Required
include SimpleForm::Helpers::Validators
include SimpleForm::Components::Errors
include SimpleForm::Components::Hints
include SimpleForm::Components::HTML5
include SimpleForm::Components::LabelInput
include SimpleForm::Components::Maxlength
include SimpleForm::Components::MinMax
include SimpleForm::Components::Pattern
include SimpleForm::Components::Placeholders
include SimpleForm::Components::Readonly
attr_reader :attribute_name, :column, :input_type, :reflection,
:options, :input_html_options, :input_html_classes, :html_classes
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
class_attribute :default_options
self.default_options = {}
def self.enable(*keys)
options = self.default_options.dup
keys.each { |key| options.delete(key) }
self.default_options = options
end
def self.disable(*keys)
options = self.default_options.dup
keys.each { |key| options[key] = false }
self.default_options = options
end
# Always enabled.
enable :hint
# Usually disabled, needs to be enabled explicitly passing true as option.
disable :maxlength, :placeholder, :pattern, :min_max
def initialize(builder, attribute_name, column, input_type, options = {})
super
options = options.dup
@builder = builder
@attribute_name = attribute_name
@column = column
@input_type = input_type
@reflection = options.delete(:reflection)
@options = options.reverse_merge!(self.class.default_options)
@required = calculate_required
# Notice that html_options_for receives a reference to input_html_classes.
# This means that classes added dynamically to input_html_classes will
# still propagate to input_html_options.
@html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
@input_html_classes = @html_classes.dup
if SimpleForm.input_class && !input_html_classes.empty?
input_html_classes << SimpleForm.input_class
end
@input_html_options = html_options_for(:input, input_html_classes).tap do |o|
o[:readonly] = true if has_readonly?
o[:disabled] = true if has_disabled?
o[:autofocus] = true if has_autofocus?
end
end
def input(wrapper_options = nil)
raise NotImplementedError
end
def input_options
options
end
def additional_classes
@additional_classes ||= [input_type, required_class, readonly_class, disabled_class].compact
end
def input_class
"#{lookup_model_names.join("_")}_#{reflection_or_attribute_name}"
end
private
def limit
if column
decimal_or_float? ? decimal_limit : column_limit
end
end
def column_limit
column.limit
end
# Add one for decimal point
def decimal_limit
column_limit && (column_limit + 1)
end
def decimal_or_float?
column.number? && column.type != :integer
end
def nested_boolean_style?
options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
end
# Find reflection name when available, otherwise use attribute
def reflection_or_attribute_name
@reflection_or_attribute_name ||= reflection ? reflection.name : attribute_name
end
# Retrieve options for the given namespace from the options hash
def html_options_for(namespace, css_classes)
html_options = options[:"#{namespace}_html"]
html_options = html_options ? html_options.dup : {}
css_classes << html_options[:class] if html_options.key?(:class)
html_options[:class] = css_classes unless css_classes.empty?
html_options
end
# Lookup translations for the given namespace using I18n, based on object name,
# actual action and attribute name. Lookup priority as follows:
#
# simple_form.{namespace}.{model}.{action}.{attribute}
# simple_form.{namespace}.{model}.{attribute}
# simple_form.{namespace}.defaults.{attribute}
#
# Namespace is used for :labels and :hints.
#
# Model is the actual object name, for a @user object you'll have :user.
# Action is the action being rendered, usually :new or :edit.
# And attribute is the attribute itself, :name for example.
#
# The lookup for nested attributes is also done in a nested format using
# both model and nested object names, such as follow:
#
# simple_form.{namespace}.{model}.{nested}.{action}.{attribute}
# simple_form.{namespace}.{model}.{nested}.{attribute}
# simple_form.{namespace}.{nested}.{action}.{attribute}
# simple_form.{namespace}.{nested}.{attribute}
# simple_form.{namespace}.defaults.{attribute}
#
# Example:
#
# simple_form:
# labels:
# user:
# new:
# email: 'E-mail para efetuar o sign in.'
# edit:
# email: 'E-mail.'
#
# Take a look at our locale example file.
def translate_from_namespace(namespace, default = '')
model_names = lookup_model_names.dup
lookups = []
while !model_names.empty?
joined_model_names = model_names.join(".")
model_names.shift
lookups << :"#{joined_model_names}.#{lookup_action}.#{reflection_or_attribute_name}"
lookups << :"#{joined_model_names}.#{reflection_or_attribute_name}"
end
lookups << :"defaults.#{lookup_action}.#{reflection_or_attribute_name}"
lookups << :"defaults.#{reflection_or_attribute_name}"
lookups << default
I18n.t(lookups.shift, scope: :"#{i18n_scope}.#{namespace}", default: lookups).presence
end
def merge_wrapper_options(options, wrapper_options)
if wrapper_options
options.merge(wrapper_options) do |_, oldval, newval|
if Array === oldval
oldval + Array(newval)
end
end
else
options
end
end
def i18n_scope
SimpleForm.i18n_scope
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/range_input.rb 0000644 0001750 0001750 00000000420 12623141213 023413 0 ustar terceiro terceiro module SimpleForm
module Inputs
class RangeInput < NumericInput
def input(wrapper_options = nil)
if html5?
input_html_options[:type] ||= "range"
input_html_options[:step] ||= 1
end
super
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/boolean_input.rb 0000644 0001750 0001750 00000006437 12623141213 023754 0 ustar terceiro terceiro module SimpleForm
module Inputs
class BooleanInput < Base
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
if nested_boolean_style?
build_hidden_field_for_checkbox +
template.label_tag(nil, class: SimpleForm.boolean_label_class) {
build_check_box_without_hidden_field(merged_input_options) +
inline_label
}
else
build_check_box(unchecked_value, merged_input_options)
end
end
def label_input(wrapper_options = nil)
if options[:label] == false || inline_label?
input(wrapper_options)
elsif nested_boolean_style?
html_options = label_html_options.dup
html_options[:class] ||= []
html_options[:class].push(SimpleForm.boolean_label_class) if SimpleForm.boolean_label_class
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
build_hidden_field_for_checkbox +
@builder.label(label_target, html_options) {
build_check_box_without_hidden_field(merged_input_options) + label_text
}
else
input(wrapper_options) + label(wrapper_options)
end
end
private
# Build a checkbox tag using default unchecked value. This allows us to
# reuse the method for nested boolean style, but with no unchecked value,
# which won't generate the hidden checkbox. This is the default functionality
# in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
def build_check_box(unchecked_value, options)
@builder.check_box(attribute_name, options, checked_value, unchecked_value)
end
# Build a checkbox without generating the hidden field. See
# #build_hidden_field_for_checkbox for more info.
def build_check_box_without_hidden_field(options)
build_check_box(nil, options)
end
# Create a hidden field for the current checkbox, so we can simulate Rails
# functionality with hidden + checkbox, but under a nested context, where
# we need the hidden field to be *outside* the label (otherwise it
# generates invalid html - html5 only).
def build_hidden_field_for_checkbox
options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
options[:name] = input_html_options[:name] if input_html_options.has_key?(:name)
@builder.hidden_field(attribute_name, options)
end
def inline_label?
nested_boolean_style? && options[:inline_label]
end
def inline_label
inline_option = options[:inline_label]
if inline_option
label = inline_option == true ? label_text : html_escape(inline_option)
" #{label}".html_safe
end
end
# Booleans are not required by default because in most of the cases
# it makes no sense marking them as required. The only exception is
# Terms of Use usually presented at most sites sign up screen.
def required_by_default?
false
end
def checked_value
options.fetch(:checked_value, '1')
end
def unchecked_value
options.fetch(:unchecked_value, '0')
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/collection_check_boxes_input.rb 0000644 0001750 0001750 00000001034 12623141213 027011 0 ustar terceiro terceiro module SimpleForm
module Inputs
class CollectionCheckBoxesInput < CollectionRadioButtonsInput
protected
# Checkbox components do not use the required html tag.
# More info: https://github.com/plataformatec/simple_form/issues/340#issuecomment-2871956
def has_required?
false
end
def build_nested_boolean_style_item_tag(collection_builder)
collection_builder.check_box + collection_builder.text
end
def item_wrapper_class
"checkbox"
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/hidden_input.rb 0000644 0001750 0001750 00000000621 12623141213 023555 0 ustar terceiro terceiro module SimpleForm
module Inputs
class HiddenInput < Base
disable :label, :errors, :hint, :required
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.hidden_field(attribute_name, merged_input_options)
end
private
def required_class
nil
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/grouped_collection_select_input.rb 0000644 0001750 0001750 00000003300 12623141213 027536 0 ustar terceiro terceiro module SimpleForm
module Inputs
class GroupedCollectionSelectInput < CollectionInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.grouped_collection_select(attribute_name, grouped_collection,
group_method, group_label_method, value_method, label_method,
input_options, merged_input_options)
end
private
def grouped_collection
@grouped_collection ||= begin
grouped_collection = options.delete(:collection)
grouped_collection.respond_to?(:call) ? grouped_collection.call : grouped_collection.to_a
end
end
# Sample collection
def collection
@collection ||= grouped_collection.map { |collection| collection.try(:send, group_method) }.detect(&:present?) || []
end
def group_method
@group_method ||= options.delete(:group_method)
end
def group_label_method
label = options.delete(:group_label_method)
unless label
common_method_for = detect_common_display_methods(detect_collection_classes(grouped_collection))
label = common_method_for[:label]
end
label
end
def detect_method_from_class(collection_classes)
return {} if collection_classes.empty?
sample = collection_classes.first
{ label: SimpleForm.collection_label_methods.find { |m| sample.instance_methods.include?(m) },
value: SimpleForm.collection_value_methods.find { |m| sample.instance_methods.include?(m) } }
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/string_input.rb 0000644 0001750 0001750 00000001052 12623141213 023627 0 ustar terceiro terceiro module SimpleForm
module Inputs
class StringInput < Base
enable :placeholder, :maxlength, :pattern
def input(wrapper_options = nil)
unless string?
input_html_classes.unshift("string")
input_html_options[:type] ||= input_type if html5?
end
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.text_field(attribute_name, merged_input_options)
end
private
def string?
input_type == :string
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/collection_radio_buttons_input.rb 0000644 0001750 0001750 00000003654 12623141213 027422 0 ustar terceiro terceiro module SimpleForm
module Inputs
class CollectionRadioButtonsInput < CollectionInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.send(:"collection_#{input_type}",
attribute_name, collection, value_method, label_method,
input_options, merged_input_options,
&collection_block_for_nested_boolean_style
)
end
def input_options
options = super
apply_default_collection_options!(options)
options
end
protected
def apply_default_collection_options!(options)
options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleForm.item_wrapper_tag)
options[:item_wrapper_class] = [
item_wrapper_class, options[:item_wrapper_class], SimpleForm.item_wrapper_class
].compact.presence if SimpleForm.include_default_input_wrapper_class
options[:collection_wrapper_tag] ||= options.fetch(:collection_wrapper_tag, SimpleForm.collection_wrapper_tag)
options[:collection_wrapper_class] = [
options[:collection_wrapper_class], SimpleForm.collection_wrapper_class
].compact.presence
end
def collection_block_for_nested_boolean_style
return unless nested_boolean_style?
proc { |builder| build_nested_boolean_style_item_tag(builder) }
end
def build_nested_boolean_style_item_tag(collection_builder)
collection_builder.radio_button + collection_builder.text
end
def item_wrapper_class
"radio"
end
# Do not attempt to generate label[for] attributes by default, unless an
# explicit html option is given. This avoids generating labels pointing to
# non existent fields.
def generate_label_for_attribute?
false
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/password_input.rb 0000644 0001750 0001750 00000000514 12623141213 024165 0 ustar terceiro terceiro module SimpleForm
module Inputs
class PasswordInput < Base
enable :placeholder, :maxlength
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.password_field(attribute_name, merged_input_options)
end
end
end
end
simple-form-3.2.0/lib/simple_form/inputs/numeric_input.rb 0000644 0001750 0001750 00000001000 12623141213 023754 0 ustar terceiro terceiro module SimpleForm
module Inputs
class NumericInput < Base
enable :placeholder, :min_max
def input(wrapper_options = nil)
input_html_classes.unshift("numeric")
if html5?
input_html_options[:type] ||= "number"
input_html_options[:step] ||= integer? ? 1 : "any"
end
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.text_field(attribute_name, merged_input_options)
end
end
end
end
simple-form-3.2.0/lib/simple_form/version.rb 0000644 0001750 0001750 00000000061 12623141213 021244 0 ustar terceiro terceiro module SimpleForm
VERSION = "3.2.0".freeze
end
simple-form-3.2.0/lib/simple_form/form_builder.rb 0000644 0001750 0001750 00000060270 12623141213 022240 0 ustar terceiro terceiro require 'active_support/core_ext/object/deep_dup'
require 'simple_form/map_type'
require 'simple_form/tags'
module SimpleForm
class FormBuilder < ActionView::Helpers::FormBuilder
attr_reader :template, :object_name, :object, :wrapper
# When action is create or update, we still should use new and edit
ACTIONS = {
'create' => 'new',
'update' => 'edit'
}
ATTRIBUTE_COMPONENTS = [:html5, :min_max, :maxlength, :placeholder, :pattern, :readonly]
extend MapType
include SimpleForm::Inputs
map_type :text, to: SimpleForm::Inputs::TextInput
map_type :file, to: SimpleForm::Inputs::FileInput
map_type :string, :email, :search, :tel, :url, :uuid, to: SimpleForm::Inputs::StringInput
map_type :password, to: SimpleForm::Inputs::PasswordInput
map_type :integer, :decimal, :float, to: SimpleForm::Inputs::NumericInput
map_type :range, to: SimpleForm::Inputs::RangeInput
map_type :check_boxes, to: SimpleForm::Inputs::CollectionCheckBoxesInput
map_type :radio_buttons, to: SimpleForm::Inputs::CollectionRadioButtonsInput
map_type :select, to: SimpleForm::Inputs::CollectionSelectInput
map_type :grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput
map_type :date, :time, :datetime, to: SimpleForm::Inputs::DateTimeInput
map_type :country, :time_zone, to: SimpleForm::Inputs::PriorityInput
map_type :boolean, to: SimpleForm::Inputs::BooleanInput
map_type :hidden, to: SimpleForm::Inputs::HiddenInput
def self.discovery_cache
@discovery_cache ||= {}
end
def initialize(*) #:nodoc:
super
@defaults = options[:defaults]
@wrapper = SimpleForm.wrapper(options[:wrapper] || SimpleForm.default_wrapper)
end
# Basic input helper, combines all components in the stack to generate
# input html based on options the user define and some guesses through
# database column information. By default a call to input will generate
# label + input + hint (when defined) + errors (when exists), and all can
# be configured inside a wrapper html.
#
# == Examples
#
# # Imagine @user has error "can't be blank" on name
# simple_form_for @user do |f|
# f.input :name, hint: 'My hint'
# end
#
# This is the output html (only the input portion, not the form):
#
#
#
# My hint
# can't be blank
#
# Each database type will render a default input, based on some mappings and
# heuristic to determine which is the best option.
#
# You have some options for the input to enable/disable some functions:
#
# as: allows you to define the input type you want, for instance you
# can use it to generate a text field for a date column.
#
# required: defines whether this attribute is required or not. True
# by default.
#
# The fact SimpleForm is built in components allow the interface to be unified.
# So, for instance, if you need to disable :hint for a given input, you can pass
# hint: false. The same works for :error, :label and :wrapper.
#
# Besides the html for any component can be changed. So, if you want to change
# the label html you just need to give a hash to :label_html. To configure the
# input html, supply :input_html instead and so on.
#
# == Options
#
# Some inputs, as datetime, time and select allow you to give extra options, like
# prompt and/or include blank. Such options are given in plainly:
#
# f.input :created_at, include_blank: true
#
# == Collection
#
# When playing with collections (:radio_buttons, :check_boxes and :select
# inputs), you have three extra options:
#
# collection: use to determine the collection to generate the radio or select
#
# label_method: the method to apply on the array collection to get the label
#
# value_method: the method to apply on the array collection to get the value
#
# == Priority
#
# Some inputs, as :time_zone and :country accepts a :priority option. If none is
# given SimpleForm.time_zone_priority and SimpleForm.country_priority are used respectively.
#
def input(attribute_name, options = {}, &block)
options = @defaults.deep_dup.deep_merge(options) if @defaults
input = find_input(attribute_name, options, &block)
wrapper = find_wrapper(input.input_type, options)
wrapper.render input
end
alias :attribute :input
# Creates a input tag for the given attribute. All the given options
# are sent as :input_html.
#
# == Examples
#
# simple_form_for @user do |f|
# f.input_field :name
# end
#
# This is the output html (only the input portion, not the form):
#
#
#
def input_field(attribute_name, options = {})
components = (wrapper.components.map(&:namespace) & ATTRIBUTE_COMPONENTS)
options = options.dup
options[:input_html] = options.except(:as, :boolean_style, :collection, :label_method, :value_method, *components)
options = @defaults.deep_dup.deep_merge(options) if @defaults
input = find_input(attribute_name, options)
wrapper = find_wrapper(input.input_type, options)
components = components.concat([:input]).map { |component| SimpleForm::Wrappers::Leaf.new(component) }
SimpleForm::Wrappers::Root.new(components, wrapper.options.merge(wrapper: false)).render input
end
# Helper for dealing with association selects/radios, generating the
# collection automatically. It's just a wrapper to input, so all options
# supported in input are also supported by association. Some extra options
# can also be given:
#
# == Examples
#
# simple_form_for @user do |f|
# f.association :company # Company.all
# end
#
# f.association :company, collection: Company.all(order: 'name')
# # Same as using :order option, but overriding collection
#
# == Block
#
# When a block is given, association simple behaves as a proxy to
# simple_fields_for:
#
# f.association :company do |c|
# c.input :name
# c.input :type
# end
#
# From the options above, only :collection can also be supplied.
#
# Please note that the association helper is currently only tested with Active Record. Depending on the ORM you are using your mileage may vary.
#
def association(association, options = {}, &block)
options = options.dup
return simple_fields_for(*[association,
options.delete(:collection), options].compact, &block) if block_given?
raise ArgumentError, "Association cannot be used in forms not associated with an object" unless @object
reflection = find_association_reflection(association)
raise "Association #{association.inspect} not found" unless reflection
options[:as] ||= :select
options[:collection] ||= fetch_association_collection(reflection, options)
attribute = build_association_attribute(reflection, association, options)
input(attribute, options.merge(reflection: reflection))
end
# Creates a button:
#
# form_for @user do |f|
# f.button :submit
# end
#
# It just acts as a proxy to method name given. We also alias original Rails
# button implementation (3.2 forward (to delegate to the original when
# calling `f.button :button`.
#
alias_method :button_button, :button
def button(type, *args, &block)
options = args.extract_options!.dup
options[:class] = [SimpleForm.button_class, options[:class]].compact
args << options
if respond_to?(:"#{type}_button")
send(:"#{type}_button", *args, &block)
else
send(type, *args, &block)
end
end
# Creates an error tag based on the given attribute, only when the attribute
# contains errors. All the given options are sent as :error_html.
#
# == Examples
#
# f.error :name
# f.error :name, id: "cool_error"
#
def error(attribute_name, options = {})
options = options.dup
options[:error_html] = options.except(:error_tag, :error_prefix, :error_method)
column = find_attribute_column(attribute_name)
input_type = default_input_type(attribute_name, column, options)
wrapper.find(:error).
render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
end
# Return the error but also considering its name. This is used
# when errors for a hidden field need to be shown.
#
# == Examples
#
# f.full_error :token #=> Token is invalid
#
def full_error(attribute_name, options = {})
options = options.dup
options[:error_prefix] ||= if object.class.respond_to?(:human_attribute_name)
object.class.human_attribute_name(attribute_name.to_s)
else
attribute_name.to_s.humanize
end
error(attribute_name, options)
end
# Creates a hint tag for the given attribute. Accepts a symbol indicating
# an attribute for I18n lookup or a string. All the given options are sent
# as :hint_html.
#
# == Examples
#
# f.hint :name # Do I18n lookup
# f.hint :name, id: "cool_hint"
# f.hint "Don't forget to accept this"
#
def hint(attribute_name, options = {})
options = options.dup
options[:hint_html] = options.except(:hint_tag, :hint)
if attribute_name.is_a?(String)
options[:hint] = attribute_name
attribute_name, column, input_type = nil, nil, nil
else
column = find_attribute_column(attribute_name)
input_type = default_input_type(attribute_name, column, options)
end
wrapper.find(:hint).
render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
end
# Creates a default label tag for the given attribute. You can give a label
# through the :label option or using i18n. All the given options are sent
# as :label_html.
#
# == Examples
#
# f.label :name # Do I18n lookup
# f.label :name, "Name" # Same behavior as Rails, do not add required tag
# f.label :name, label: "Name" # Same as above, but adds required tag
#
# f.label :name, required: false
# f.label :name, id: "cool_label"
#
def label(attribute_name, *args)
return super if args.first.is_a?(String) || block_given?
options = args.extract_options!.dup
options[:label_html] = options.except(:label, :required, :as)
column = find_attribute_column(attribute_name)
input_type = default_input_type(attribute_name, column, options)
SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options).label
end
# Creates an error notification message that only appears when the form object
# has some error. You can give a specific message with the :message option,
# otherwise it will look for a message using I18n. All other options given are
# passed straight as html options to the html tag.
#
# == Examples
#
# f.error_notification
# f.error_notification message: 'Something went wrong'
# f.error_notification id: 'user_error_message', class: 'form_error'
#
def error_notification(options = {})
SimpleForm::ErrorNotification.new(self, options).render
end
# Create a collection of radio inputs for the attribute. Basically this
# helper will create a radio input associated with a label for each
# text/value option in the collection, using value_method and text_method
# to convert these text/value. You can give a symbol or a proc to both
# value_method and text_method, that will be evaluated for each item in
# the collection.
#
# == Examples
#
# form_for @user do |f|
# f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# end
#
#
#
#
#
#
# It is also possible to give a block that should generate the radio +
# label. To wrap the radio with the label, for instance:
#
# form_for @user do |f|
# f.collection_radio_buttons(
# :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# ) do |b|
# b.label { b.radio_button + b.text }
# end
# end
#
# == Options
#
# Collection radio accepts some extra options:
#
# * checked => the value that should be checked initially.
#
# * disabled => the value or values that should be disabled. Accepts a single
# item or an array of items.
#
# * collection_wrapper_tag => the tag to wrap the entire collection.
#
# * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
#
# * item_wrapper_tag => the tag to wrap each item in the collection.
#
# * item_wrapper_class => the CSS class to use for item_wrapper_tag
#
# * a block => to generate the label + radio or any other component.
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
SimpleForm::Tags::CollectionRadioButtons.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
end
# Creates a collection of check boxes for each item in the collection,
# associated with a clickable label. Use value_method and text_method to
# convert items in the collection for use as text/value in check boxes.
# You can give a symbol or a proc to both value_method and text_method,
# that will be evaluated for each item in the collection.
#
# == Examples
#
# form_for @user do |f|
# f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# end
#
#
#
#
#
#
#
#
# It is also possible to give a block that should generate the check box +
# label. To wrap the check box with the label, for instance:
#
# form_for @user do |f|
# f.collection_check_boxes(
# :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# ) do |b|
# b.label { b.check_box + b.text }
# end
# end
#
# == Options
#
# Collection check box accepts some extra options:
#
# * checked => the value or values that should be checked initially. Accepts
# a single item or an array of items. It overrides existing associations.
#
# * disabled => the value or values that should be disabled. Accepts a single
# item or an array of items.
#
# * collection_wrapper_tag => the tag to wrap the entire collection.
#
# * collection_wrapper_class => the CSS class to use for collection_wrapper_tag. This option
# is ignored if the :collection_wrapper_tag option is blank.
#
# * item_wrapper_tag => the tag to wrap each item in the collection.
#
# * item_wrapper_class => the CSS class to use for item_wrapper_tag
#
# * a block => to generate the label + check box or any other component.
def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
SimpleForm::Tags::CollectionCheckBoxes.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
end
# Extract the model names from the object_name mess, ignoring numeric and
# explicit child indexes.
#
# Example:
#
# route[blocks_attributes][0][blocks_learning_object_attributes][1][foo_attributes]
# ["route", "blocks", "blocks_learning_object", "foo"]
#
def lookup_model_names #:nodoc:
@lookup_model_names ||= begin
child_index = options[:child_index]
names = object_name.to_s.scan(/(?!\d)\w+/).flatten
names.delete(child_index) if child_index
names.each { |name| name.gsub!('_attributes', '') }
names.freeze
end
end
# The action to be used in lookup.
def lookup_action #:nodoc:
@lookup_action ||= begin
action = template.controller && template.controller.action_name
return unless action
action = action.to_s
ACTIONS[action] || action
end
end
private
def fetch_association_collection(reflection, options)
options.fetch(:collection) do
relation = reflection.klass.all
if reflection.respond_to?(:scope) && reflection.scope
relation = reflection.klass.instance_exec(&reflection.scope)
else
order = reflection.options[:order]
conditions = reflection.options[:conditions]
conditions = object.instance_exec(&conditions) if conditions.respond_to?(:call)
relation = relation.where(conditions)
relation = relation.order(order) if relation.respond_to?(:order)
end
relation
end
end
def build_association_attribute(reflection, association, options)
case reflection.macro
when :belongs_to
(reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
when :has_one
raise ArgumentError, ":has_one associations are not supported by f.association"
else
if options[:as] == :select
html_options = options[:input_html] ||= {}
html_options[:multiple] = true unless html_options.key?(:multiple)
end
# Force the association to be preloaded for performance.
if options[:preload] != false && object.respond_to?(association)
target = object.send(association)
target.to_a if target.respond_to?(:to_a)
end
:"#{reflection.name.to_s.singularize}_ids"
end
end
# Find an input based on the attribute name.
def find_input(attribute_name, options = {}, &block)
column = find_attribute_column(attribute_name)
input_type = default_input_type(attribute_name, column, options)
if block_given?
SimpleForm::Inputs::BlockInput.new(self, attribute_name, column, input_type, options, &block)
else
find_mapping(input_type).new(self, attribute_name, column, input_type, options)
end
end
# Attempt to guess the better input type given the defined options. By
# default alwayls fallback to the user :as option, or to a :select when a
# collection is given.
def default_input_type(attribute_name, column, options)
return options[:as].to_sym if options[:as]
custom_type = find_custom_type(attribute_name.to_s) and return custom_type
return :select if options[:collection]
input_type = column.try(:type)
case input_type
when :timestamp
:datetime
when :string, nil
case attribute_name.to_s
when /password/ then :password
when /time_zone/ then :time_zone
when /country/ then :country
when /email/ then :email
when /phone/ then :tel
when /url/ then :url
else
file_method?(attribute_name) ? :file : (input_type || :string)
end
else
input_type
end
end
def find_custom_type(attribute_name)
SimpleForm.input_mappings.find { |match, type|
attribute_name =~ match
}.try(:last) if SimpleForm.input_mappings
end
def file_method?(attribute_name)
file = @object.send(attribute_name) if @object.respond_to?(attribute_name)
file && SimpleForm.file_methods.any? { |m| file.respond_to?(m) }
end
def find_attribute_column(attribute_name)
if @object.respond_to?(:column_for_attribute) && @object.has_attribute?(attribute_name)
@object.column_for_attribute(attribute_name)
end
end
def find_association_reflection(association)
if @object.class.respond_to?(:reflect_on_association)
@object.class.reflect_on_association(association)
end
end
# Attempts to find a mapping. It follows the following rules:
#
# 1) It tries to find a registered mapping, if succeeds:
# a) Try to find an alternative with the same name in the Object scope
# b) Or use the found mapping
# 2) If not, fallbacks to #{input_type}Input
# 3) If not, fallbacks to SimpleForm::Inputs::#{input_type}Input
def find_mapping(input_type)
discovery_cache[input_type] ||=
if mapping = self.class.mappings[input_type]
mapping_override(mapping) || mapping
else
camelized = "#{input_type.to_s.camelize}Input"
attempt_mapping_with_custom_namespace(camelized) ||
attempt_mapping(camelized, Object) ||
attempt_mapping(camelized, self.class) ||
raise("No input found for #{input_type}")
end
end
# Attempts to find a wrapper mapping. It follows the following rules:
#
# 1) It tries to find a wrapper for the current form
# 2) If not, it tries to find a config
def find_wrapper_mapping(input_type)
if options[:wrapper_mappings] && options[:wrapper_mappings][input_type]
options[:wrapper_mappings][input_type]
else
SimpleForm.wrapper_mappings && SimpleForm.wrapper_mappings[input_type]
end
end
def find_wrapper(input_type, options)
if name = options[:wrapper] || find_wrapper_mapping(input_type)
name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
else
wrapper
end
end
# If cache_discovery is enabled, use the class level cache that persists
# between requests, otherwise use the instance one.
def discovery_cache
if SimpleForm.cache_discovery
self.class.discovery_cache
else
@discovery_cache ||= {}
end
end
def mapping_override(klass)
name = klass.name
if name =~ /^SimpleForm::Inputs/
input_name = name.split("::").last
attempt_mapping_with_custom_namespace(input_name) ||
attempt_mapping(input_name, Object)
end
end
def attempt_mapping(mapping, at)
return if SimpleForm.inputs_discovery == false && at == Object
begin
at.const_get(mapping)
rescue NameError => e
raise if e.message !~ /#{mapping}$/
end
end
def attempt_mapping_with_custom_namespace(input_name)
SimpleForm.custom_inputs_namespaces.each do |namespace|
if (mapping = attempt_mapping(input_name, namespace.constantize))
return mapping
end
end
nil
end
end
end
simple-form-3.2.0/lib/simple_form/helpers.rb 0000644 0001750 0001750 00000001061 12623141213 021222 0 ustar terceiro terceiro module SimpleForm
# Helpers are made of several helpers that cannot be turned on automatically.
# For instance, disabled cannot be turned on automatically, it requires the
# user to explicitly pass the option disabled: true so it may work.
module Helpers
autoload :Autofocus, 'simple_form/helpers/autofocus'
autoload :Disabled, 'simple_form/helpers/disabled'
autoload :Readonly, 'simple_form/helpers/readonly'
autoload :Required, 'simple_form/helpers/required'
autoload :Validators, 'simple_form/helpers/validators'
end
end
simple-form-3.2.0/lib/simple_form/wrappers.rb 0000644 0001750 0001750 00000000462 12623141213 021427 0 ustar terceiro terceiro module SimpleForm
module Wrappers
autoload :Builder, 'simple_form/wrappers/builder'
autoload :Many, 'simple_form/wrappers/many'
autoload :Root, 'simple_form/wrappers/root'
autoload :Single, 'simple_form/wrappers/single'
autoload :Leaf, 'simple_form/wrappers/leaf'
end
end
simple-form-3.2.0/lib/simple_form/helpers/ 0000755 0001750 0001750 00000000000 12623141213 020677 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/helpers/autofocus.rb 0000644 0001750 0001750 00000000240 12623141213 023230 0 ustar terceiro terceiro module SimpleForm
module Helpers
module Autofocus
private
def has_autofocus?
options[:autofocus] == true
end
end
end
end
simple-form-3.2.0/lib/simple_form/helpers/disabled.rb 0000644 0001750 0001750 00000000344 12623141213 022774 0 ustar terceiro terceiro module SimpleForm
module Helpers
module Disabled
private
def has_disabled?
options[:disabled] == true
end
def disabled_class
:disabled if has_disabled?
end
end
end
end
simple-form-3.2.0/lib/simple_form/helpers/readonly.rb 0000644 0001750 0001750 00000000344 12623141213 023042 0 ustar terceiro terceiro module SimpleForm
module Helpers
module Readonly
private
def readonly_class
:readonly if has_readonly?
end
def has_readonly?
options[:readonly] == true
end
end
end
end
simple-form-3.2.0/lib/simple_form/helpers/validators.rb 0000644 0001750 0001750 00000002111 12623141213 023367 0 ustar terceiro terceiro module SimpleForm
module Helpers
module Validators
def has_validators?
@has_validators ||= attribute_name && object.class.respond_to?(:validators_on)
end
private
def attribute_validators
object.class.validators_on(attribute_name)
end
def reflection_validators
reflection ? object.class.validators_on(reflection.name) : []
end
def valid_validator?(validator)
!conditional_validators?(validator) && action_validator_match?(validator)
end
def conditional_validators?(validator)
validator.options.include?(:if) || validator.options.include?(:unless)
end
def action_validator_match?(validator)
return true if !validator.options.include?(:on)
case validator.options[:on]
when :save
true
when :create
!object.persisted?
when :update
object.persisted?
end
end
def find_validator(kind)
attribute_validators.find { |v| v.kind == kind } if has_validators?
end
end
end
end
simple-form-3.2.0/lib/simple_form/helpers/required.rb 0000644 0001750 0001750 00000001435 12623141213 023047 0 ustar terceiro terceiro module SimpleForm
module Helpers
module Required
private
def required_field?
@required
end
def calculate_required
if !options[:required].nil?
options[:required]
elsif has_validators?
required_by_validators?
else
required_by_default?
end
end
def required_by_validators?
(attribute_validators + reflection_validators).any? { |v| v.kind == :presence && valid_validator?(v) }
end
def required_by_default?
SimpleForm.required_by_default
end
# Do not use has_required? because we want to add the class
# regardless of the required option.
def required_class
required_field? ? :required : :optional
end
end
end
end
simple-form-3.2.0/lib/simple_form/map_type.rb 0000644 0001750 0001750 00000000676 12623141213 021411 0 ustar terceiro terceiro require 'active_support/core_ext/class/attribute'
module SimpleForm
module MapType
def self.extended(base)
base.class_attribute :mappings
base.mappings = {}
end
def map_type(*types)
map_to = types.extract_options![:to]
raise ArgumentError, "You need to give :to as option to map_type" unless map_to
self.mappings = mappings.merge types.each_with_object({}) { |t, m| m[t] = map_to }
end
end
end
simple-form-3.2.0/lib/simple_form/components/ 0000755 0001750 0001750 00000000000 12623141213 021422 5 ustar terceiro terceiro simple-form-3.2.0/lib/simple_form/components/errors.rb 0000644 0001750 0001750 00000002740 12623141213 023266 0 ustar terceiro terceiro module SimpleForm
module Components
module Errors
def error(wrapper_options = nil)
error_text if has_errors?
end
def full_error(wrapper_options = nil)
full_error_text if options[:error] != false && has_errors?
end
def has_errors?
object && object.respond_to?(:errors) && errors.present?
end
protected
def error_text
text = has_custom_error? ? options[:error] : errors.send(error_method)
"#{html_escape(options[:error_prefix])} #{html_escape(text)}".lstrip.html_safe
end
def full_error_text
has_custom_error? ? options[:error] : full_errors.send(error_method)
end
def error_method
options[:error_method] || SimpleForm.error_method
end
def errors
@errors ||= (errors_on_attribute + errors_on_association).compact
end
def full_errors
@full_errors ||= (full_errors_on_attribute + full_errors_on_association).compact
end
def errors_on_attribute
object.errors[attribute_name]
end
def full_errors_on_attribute
object.errors.full_messages_for(attribute_name)
end
def errors_on_association
reflection ? object.errors[reflection.name] : []
end
def full_errors_on_association
reflection ? object.errors.full_messages_for(reflection.name) : []
end
def has_custom_error?
options[:error].is_a?(String)
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/hints.rb 0000644 0001750 0001750 00000001005 12623141213 023070 0 ustar terceiro terceiro module SimpleForm
module Components
# Needs to be enabled in order to do automatic lookups.
module Hints
def hint(wrapper_options = nil)
@hint ||= begin
hint = options[:hint]
if hint.is_a?(String)
html_escape(hint)
else
content = translate_from_namespace(:hints)
content.html_safe if content
end
end
end
def has_hint?
options[:hint] != false && hint.present?
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/pattern.rb 0000644 0001750 0001750 00000001453 12623141213 023427 0 ustar terceiro terceiro module SimpleForm
module Components
# Needs to be enabled in order to do automatic lookups.
module Pattern
def pattern(wrapper_options = nil)
input_html_options[:pattern] ||= pattern_source
nil
end
private
def pattern_source
pattern = options[:pattern]
if pattern.is_a?(String)
pattern
elsif (pattern_validator = find_pattern_validator) && (with = pattern_validator.options[:with])
evaluate_format_validator_option(with).source
end
end
def find_pattern_validator
find_validator(:format)
end
def evaluate_format_validator_option(option)
if option.respond_to?(:call)
option.call(object)
else
option
end
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/placeholders.rb 0000644 0001750 0001750 00000000671 12623141213 024420 0 ustar terceiro terceiro module SimpleForm
module Components
# Needs to be enabled in order to do automatic lookups.
module Placeholders
def placeholder(wrapper_options = nil)
input_html_options[:placeholder] ||= placeholder_text
nil
end
def placeholder_text
placeholder = options[:placeholder]
placeholder.is_a?(String) ? placeholder : translate_from_namespace(:placeholders)
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/html5.rb 0000644 0001750 0001750 00000001164 12623141213 023002 0 ustar terceiro terceiro module SimpleForm
module Components
module HTML5
def initialize(*)
@html5 = false
end
def html5(wrapper_options = nil)
@html5 = true
input_html_options[:required] = has_required?
input_html_options[:'aria-required'] = has_required? || nil
nil
end
def html5?
@html5
end
def has_required?
# We need to check browser_validations because
# some browsers are still checking required even
# if novalidate was given.
required_field? && SimpleForm.browser_validations
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/labels.rb 0000644 0001750 0001750 00000004730 12623141213 023215 0 ustar terceiro terceiro module SimpleForm
module Components
module Labels
extend ActiveSupport::Concern
module ClassMethods #:nodoc:
def translate_required_html
i18n_cache :translate_required_html do
I18n.t(:"simple_form.required.html", default:
%[#{translate_required_mark}]
)
end
end
def translate_required_text
I18n.t(:"simple_form.required.text", default: 'required')
end
def translate_required_mark
I18n.t(:"simple_form.required.mark", default: '*')
end
end
def label(wrapper_options = nil)
label_options = merge_wrapper_options(label_html_options, wrapper_options)
if generate_label_for_attribute?
@builder.label(label_target, label_text, label_options)
else
template.label_tag(nil, label_text, label_options)
end
end
def label_text(wrapper_options = nil)
label_text = options[:label_text] || SimpleForm.label_text
label_text.call(html_escape(raw_label_text), required_label_text, options[:label].present?).strip.html_safe
end
def label_target
attribute_name
end
def label_html_options
label_html_classes = SimpleForm.additional_classes_for(:label) {
[input_type, required_class, disabled_class, SimpleForm.label_class].compact
}
label_options = html_options_for(:label, label_html_classes)
if options.key?(:input_html) && options[:input_html].key?(:id)
label_options[:for] = options[:input_html][:id]
end
label_options
end
protected
def raw_label_text #:nodoc:
options[:label] || label_translation
end
# Default required text when attribute is required.
def required_label_text #:nodoc:
required_field? ? self.class.translate_required_html.dup : ''
end
# First check labels translation and then human attribute name.
def label_translation #:nodoc:
if SimpleForm.translate_labels && (translated_label = translate_from_namespace(:labels))
translated_label
elsif object.class.respond_to?(:human_attribute_name)
object.class.human_attribute_name(reflection_or_attribute_name.to_s)
else
attribute_name.to_s.humanize
end
end
def generate_label_for_attribute?
true
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/readonly.rb 0000644 0001750 0001750 00000001072 12623141213 023564 0 ustar terceiro terceiro module SimpleForm
module Components
# Needs to be enabled in order to do automatic lookups.
module Readonly
def readonly(wrapper_options = nil)
if readonly_attribute? && !has_readonly?
input_html_options[:readonly] ||= true
input_html_classes << :readonly
end
nil
end
private
def readonly_attribute?
object.class.respond_to?(:readonly_attributes) &&
object.persisted? &&
object.class.readonly_attributes.include?(attribute_name.to_s)
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/min_max.rb 0000644 0001750 0001750 00000002677 12623141213 023413 0 ustar terceiro terceiro module SimpleForm
module Components
module MinMax
def min_max(wrapper_options = nil)
if numeric_validator = find_numericality_validator
validator_options = numeric_validator.options
input_html_options[:min] ||= minimum_value(validator_options)
input_html_options[:max] ||= maximum_value(validator_options)
end
nil
end
private
def integer?
input_type == :integer
end
def minimum_value(validator_options)
if integer? && validator_options.key?(:greater_than)
evaluate_numericality_validator_option(validator_options[:greater_than]) + 1
else
evaluate_numericality_validator_option(validator_options[:greater_than_or_equal_to])
end
end
def maximum_value(validator_options)
if integer? && validator_options.key?(:less_than)
evaluate_numericality_validator_option(validator_options[:less_than]) - 1
else
evaluate_numericality_validator_option(validator_options[:less_than_or_equal_to])
end
end
def find_numericality_validator
find_validator(:numericality)
end
def evaluate_numericality_validator_option(option)
if option.is_a?(Numeric)
option
elsif option.is_a?(Symbol)
object.send(option)
elsif option.respond_to?(:call)
option.call(object)
end
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/label_input.rb 0000644 0001750 0001750 00000001453 12623141213 024250 0 ustar terceiro terceiro module SimpleForm
module Components
module LabelInput
extend ActiveSupport::Concern
included do
include SimpleForm::Components::Labels
end
def label_input(wrapper_options = nil)
if options[:label] == false
deprecated_component(:input, wrapper_options)
else
deprecated_component(:label, wrapper_options) + deprecated_component(:input, wrapper_options)
end
end
private
def deprecated_component(namespace, wrapper_options)
method = method(namespace)
if method.arity == 0
ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: namespace })
method.call
else
method.call(wrapper_options)
end
end
end
end
end
simple-form-3.2.0/lib/simple_form/components/maxlength.rb 0000644 0001750 0001750 00000001567 12623141213 023747 0 ustar terceiro terceiro module SimpleForm
module Components
# Needs to be enabled in order to do automatic lookups.
module Maxlength
def maxlength(wrapper_options = nil)
input_html_options[:maxlength] ||= maximum_length_from_validation || limit
nil
end
private
def maximum_length_from_validation
maxlength = options[:maxlength]
if maxlength.is_a?(String) || maxlength.is_a?(Integer)
maxlength
else
length_validator = find_length_validator
if length_validator && !has_tokenizer?(length_validator)
length_validator.options[:is] || length_validator.options[:maximum]
end
end
end
def find_length_validator
find_validator(:length)
end
def has_tokenizer?(length_validator)
length_validator.options[:tokenizer]
end
end
end
end
simple-form-3.2.0/lib/simple_form/components.rb 0000644 0001750 0001750 00000001330 12623141213 021744 0 ustar terceiro terceiro module SimpleForm
# Components are a special type of helpers that can work on their own.
# For example, by using a component, it will automatically change the
# output under given circumstances without user input. For example,
# the disabled helper always need a disabled: true option given
# to the input in order to be enabled. On the other hand, things like
# hints can generate output automatically by doing I18n lookups.
module Components
extend ActiveSupport::Autoload
autoload :Errors
autoload :Hints
autoload :HTML5
autoload :LabelInput
autoload :Labels
autoload :MinMax
autoload :Maxlength
autoload :Pattern
autoload :Placeholders
autoload :Readonly
end
end
simple-form-3.2.0/lib/simple_form/tags.rb 0000644 0001750 0001750 00000004223 12623141213 020521 0 ustar terceiro terceiro module SimpleForm
module Tags
module CollectionExtensions
private
def render_collection
item_wrapper_tag = @options.fetch(:item_wrapper_tag, :span)
item_wrapper_class = @options[:item_wrapper_class]
@collection.map do |item|
value = value_for_collection(item, @value_method)
text = value_for_collection(item, @text_method)
default_html_options = default_html_options_for_collection(item, value)
additional_html_options = option_html_attributes(item)
rendered_item = yield item, value, text, default_html_options.merge(additional_html_options)
if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
label_options = default_html_options.slice(:index, :namespace)
label_options['class'] = @options[:item_label_class]
rendered_item = @template_object.label(@object_name, sanitize_attribute_name(value), rendered_item, label_options)
end
item_wrapper_tag ? @template_object.content_tag(item_wrapper_tag, rendered_item, class: item_wrapper_class) : rendered_item
end.join.html_safe
end
def wrap_rendered_collection(collection)
wrapper_tag = @options[:collection_wrapper_tag]
if wrapper_tag
wrapper_class = @options[:collection_wrapper_class]
@template_object.content_tag(wrapper_tag, collection, class: wrapper_class)
else
collection
end
end
end
class CollectionRadioButtons < ActionView::Helpers::Tags::CollectionRadioButtons
include CollectionExtensions
def render
wrap_rendered_collection(super)
end
private
def render_component(builder)
builder.radio_button + builder.label(class: "collection_radio_buttons")
end
end
class CollectionCheckBoxes < ActionView::Helpers::Tags::CollectionCheckBoxes
include CollectionExtensions
def render
wrap_rendered_collection(super)
end
private
def render_component(builder)
builder.check_box + builder.label(class: "collection_check_boxes")
end
end
end
end
simple-form-3.2.0/lib/simple_form/i18n_cache.rb 0000644 0001750 0001750 00000001067 12623141213 021470 0 ustar terceiro terceiro module SimpleForm
# A lot of configuration values are retrived from I18n,
# like boolean collection, required string. This module provides
# caching facility to speed up form construction.
module I18nCache
def i18n_cache(key)
get_i18n_cache(key)[I18n.locale] ||= yield.freeze
end
def get_i18n_cache(key)
if class_variable_defined?(:"@@#{key}")
class_variable_get(:"@@#{key}")
else
reset_i18n_cache(key)
end
end
def reset_i18n_cache(key)
class_variable_set(:"@@#{key}", {})
end
end
end
simple-form-3.2.0/CHANGELOG.md 0000644 0001750 0001750 00000012357 12623141213 015774 0 ustar terceiro terceiro ## 3.2.0
### bug fix
* Improve performance of input generation by disabling support for `_html` translations. This reverts the feature introduced on the 3.1.0 branch
## 3.1.1
### enhancements
* Add the `disabled_class` to the label when the input is disabled. [@rhodrid](https://github.com/rhodrid)
### bug fix
* Make it possible to override `required` value that was previously set in the wrapper. [@nashby](https://github.com/nashby)
* `date/time/datetime` inputs now correctly generate the label `for` attribute when
HTML5 compatibility is explicitly enabled. [@ericsullivan](https://github.com/ericsullivan)
* The datetime, date, and time inputs now have a nice format by default on bootstrap.
[@ulissesalmeida](https://github.com/ulissesalmeida) [@eltonchrls](https://github.com/eltonchrls)
* Now it is possible to set custom input mappings for collections.
Example:
```ruby
# On configuration:
config.input_mappings = { /gender$/ => :check_boxes }
# On form:
f.input :gender, collection: [:male, :female]
```
[strangeworks](https://github.com/strangeworks)
## 3.1.0
### enhancements
* Update foundation generator to version 5. [@jorge-d](https://github.com/jorge-d)
* Add mapping to `uuid` columns.
* Add custom namespaces for custom inputs feature. [@vala](https://github.com/vala)
* Add `:unless_blank` option to the wrapper API. [@IanVaughan](https://github.com/IanVaughan)
* Add support to html markup in the I18n options. [@laurocaetano](https://github.com/laurocaetano)
* Add the `full_error` component. [@laurocaetano](https://github.com/laurocaetano)
* Add support to `scope` to be used on associations. [@laurocaetano](https://github.com/laurocaetano)
* Execute the association `condition` in the object context. [@laurocaetano](https://github.com/laurocaetano)
* Check if the given association responds to `order` before calling it. [@laurocaetano](https://github.com/laurocaetano)
* Add Bootstrap 3 initializer template.
* For radio or checkbox collection always use `:item_wrapper_tag` to wrap the content and add `label` when using `boolean_style` with `:nested` [@kassio](https://github.com/kassio) and [@erichkist](https://github.com/erichkist)
* `input_field` uses the same wrapper as input but only with attribute components. [@nashby](https://github.com/nashby)
* Add wrapper mapping per form basis [@rcillo](https://github.com/rcillo) and [@bernardoamc](https://github.com/bernardoamc)
* Add `for` attribute to `label` when collections are rendered as radio or checkbox [@erichkist](https://github.com/erichkist), [@ulissesalmeida](https://github.com/ulissesalmeida) and [@fabioyamate](https://github.com/fabioyamate)
* Add `include_default_input_wrapper_class` config [@luizcosta](https://github.com/luizcosta)
* Map `datetime`, `date` and `time` input types to their respective HTML5 input tags
when the `:html5` is set to `true` [@volmer](https://github.com/volmer)
* Add `boolean_label_class` config.
* Add `:html` option to include additional attributes on custom wrappers [@remofritzsche](https://github.com/remofritzsche) and [@ulissesalmeida](https://github.com/ulissesalmeida)
* Make possible to use the Wrappers API to define attributes for the components.
See https://github.com/plataformatec/simple_form/pull/997 for more information.
* Put a whitespace before the `inline_label` options of boolean input if it is present.
* Add support to configure the `label_text` proc at the wrapper level. [@NOX73](https://github.com/NOX73)
* `label_text` proc now receive three arguments (label, request, and if the label was explicit). [@timscott](https://github.com/timscott)
* Add I18n support to `:include_blank` and `:prompt` when `:translate` is used as value. [@haines](https://github.com/plataformatec/simple_form/pull/616)
* Add support to define custom error messages for the attributes.
* Add support to change the I18n scope to be used in Simple Form. [@nielsbuus](https://github.com/nielsbuus)
* The default form class can now be overridden with `html: { :class }`. [@rmm5t](https://github.com/rmm5t)
### bug fix
* Fix `full_error` when the attribute is an association. [@mvdamme](https://github.com/jorge-d)
* Fix suppport to `:namespace` and `:index` options for nested check boxes and radio buttons when the attribute is an association.
* Collection input that uses automatic collection translation properly sets checked values.
Closes [#971](https://github.com/plataformatec/simple_form/issues/971) [@nashby](https://github.com/nashby)
* Collection input generates `required` attribute if it has `prompt` option. [@nashby](https://github.com/nashby)
* Grouped collection uses the first non-empty object to detect label and value methods.
## deprecation
* Methods on custom inputs now accept a required argument with the wrapper options.
See https://github.com/plataformatec/simple_form/pull/997 for more information.
* SimpleForm.form_class is deprecated in favor of SimpleForm.default_form_class.
Future versions of Simple Form will not generate `simple_form` class for the form
element.
See https://github.com/plataformatec/simple_form/pull/1109 for more information.
Please check [v3.0](https://github.com/plataformatec/simple_form/blob/v3.0/CHANGELOG.md) for previous changes.
simple-form-3.2.0/README.md 0000644 0001750 0001750 00000107111 12623141213 015433 0 ustar terceiro terceiro 
By [Plataformatec](http://plataformatec.com.br/).
Rails forms made easy.
**Simple Form** aims to be as flexible as possible while helping you with powerful components to create
your forms. The basic goal of **Simple Form** is to not touch your way of defining the layout, letting
you find the better design for your eyes. Most of the DSL was inherited from Formtastic,
which we are thankful for and should make you feel right at home.
INFO: This README is [also available in a friendly navigable format](http://simple-form.plataformatec.com.br/)
and refers to **Simple Form** 3.1. For older releases, check the related branch for your version.
## Installation
Add it to your Gemfile:
```ruby
gem 'simple_form'
```
Run the following command to install it:
```console
bundle install
```
Run the generator:
```console
rails generate simple_form:install
```
### Bootstrap
**Simple Form** can be easily integrated to the [Bootstrap](http://getbootstrap.com/).
To do that you have to use the `bootstrap` option in the install generator, like this:
```console
rails generate simple_form:install --bootstrap
```
You have to be sure that you added a copy of the [Bootstrap](http://getbootstrap.com/)
assets on your application.
For more information see the generator output, our
[example application code](https://github.com/rafaelfranca/simple_form-bootstrap) and
[the live example app](http://simple-form-bootstrap.plataformatec.com.br/).
### Zurb Foundation 5
To generate wrappers that are compatible with [Zurb Foundation 5](http://foundation.zurb.com/), pass
the `foundation` option to the generator, like this:
```console
rails generate simple_form:install --foundation
```
Please note that the Foundation wrapper does not support the `:hint` option by default. In order to
enable hints, please uncomment the appropriate line in `config/initializers/simple_form_foundation.rb`.
You will need to provide your own CSS styles for hints.
Please see the [instructions on how to install Foundation in a Rails app](http://foundation.zurb.com/docs/applications.html).
### Country Select
If you want to use the country select, you will need the
[country_select gem](https://rubygems.org/gems/country_select), add it to your Gemfile:
```ruby
gem 'country_select'
```
If you don't want to use the gem you can easily override this behaviour by mapping the
country inputs to something else, with a line like this in your `simple_form.rb` initializer:
```ruby
config.input_mappings = { /country/ => :string }
```
## Usage
**Simple Form** was designed to be customized as you need to. Basically it's a stack of components that
are invoked to create a complete html input for you, which by default contains label, hints, errors
and the input itself. It does not aim to create a lot of different logic from the default Rails
form helpers, as they do a great job by themselves. Instead, **Simple Form** acts as a DSL and just
maps your input type (retrieved from the column definition in the database) to a specific helper method.
To start using **Simple Form** you just have to use the helper it provides:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
```
This will generate an entire form with labels for user name and password as well, and render errors
by default when you render the form with invalid data (after submitting for example).
You can overwrite the default label by passing it to the input method. You can also add a hint,
an error, or even a placeholder. For boolean inputs, you can add an inline label as well:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username, label: 'Your username please', error: 'Username is mandatory, please specify one' %>
<%= f.input :password, hint: 'No special characters.' %>
<%= f.input :email, placeholder: 'user@domain.com' %>
<%= f.input :remember_me, inline_label: 'Yes, remember me' %>
<%= f.button :submit %>
<% end %>
```
In some cases you may want to disable labels, hints or error. Or you may want to configure the html
of any of them:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username, label_html: { class: 'my_class' } %>
<%= f.input :password, hint: false, error_html: { id: 'password_error'} %>
<%= f.input :password_confirmation, label: false %>
<%= f.button :submit %>
<% end %>
```
It is also possible to pass any html attribute straight to the input, by using the `:input_html`
option, for instance:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>
```
If you want to pass the same options to all inputs in the form (for example, a default class),
you can use the `:defaults` option in `simple_form_for`. Specific options in `input` call will
overwrite the defaults:
```erb
<%= simple_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>
```
Since **Simple Form** generates a wrapper div around your label and input by default, you can pass
any html attribute to that wrapper as well using the `:wrapper_html` option, like so:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username, wrapper_html: { class: 'username' } %>
<%= f.input :password, wrapper_html: { id: 'password' } %>
<%= f.input :remember_me, wrapper_html: { class: 'options' } %>
<%= f.button :submit %>
<% end %>
```
Required fields are marked with an * prepended to their labels.
By default all inputs are required. When the form object has `presence` validations attached to its
fields, **Simple Form** tells required and optional fields apart. For performance reasons, this
detection is skipped on validations that make use of conditional options, such as `:if` and `:unless`.
And of course, the `required` property of any input can be overwritten as needed:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :name, required: false %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
```
By default, **Simple Form** will look at the column type in the database and use an
appropriate input for the column. For example, a column created with type
`:text` in the database will use a `textarea` input by default. See the section
[Available input types and defaults for each column
type](https://github.com/plataformatec/simple_form#available-input-types-and-defaults-for-each-column-type)
for a complete list of defaults.
**Simple Form** also lets you overwrite the default input type it creates:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.input :description, as: :text %>
<%= f.input :accepts, as: :radio_buttons %>
<%= f.button :submit %>
<% end %>
```
So instead of a checkbox for the *accepts* attribute, you'll have a pair of radio buttons with yes/no
labels and a textarea instead of a text field for the description. You can also render boolean
attributes using `as: :select` to show a dropdown.
It is also possible to give the `:disabled` option to **Simple Form**, and it'll automatically mark
the wrapper as disabled with a CSS class, so you can style labels, hints and other components inside
the wrapper as well:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :username, disabled: true, hint: 'You cannot change your username.' %>
<%= f.button :submit %>
<% end %>
```
**Simple Form** accepts same options as their corresponding input type helper in Rails:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :date_of_birth, as: :date, start_year: Date.today.year - 90,
end_year: Date.today.year - 12, discard_day: true,
order: [:month, :year] %>
<%= f.input :accepts, as: :boolean, checked_value: true, unchecked_value: false %>
<%= f.button :submit %>
<% end %>
```
**Simple Form** also allows you to use label, hint, input_field, error and full_error helpers
(please take a look at the rdocs for each method for more info):
```erb
<%= simple_form_for @user do |f| %>
<%= f.label :username %>
<%= f.input_field :username %>
<%= f.hint 'No special characters, please!' %>
<%= f.error :username, id: 'user_name_error' %>
<%= f.full_error :token %>
<%= f.submit 'Save' %>
<% end %>
```
Any extra option passed to these methods will be rendered as html option.
### Stripping away all wrapper divs
**Simple Form** also allows you to strip away all the div wrappers around the `` field that is
generated with the usual `f.input`.
The easiest way to achieve this is to use `f.input_field`.
Example:
```ruby
simple_form_for @user do |f|
f.input_field :name
f.input_field :remember_me, as: :boolean
end
```
```html
```
For check boxes and radio buttons you can remove the label changing `boolean_style` from default value `:nested` to `:inline`.
Example:
```ruby
simple_form_for @user do |f|
f.input_field :name
f.input_field :remember_me, as: :boolean, boolean_style: :inline
end
```
```html
```
Produces:
```html
```
To view the actual RDocs for this, check them out here - http://rubydoc.info/github/plataformatec/simple_form/master/SimpleForm/FormBuilder:input_field
### Collections
And what if you want to create a select containing the age from 18 to 60 in your form? You can do it
overriding the `:collection` option:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :user %>
<%= f.input :age, collection: 18..60 %>
<%= f.button :submit %>
<% end %>
```
Collections can be arrays or ranges, and when a `:collection` is given the `:select` input will be
rendered by default, so we don't need to pass the `as: :select` option. Other types of collection
are `:radio_buttons` and `:check_boxes`. Those are added by **Simple Form** to Rails set of form
helpers (read Extra Helpers section below for more information).
Collection inputs accept two other options beside collections:
* *label_method* => the label method to be applied to the collection to retrieve the label (use this
instead of the `text_method` option in `collection_select`)
* *value_method* => the value method to be applied to the collection to retrieve the value
Those methods are useful to manipulate the given collection. Both of these options also accept
lambda/procs in case you want to calculate the value or label in a special way eg. custom
translation. All other options given are sent straight to the underlying helper. For example, you
can give prompt as:
```ruby
f.input :age, collection: 18..60, prompt: "Select your age", selected: 21
```
Extra options are passed into helper [`collection_select`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select).
It is also possible to create grouped collection selects, that will use the html *optgroup* tags, like this:
```ruby
f.input :country_id, collection: @continents, as: :grouped_select, group_method: :countries
```
Grouped collection inputs accept the same `:label_method` and `:value_method` options, which will be
used to retrieve label/value attributes for the `option` tags. Besides that, you can give:
* *group_method* => the method to be called on the given collection to generate the options for
each group (required)
* *group_label_method* => the label method to be applied on the given collection to retrieve the label
for the _optgroup_ (**Simple Form** will attempt to guess the best one the same way it does with
`:label_method`)
### Priority
**Simple Form** also supports `:time_zone` and `:country`. When using such helpers, you can give
`:priority` as an option to select which time zones and/or countries should be given higher priority:
```ruby
f.input :residence_country, priority: [ "Brazil" ]
f.input :time_zone, priority: /US/
```
Those values can also be configured with a default value to be used on the site through the
`SimpleForm.country_priority` and `SimpleForm.time_zone_priority` helpers.
Note: While using `country_select` if you want to restrict to only a subset of countries for a specific
drop down then you may use the `:collection` option:
```ruby
f.input :shipping_country, priority: [ "Brazil" ], collection: [ "Australia", "Brazil", "New Zealand"]
```
### Associations
To deal with associations, **Simple Form** can generate select inputs, a series of radios buttons or checkboxes.
Lets see how it works: imagine you have a user model that belongs to a company and `has_and_belongs_to_many`
roles. The structure would be something like:
```ruby
class User < ActiveRecord::Base
belongs_to :company
has_and_belongs_to_many :roles
end
class Company < ActiveRecord::Base
has_many :users
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end
```
Now we have the user form:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :name %>
<%= f.association :company %>
<%= f.association :roles %>
<%= f.button :submit %>
<% end %>
```
Simple enough, right? This is going to render a `:select` input for choosing the `:company`, and another
`:select` input with `:multiple` option for the `:roles`. You can, of course, change it to use radio
buttons and checkboxes as well:
```ruby
f.association :company, as: :radio_buttons
f.association :roles, as: :check_boxes
```
The association helper just invokes `input` under the hood, so all options available to `:select`,
`:radio_buttons` and `:check_boxes` are also available to association. Additionally, you can specify
the collection by hand, all together with the prompt:
```ruby
f.association :company, collection: Company.active.order(:name), prompt: "Choose a Company"
```
In case you want to declare different labels and values:
```ruby
f.association :company, label_method: :company_name, value_method: :id, include_blank: false
```
Please note that the association helper is currently only tested with Active Record. It currently
does not work well with Mongoid and depending on the ORM you're using your mileage may vary.
### Buttons
All web forms need buttons, right? **Simple Form** wraps them in the DSL, acting like a proxy:
```erb
<%= simple_form_for @user do |f| %>
<%= f.input :name %>
<%= f.button :submit %>
<% end %>
```
The above will simply call submit. You choose to use it or not, it's just a question of taste.
The button method also accepts optional parameters, that are delegated to the underlying submit call:
```erb
<%= f.button :submit, "Custom Button Text", class: "my-button" %>
```
To create a `