1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
# frozen_string_literal: true
module ClientSideValidations
module ActionView
module Helpers
module FormHelper
class Error < StandardError
end
def form_for(record, options = {}, &block)
return super unless options[:validate]
# We are not going to use super here, because we need
# to inject the csv options in a data attribute in a clean way.
# So we basically reimplement the whole form_for method
raise ArgumentError, 'Missing block' unless block
options[:html] ||= {}
# Moving the switch statement to another method to
# lower complexity
model, object_name = check_record(record, options)
remote = options.delete(:remote)
if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
options[:authenticity_token] = false
end
options[:model] = model
options[:scope] = object_name
options[:local] = !remote
options[:skip_default_ids] = false
options[:allow_method_names_outside_object] = options.fetch(:allow_method_names_outside_object, false)
form_with(**options, &block)
end
def apply_csv_form_for_options!(object, options)
options[:html][:validate] = true if options[:validate]
options[:html][:method] ||= options[:method]
apply_form_for_options! object, options
end
def fields_for(record_name, record_object = nil, options = {}, &)
# Order matters here. Rails mutates the `options` object
builder = instantiate_builder(record_name, record_object, options)
output = capture(builder, &)
build_bound_validators! options
output
end
private
def check_record(record, options)
case record
when String, Symbol
raise ClientSideValidations::ActionView::Helpers::FormHelper::Error, 'Using form_for(:name, @resource) is not supported with ClientSideValidations. Please use form_for(@resource, as: :name) instead.'
else
object = record.is_a?(Array) ? record.last : record
raise ArgumentError, 'First argument in form cannot contain nil or be empty' unless object
object_name = options[:as] || model_name_from_record_or_class(object).param_key
apply_csv_form_for_options!(object, options)
end
[record, object_name]
end
def build_bound_validators!(options)
return unless @validators
options[:validators].each do |key, value|
if @validators.key?(key)
@validators[key].merge! value
else
@validators[key] = value
end
end
end
def construct_validators
@validators.each_with_object({}) do |object_opts, validator_hash|
next unless object_opts[0].respond_to?(:client_side_validation_hash)
option_hash = object_opts[1].each_with_object({}) do |attr, result|
result[attr[0]] = attr[1][:options]
end
validation_hash = object_opts[0].client_side_validation_hash(option_hash)
option_hash.each_key do |attr|
add_validator validator_hash, validation_hash, object_opts[1][attr][:name], attr
end
end
end
def add_validator(validator_hash, validation_hash, name, attr)
if validation_hash.key?(attr)
validator_hash[name] = validation_hash[attr]
elsif attr.to_s.end_with?('_id')
association_name = attr.to_s.gsub(/_id\Z/, '').to_sym
add_validator_with_association validator_hash, validation_hash, name, association_name
elsif attr.to_s.end_with?('_ids')
association_name = attr.to_s.gsub(/_ids\Z/, '').pluralize.to_sym
add_validator_with_association validator_hash, validation_hash, name, association_name
end
end
def add_validator_with_association(validator_hash, validation_hash, name, association_name)
return unless validation_hash.key?(association_name)
validator_hash[name] = validation_hash[association_name]
end
def number_format
if ClientSideValidations::Config.number_format_with_locale && defined?(I18n)
I18n.t('number.format').slice :separator, :delimiter
else
{ separator: '.', delimiter: ',' }
end
end
def apply_csv_html_options!(html_options, options, builder)
html_options.delete 'validate'
csv_options = {
html_settings: builder.client_side_form_settings(options, self),
number_format: number_format,
validators: construct_validators
}
html_options['data-client-side-validations'] = csv_options.to_json
end
end
end
end
end
|