caring_form 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +17 -0
- data/Appraisals +18 -0
- data/Gemfile +9 -0
- data/Guardfile +15 -0
- data/LICENSE +22 -0
- data/README.md +33 -0
- data/Rakefile +12 -0
- data/app/assets/javascripts/caring_form/form-observer.coffee +63 -0
- data/app/assets/javascripts/caring_form/main.coffee +15 -0
- data/app/assets/javascripts/caring_form/remote-validator.coffee +71 -0
- data/app/assets/javascripts/caring_form/rule-based-validator.coffee +37 -0
- data/app/assets/javascripts/caring_form/setup.coffee +5 -0
- data/app/assets/javascripts/caring_form/webshims-customization.coffee +25 -0
- data/app/assets/javascripts/caring_forms.js +7 -0
- data/caring_form.gemspec +31 -0
- data/gemfiles/rails_3_1.gemfile +8 -0
- data/gemfiles/rails_3_2.gemfile +8 -0
- data/gemfiles/rails_4.gemfile +7 -0
- data/gemfiles/rails_4_1.gemfile +8 -0
- data/lib/caring_form.rb +20 -0
- data/lib/caring_form/action_view_extensions/builder.rb +75 -0
- data/lib/caring_form/action_view_extensions/config.rb +4 -0
- data/lib/caring_form/action_view_extensions/flash_error_helper.rb +28 -0
- data/lib/caring_form/action_view_extensions/form_helper.rb +33 -0
- data/lib/caring_form/active_model/monkey_patching.rb +32 -0
- data/lib/caring_form/dsl.rb +91 -0
- data/lib/caring_form/engine.rb +4 -0
- data/lib/caring_form/field/base.rb +145 -0
- data/lib/caring_form/field/check_box.rb +23 -0
- data/lib/caring_form/field/check_boxes.rb +15 -0
- data/lib/caring_form/field/collection.rb +48 -0
- data/lib/caring_form/field/dummy.rb +30 -0
- data/lib/caring_form/field/email.rb +41 -0
- data/lib/caring_form/field/full_name.rb +40 -0
- data/lib/caring_form/field/looking_for.rb +37 -0
- data/lib/caring_form/field/metadata.rb +26 -0
- data/lib/caring_form/field/radio_buttons.rb +15 -0
- data/lib/caring_form/field/string.rb +13 -0
- data/lib/caring_form/field/submit.rb +83 -0
- data/lib/caring_form/field/tel.rb +37 -0
- data/lib/caring_form/field/text.rb +13 -0
- data/lib/caring_form/field/us_zip_code.rb +37 -0
- data/lib/caring_form/field_container.rb +126 -0
- data/lib/caring_form/form_builder.rb +51 -0
- data/lib/caring_form/model.rb +58 -0
- data/lib/caring_form/model/active_model.rb +11 -0
- data/lib/caring_form/model/active_record.rb +38 -0
- data/lib/caring_form/simple_form/initializer.rb +26 -0
- data/lib/caring_form/simple_form/monkey_patching.rb +51 -0
- data/lib/caring_form/tools/referee.rb +62 -0
- data/lib/caring_form/version.rb +3 -0
- data/lib/tasks/webshims.rake +7 -0
- data/spec/caring_form/action_view_extensions/flash_error_helper_spec.rb +50 -0
- data/spec/caring_form/action_view_extensions/form_helper_spec.rb +72 -0
- data/spec/caring_form/dsl_spec.rb +21 -0
- data/spec/caring_form/field/base_spec.rb +204 -0
- data/spec/caring_form/field/check_boxes_spec.rb +32 -0
- data/spec/caring_form/field/collection_spec.rb +28 -0
- data/spec/caring_form/field/radio_buttons_spec.rb +29 -0
- data/spec/caring_form/field/submit_spec.rb +57 -0
- data/spec/caring_form/field_container_spec.rb +85 -0
- data/spec/caring_form/form_builder_spec.rb +113 -0
- data/spec/caring_form/model_spec.rb +235 -0
- data/spec/caring_form/tools/referee_spec.rb +86 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/nokogiri_matcher.rb +204 -0
- metadata +278 -0
data/lib/caring_form.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "caring_form/version"
|
|
2
|
+
require 'caring_form/simple_form/initializer'
|
|
3
|
+
require 'caring_form/simple_form/monkey_patching'
|
|
4
|
+
require 'caring_form/active_model/monkey_patching'
|
|
5
|
+
|
|
6
|
+
if defined?(Rails)
|
|
7
|
+
require 'caring_form/engine'
|
|
8
|
+
require "webshims-rails"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module CaringForm
|
|
12
|
+
Error = Class.new(StandardError)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require 'caring_form/model'
|
|
16
|
+
require 'caring_form/form_builder'
|
|
17
|
+
require 'caring_form/action_view_extensions/form_helper'
|
|
18
|
+
require 'caring_form/action_view_extensions/builder'
|
|
19
|
+
require 'caring_form/action_view_extensions/config'
|
|
20
|
+
require 'caring_form/action_view_extensions/flash_error_helper'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module CaringForm
|
|
2
|
+
module ActionViewExtensions
|
|
3
|
+
module Builder
|
|
4
|
+
def collection_caring_radio(*args)
|
|
5
|
+
collection_caring(:radio_button, *args)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def collection_caring_check(attribute, collection, value, text, options = {}, html_options = {})
|
|
9
|
+
if html_options[:required] && options[:collection] && options[:collection].length > 1
|
|
10
|
+
html_options.delete(:required)
|
|
11
|
+
html_options[:class] = "group-required #{html_options[:class]}".strip
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
collection_caring(:check_box, attribute, collection, value, text, options, html_options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def collection_caring(input_helper, attribute, collection, value_method, text_method, options={}, html_options={})
|
|
20
|
+
collection.inject('') do |result, item|
|
|
21
|
+
value = item.send value_method
|
|
22
|
+
text = item.send text_method
|
|
23
|
+
|
|
24
|
+
default_html_options = begin
|
|
25
|
+
if self.respond_to? :default_html_options_for_collection
|
|
26
|
+
default_html_options_for_collection(item, value, options, html_options)
|
|
27
|
+
else
|
|
28
|
+
@default_options.merge(html_options)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
label_options = {:class => 'rhs'}
|
|
33
|
+
|
|
34
|
+
if default_html_options.has_key?(:id)
|
|
35
|
+
value = value.gsub(/\s+/, '').underscore
|
|
36
|
+
default_html_options[:id] = "#{default_html_options[:id]}_#{value}"
|
|
37
|
+
label_options[:for] = default_html_options[:id]
|
|
38
|
+
label_name = nil
|
|
39
|
+
else
|
|
40
|
+
label_name = "#{attribute}_#{value}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
html = if input_helper == :radio_button
|
|
44
|
+
radio_button(attribute, value, default_html_options)
|
|
45
|
+
else
|
|
46
|
+
default_html_options[:multiple] = true
|
|
47
|
+
check_box(attribute, default_html_options, value, '')
|
|
48
|
+
end
|
|
49
|
+
result << html
|
|
50
|
+
result << if label_name.nil?
|
|
51
|
+
label(:not_used, text, label_options)
|
|
52
|
+
else
|
|
53
|
+
label(label_name, text, label_options)
|
|
54
|
+
end
|
|
55
|
+
result << '<br />'.html_safe
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
ActionView::Helpers::FormBuilder.send :include, CaringForm::ActionViewExtensions::Builder
|
|
63
|
+
|
|
64
|
+
require 'simple_form'
|
|
65
|
+
module SimpleForm
|
|
66
|
+
class FormBuilder
|
|
67
|
+
if defined?(SimpleForm::Inputs::CollectionRadioButtonsInput)
|
|
68
|
+
map_type :caring_radio, :to => SimpleForm::Inputs::CollectionRadioButtonsInput
|
|
69
|
+
map_type :caring_check, :to => SimpleForm::Inputs::CollectionCheckBoxesInput
|
|
70
|
+
else
|
|
71
|
+
map_type :caring_radio, :to => SimpleForm::Inputs::CollectionInput
|
|
72
|
+
map_type :caring_check, :to => SimpleForm::Inputs::CollectionInput
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module CaringForm
|
|
2
|
+
module ActionViewExtensions
|
|
3
|
+
module FlashErrorHelper
|
|
4
|
+
def caring_form_errors_for(form)
|
|
5
|
+
return '' if form.valid?
|
|
6
|
+
header, message = form.error_config.values_at(:header, :message)
|
|
7
|
+
|
|
8
|
+
content_tag(:div, :class => 'flash error') do
|
|
9
|
+
content_tag(:h2, header) +
|
|
10
|
+
content_tag(:div, :class => 'flash-close') do
|
|
11
|
+
content_tag(:a, "Close", :href => 'javascript:void(0)')
|
|
12
|
+
end +
|
|
13
|
+
content_tag(:div, :class => 'message') do
|
|
14
|
+
message.html_safe + content_tag(:ul) do
|
|
15
|
+
form.errors.values.flatten.map do |error_message|
|
|
16
|
+
content_tag(:li, error_message)
|
|
17
|
+
end.join.html_safe
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if defined?(ActionView)
|
|
27
|
+
ActionView::Base.send :include, CaringForm::ActionViewExtensions::FlashErrorHelper
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# TODO: be more flexible for URL generation (set form object #to_param, #persisted?, etc... to rely on rails conventions)
|
|
2
|
+
module CaringForm
|
|
3
|
+
module ActionViewExtensions
|
|
4
|
+
module FormHelper
|
|
5
|
+
def caring_form_for(form_object, *args, &block)
|
|
6
|
+
block ||= proc {}
|
|
7
|
+
options = args.extract_options!
|
|
8
|
+
options[:builder] = CaringForm::FormBuilder
|
|
9
|
+
options[:url] = options.fetch(:url) do
|
|
10
|
+
form_object.url.present? ? form_object.url : url_for(params)
|
|
11
|
+
end
|
|
12
|
+
options[:html] ||= {}
|
|
13
|
+
options[:html][:class] = class_value(form_object, options[:html][:class])
|
|
14
|
+
options[:html][:id] ||= form_object.id unless form_object.id.nil?
|
|
15
|
+
args << options
|
|
16
|
+
form_for(form_object, *args, &block)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def class_value(form, extra_classes)
|
|
22
|
+
classes = %w(caring-form form-text simple_form)
|
|
23
|
+
classes.push(form.classes) if form.classes.present?
|
|
24
|
+
classes.push(extra_classes) if extra_classes.present?
|
|
25
|
+
classes.join(' ')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if defined?(ActionView)
|
|
32
|
+
ActionView::Base.send :include, CaringForm::ActionViewExtensions::FormHelper
|
|
33
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'active_model'
|
|
2
|
+
|
|
3
|
+
if ActiveModel::VERSION::MAJOR == 3 && ActiveModel::VERSION::MINOR == 0
|
|
4
|
+
|
|
5
|
+
require 'active_model/validations/inclusion'
|
|
6
|
+
|
|
7
|
+
# backport inclusion validation from v3.1+ where :in can be a lambda/proc
|
|
8
|
+
class ActiveModel::Validations::InclusionValidator
|
|
9
|
+
ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
|
|
10
|
+
"and must be supplied as the :in option of the configuration hash"
|
|
11
|
+
|
|
12
|
+
def check_validity!
|
|
13
|
+
unless [:include?, :call].any?{ |method| options[:in].respond_to?(method) }
|
|
14
|
+
raise ArgumentError, ERROR_MESSAGE
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def validate_each(record, attribute, value)
|
|
19
|
+
delimiter = options[:in]
|
|
20
|
+
exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
|
|
21
|
+
unless exclusions.send(inclusion_method(exclusions), value)
|
|
22
|
+
record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def inclusion_method(enumerable)
|
|
29
|
+
enumerable.is_a?(Range) ? :cover? : :include?
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'caring_form/field_container'
|
|
2
|
+
|
|
3
|
+
module CaringForm
|
|
4
|
+
module Dsl
|
|
5
|
+
def self.included(klass)
|
|
6
|
+
klass.instance_eval do
|
|
7
|
+
include CaringForm::FieldContainer
|
|
8
|
+
extend ClassMethods
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def autofocus?(name)
|
|
13
|
+
self.class.autofocus == name
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def index_on
|
|
17
|
+
return nil unless (index_name = self.class.index_on)
|
|
18
|
+
return nil unless respond_to?(index_name)
|
|
19
|
+
value = send(index_name)
|
|
20
|
+
value.present? ? value : nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def spam?
|
|
24
|
+
self.class.can_check_spam? && reference.present?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def attributes(options = {})
|
|
28
|
+
keys = if options.has_key?(:except)
|
|
29
|
+
except = options[:except]
|
|
30
|
+
field_names do |name, field|
|
|
31
|
+
except.none? { |key, value| field[key] == value }
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
field_names
|
|
35
|
+
end
|
|
36
|
+
keys.each_with_object({}) do |key, hash|
|
|
37
|
+
next unless respond_to?(key)
|
|
38
|
+
value = send(key)
|
|
39
|
+
hash[key.to_sym] = value unless value.nil?
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def error_config
|
|
44
|
+
self.class.error_config
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ClassMethods
|
|
48
|
+
[:autofocus, :index_on, :id, :url, :classes].each do |variable|
|
|
49
|
+
variable_name = :"@#{variable}"
|
|
50
|
+
define_method(variable) do |*names|
|
|
51
|
+
instance_variable_set(variable_name, names.first) unless names.empty?
|
|
52
|
+
instance_variable_get(variable_name)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def protect_from_bots
|
|
57
|
+
dummy(:reference, :ancillary => true)
|
|
58
|
+
@can_check_spam = true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def can_check_spam?
|
|
62
|
+
@can_check_spam == true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def on_error(options = {})
|
|
66
|
+
@error_config = options.slice(:header, :message)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def error_config
|
|
70
|
+
@error_config ||= {
|
|
71
|
+
:header => "Sorry, this operation failed",
|
|
72
|
+
:message => "Please fix the errors below and try again."
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def method_missing(meth, *args, &blk)
|
|
77
|
+
if CaringForm::FieldContainer::field_for(meth)
|
|
78
|
+
singleton = (class << self; self; end)
|
|
79
|
+
singleton.send(:define_method, meth) do |*meth_args|
|
|
80
|
+
options = meth_args.extract_options!.merge(:type => meth)
|
|
81
|
+
meth_args << nil if meth_args.empty? # set name to nil if no name
|
|
82
|
+
field(*(meth_args << options))
|
|
83
|
+
end
|
|
84
|
+
send(meth, *args)
|
|
85
|
+
else
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# TODO: remove :wrapper that's only used to wrap a submit (use wrapper_tag instead?)
|
|
2
|
+
# TODO: replace :required_message with a more generic way of overriding built-in field validation messages
|
|
3
|
+
# TODO: allow to override validation message in the UI (warning: many validation rules on server side but only one validation message on client side)
|
|
4
|
+
# TODO: document the API: which fields accept which options?
|
|
5
|
+
# TODO: move non generic fields to their own place (looking_for, us_zip_code, etc...)
|
|
6
|
+
# TODO: make sure we pass through all options we don't handle to simple_form so caring_form builder is a subset of simple_form builder
|
|
7
|
+
# TODO: make sure we have a clear pattern to override field defaults, field declaration (form object) and field options (view) and that we use it everywhere
|
|
8
|
+
# TODO: use locale to store default messages such as default validation messages
|
|
9
|
+
|
|
10
|
+
require 'caring_form/tools/referee'
|
|
11
|
+
|
|
12
|
+
module CaringForm
|
|
13
|
+
module Field
|
|
14
|
+
def self.field_attributes
|
|
15
|
+
[
|
|
16
|
+
:type, :hint, :optional, :label, :pattern, :remote_validator,
|
|
17
|
+
:collection, :wrapper, :wrapper_tag, :wrapper_html, :input_html,
|
|
18
|
+
:input_tag, :label_html, :ancillary, :primary, :prompt, :as, :if,
|
|
19
|
+
:required_message, :value
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Base = Struct.new(:name, *CaringForm::Field.field_attributes) do
|
|
24
|
+
def self.register(type)
|
|
25
|
+
CaringForm::FieldContainer.register_field(self, type)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(*args)
|
|
29
|
+
super
|
|
30
|
+
|
|
31
|
+
self.type ||= :string
|
|
32
|
+
self.optional ||= false
|
|
33
|
+
self.input_tag ||= 'input'
|
|
34
|
+
self.wrapper_tag ||= 'li'
|
|
35
|
+
self.wrapper_html ||= {}
|
|
36
|
+
self.input_html ||= {}
|
|
37
|
+
self.label_html ||= {}
|
|
38
|
+
self.ancillary ||= false
|
|
39
|
+
self.required_message ||= "Enter the #{name.to_s.humanize.downcase}"
|
|
40
|
+
|
|
41
|
+
self.label = default_label if self.label.nil?
|
|
42
|
+
|
|
43
|
+
@referee = Tools::Referee.new(self)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def apply_to_model(klass)
|
|
47
|
+
klass.send(:attr_accessor, name)
|
|
48
|
+
options = {:message => required_message}
|
|
49
|
+
if @referee.is_rule?(:optional)
|
|
50
|
+
referee = @referee
|
|
51
|
+
options[:if] = lambda do |form|
|
|
52
|
+
!referee.decide(:optional, form)
|
|
53
|
+
end
|
|
54
|
+
klass.send(:validates_presence_of, name, options)
|
|
55
|
+
elsif !optional
|
|
56
|
+
options[:if] = self.if if self.if.present?
|
|
57
|
+
klass.send(:validates_presence_of, name, options)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def input_properties(form, options = {})
|
|
62
|
+
options = normalize_options(form, options)
|
|
63
|
+
req = {
|
|
64
|
+
:as => options.fetch(:as, simple_type),
|
|
65
|
+
:collection => options.fetch(:collection, collection),
|
|
66
|
+
:prompt => options.fetch(:prompt, prompt),
|
|
67
|
+
:label => options.fetch(:label, label),
|
|
68
|
+
:wrapper => options.fetch(:wrapper, wrapper),
|
|
69
|
+
:wrapper_tag => options.fetch(:wrapper_tag, wrapper_tag),
|
|
70
|
+
:wrapper_html => options.fetch(:wrapper_html, wrapper_html).merge(:class => 'field'),
|
|
71
|
+
:input_html => options.fetch(:input_html, input_html),
|
|
72
|
+
:label_html => options.fetch(:label_html, label_html)
|
|
73
|
+
}
|
|
74
|
+
req[:input_html][:autofocus] = 'autofocus' if form.autofocus?(name)
|
|
75
|
+
req[:input_html][:title] ||= required_message if required_message.present?
|
|
76
|
+
if form.errors[self.name].present?
|
|
77
|
+
req[:wrapper_html][:class] = "field-with-errors #{req[:wrapper_html][:class]}".rstrip
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if form.index_on.present?
|
|
81
|
+
req[:label_html][:index] = req[:input_html][:index] = form.index_on
|
|
82
|
+
end
|
|
83
|
+
if @referee.decide(:optional, form)
|
|
84
|
+
req[:required] = false
|
|
85
|
+
else
|
|
86
|
+
req[:input_html][:required] = 'required'
|
|
87
|
+
end
|
|
88
|
+
req[:input_html].merge!(@referee.rule_as_data_attribute(:optional, form))
|
|
89
|
+
req[:input_html][:name] = name if ancillary
|
|
90
|
+
set_hint!(req)
|
|
91
|
+
set_remote_validator!(req)
|
|
92
|
+
req.deep_merge!(options)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def simple_type
|
|
96
|
+
raise "override me!"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def default_label
|
|
100
|
+
self.name.to_s.humanize.titleize
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def render(form, builder, options = {})
|
|
104
|
+
properties = input_properties(form, options)
|
|
105
|
+
if properties[:generate] == false
|
|
106
|
+
''
|
|
107
|
+
else
|
|
108
|
+
properties[:required] = true unless optional
|
|
109
|
+
builder.input(name, properties)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def normalize_options(form, options)
|
|
116
|
+
options = options.dup
|
|
117
|
+
[:label, :collection].each do |name|
|
|
118
|
+
value = options.fetch(name, send(name))
|
|
119
|
+
options[name] = form.send(value) if value.is_a?(Symbol)
|
|
120
|
+
end
|
|
121
|
+
if_value = options.fetch(:if, self.if)
|
|
122
|
+
options[:generate] = form.send(if_value) if if_value.is_a?(Symbol)
|
|
123
|
+
options
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def set_hint!(req)
|
|
127
|
+
return unless hint.present?
|
|
128
|
+
req[:hint] = hint
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def set_remote_validator!(req)
|
|
132
|
+
return unless remote_validator.present?
|
|
133
|
+
req[:as] = :string_inline_error
|
|
134
|
+
url, idle = if remote_validator.respond_to?(:values_at)
|
|
135
|
+
remote_validator.values_at(:url, :idle_time)
|
|
136
|
+
else
|
|
137
|
+
[remote_validator, nil]
|
|
138
|
+
end
|
|
139
|
+
req[:input_html][:'data-validator-url'] = url
|
|
140
|
+
req[:input_html][:'data-max-idle-time'] = idle if idle
|
|
141
|
+
req[:input_html][:class] = "validate-remotely #{req[:input_html][:class]}".strip
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|