module ClientSideValidations::ActionView::Helpers::FormHelper

Public Instance Methods

apply_csv_form_for_options!(record, object, options) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 39
def apply_csv_form_for_options!(record, object, options)
  options[:html][:validate] = true if options[:validate]
  options[:html][:method] ||= options[:method]

  # TODO: remove else branch when minimum compatible version when dropping 6.1 support
  if method(:apply_form_for_options!).arity == 2
    apply_form_for_options! object, options
  else
    apply_form_for_options! record, object, options
  end
end
fields_for(record_name, record_object = nil, options = {}, &block) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 51
def fields_for(record_name, record_object = nil, options = {}, &block)
  # Order matters here. Rails mutates the `options` object
  builder = instantiate_builder(record_name, record_object, options)
  output = capture(builder, &block)

  build_bound_validators! options

  output
end
form_for(record, options = {}, &block) click to toggle source
Calls superclass method
# File lib/client_side_validations/action_view/form_helper.rb, line 10
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
form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block) click to toggle source
Calls superclass method
# File lib/client_side_validations/action_view/form_with_helper.rb, line 7
def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
  return super unless options[:validate]

  options[:allow_method_names_outside_object] = true
  options[:skip_default_ids] = false

  url, model, scope = check_model(url, model, format, scope) if model

  if block
    form_tag_with_validators scope, model, options, url, &block
  else
    html_options = html_options_for_form_with(url, model, **options)
    form_tag_html(html_options)
  end
end

Private Instance Methods

add_validator(validator_hash, validation_hash, name, attr) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 106
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
add_validator_with_association(validator_hash, validation_hash, name, association_name) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 118
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
apply_csv_html_options!(html_options, options, builder) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 132
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
build_bound_validators!(options) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 78
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
check_model(url, model, format, scope) click to toggle source
# File lib/client_side_validations/action_view/form_with_helper.rb, line 25
def check_model(url, model, format, scope)
  url ||= polymorphic_path(model, format: format)

  model   = model.last if model.is_a?(Array)
  scope ||= model_name_from_record_or_class(model).param_key

  [url, model, scope]
end
check_record(record, options) click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 63
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!(record, object, options)
  end

  [record, object_name]
end
construct_validators() click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 90
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
form_tag_with_validators(scope, model, options, url, &block) click to toggle source
# File lib/client_side_validations/action_view/form_with_helper.rb, line 34
def form_tag_with_validators(scope, model, options, url, &block)
  @validators = {}

  builder = instantiate_builder(scope, model, options)
  output  = capture(builder, &block)
  options[:multipart] ||= builder.multipart?

  build_bound_validators! options

  html_options = html_options_for_form_with(url, model, **options)

  if model
    html_options[:novalidate] ||= 'novalidate'
    apply_csv_html_options! html_options, options, builder
  end

  form_tag_with_body(html_options, output)
end
number_format() click to toggle source
# File lib/client_side_validations/action_view/form_helper.rb, line 124
def number_format
  if ClientSideValidations::Config.number_format_with_locale && defined?(I18n)
    I18n.t('number.format').slice :separator, :delimiter
  else
    { separator: '.', delimiter: ',' }
  end
end