From ba8cf5534d17737fa2c591264b1849a2050df87f Mon Sep 17 00:00:00 2001 From: Harshal LADHE Date: Sat, 1 Jul 2023 13:12:56 +0530 Subject: [PATCH] Reduce method complexity of `button`, error methods , and field wrapper options --- .../field_wrapper_builder.rb | 28 ++++++----- lib/rails_bootstrap_form/helpers/buttons.rb | 48 +++++++++++++------ lib/rails_bootstrap_form/helpers/errors.rb | 45 +++++++++-------- .../special_form_class_models_spec.rb | 16 +++---- 4 files changed, 83 insertions(+), 54 deletions(-) diff --git a/lib/rails_bootstrap_form/field_wrapper_builder.rb b/lib/rails_bootstrap_form/field_wrapper_builder.rb index 02a3ee7..7fe34ec 100644 --- a/lib/rails_bootstrap_form/field_wrapper_builder.rb +++ b/lib/rails_bootstrap_form/field_wrapper_builder.rb @@ -4,6 +4,9 @@ module RailsBootstrapForm module FieldWrapperBuilder + + private + def field_wrapper_builder(attribute, bootstrap, options, html_options = nil, &block) field_options = field_css_options(attribute, bootstrap, options, html_options.try(:symbolize_keys!)) @@ -72,18 +75,11 @@ def field_wrapper_default_class(bootstrap) def field_css_options(attribute, bootstrap, options, html_options) css_options = (html_options || options) - field_classes = Array(bootstrap.field_class) << [bootstrap.additional_field_class || css_options[:class]] - field_classes << "is-invalid" if is_invalid?(attribute) - if is_size_valid?(bootstrap) - field_classes << "#{bootstrap.field_class}-#{bootstrap.size}" - end + field_classes = build_field_classes(attribute, bootstrap, css_options) css_options[:class] = field_classes.flatten.compact css_options.merge!(required_field_options(attribute, options)) - - if placeholder_required?(bootstrap) - css_options[:placeholder] ||= label_text(attribute, bootstrap) - end + add_placeholder_if_required!(css_options, attribute, bootstrap) css_options end @@ -96,11 +92,21 @@ def floating_label_classes(attribute) classes end + def build_field_classes(attribute, bootstrap, css_options) + field_classes = Array(bootstrap.field_class) << + field_classes << [bootstrap.additional_field_class || css_options[:class]] + field_classes << "is-invalid" if is_invalid?(attribute) + field_classes << "#{bootstrap.field_class}-#{bootstrap.size}" if is_size_valid?(bootstrap) + field_classes + end + def placeholder_required?(bootstrap) (bootstrap.floating? && !bootstrap.layout_horizontal?) || bootstrap.layout_inline? end - private :field_wrapper, :field_wrapper_classes, :field_wrapper_default_class, - :field_css_options, :floating_label_classes + def add_placeholder_if_required!(css_options, attribute, bootstrap) + css_options[:placeholder] ||= label_text(attribute, bootstrap) if placeholder_required?(bootstrap) + css_options + end end end diff --git a/lib/rails_bootstrap_form/helpers/buttons.rb b/lib/rails_bootstrap_form/helpers/buttons.rb index 7cc1899..7f4ef24 100644 --- a/lib/rails_bootstrap_form/helpers/buttons.rb +++ b/lib/rails_bootstrap_form/helpers/buttons.rb @@ -7,26 +7,17 @@ module Helpers module Buttons extend ActiveSupport::Concern - def self.included(base_class) + included do def button(value, options, &block) bootstrap = bootstrap_form_options.scoped(options.delete(:bootstrap)) + value, options = extract_button_value_and_options(value, options) - value, options = nil, value.merge(options) if value.is_a?(Hash) + add_button_css_classes!(options, bootstrap) - add_css_class!(options, "btn") - add_css_class!(options, button_variant_class(options)) + button_html = render_button_html(value, options, bootstrap, &block) + button_html = wrap_button_html(button_html, bootstrap) - button_html = if (bootstrap.render_as_button? || block) - button_tag(value, options, &block) - else - submit(value, options) - end - - if bootstrap.layout_inline? - tag.div(class: "col-12") { button_html } - else - button_html - end + button_html end def secondary(value = nil, options = {}, &block) @@ -52,6 +43,33 @@ def button_variant_class(options) else "" end end + + def extract_button_value_and_options(value, options) + return [nil, value.merge(options)] if value.is_a?(Hash) + + [value, options] + end + + def add_button_css_classes!(options, bootstrap) + add_css_class!(options, "btn") + add_css_class!(options, button_variant_class(options)) + end + + def render_button_html(value, options, bootstrap, &block) + if bootstrap.render_as_button? || block + button_tag(value, options, &block) + else + submit(value, options) + end + end + + def wrap_button_html(button_html, bootstrap) + if bootstrap.layout_inline? + tag.div(class: "col-12") { button_html } + else + button_html + end + end end end end diff --git a/lib/rails_bootstrap_form/helpers/errors.rb b/lib/rails_bootstrap_form/helpers/errors.rb index 7aa5d67..05f902e 100644 --- a/lib/rails_bootstrap_form/helpers/errors.rb +++ b/lib/rails_bootstrap_form/helpers/errors.rb @@ -10,16 +10,10 @@ module Errors private def is_invalid?(attribute) - (attribute && object.respond_to?(:errors) && object.errors[attribute].any?) || + (attribute && object.respond_to?(:errors) && has_attribute_error?(attribute)) || has_association_error?(attribute) end - # def input_with_error(attribute, &block) - # input = capture(&block) - # input << generate_error(attribute) - # input - # end - def generate_error(attribute) if is_invalid?(attribute) error_text = error_messages(attribute) @@ -29,23 +23,41 @@ def generate_error(attribute) end end + def error_messages(attribute) + messages = Array(attribute_error_messages(attribute)) + messages << associated_error_messages(attribute) + + messages.flatten.to_sentence + end + + def has_attribute_error?(attribute) + attribute_error_messages(attribute).any? + end + def has_association_error?(attribute) object.class.try(:reflections)&.any? do |association_name, association| - has_error_for_association?(attribute, association_name) + has_errors_on_association?(attribute, association_name) end end - def error_messages(attribute) - messages = object.errors[attribute] + def has_errors_on_association?(attribute, association_name) + return false unless is_belongs_to_association?(object.class.reflections[association_name]) + return false unless is_association_same?(attribute, object.class.reflections[association_name]) + + object.errors[association_name].any? + end + + def attribute_error_messages(attribute) + object.errors[attribute] + end - object.class.try(:reflections)&.each do |association_name, association| + def associated_error_messages(attribute) + object.class.try(:reflections)&.each_with_object([]) do |(association_name, association), messages| next unless is_belongs_to_association?(association) next unless is_association_same?(attribute, association) messages << object.errors[association_name] end - - messages.flatten.to_sentence end def is_belongs_to_association?(association) @@ -55,13 +67,6 @@ def is_belongs_to_association?(association) def is_association_same?(attribute, association) (association.foreign_key == attribute.to_s) end - - def has_error_for_association?(attribute, association_name) - return false unless is_belongs_to_association?(object.class.reflections[association_name]) - return false unless is_association_same?(attribute, object.class.reflections[association_name]) - - object.errors[association_name].any? - end end end end diff --git a/spec/rails_bootstrap_form/special_form_class_models_spec.rb b/spec/rails_bootstrap_form/special_form_class_models_spec.rb index 6675d54..f099a5d 100644 --- a/spec/rails_bootstrap_form/special_form_class_models_spec.rb +++ b/spec/rails_bootstrap_form/special_form_class_models_spec.rb @@ -94,19 +94,19 @@ def self.model_name } }) expected = <<~HTML -
-
+
+
-
-
+
can't be blank and
+
A good password should be at least six characters long
-
can't be blank
-
A good password should be at least six characters long
-
+ HTML - actual = form_builder.text_field(:password) + actual = bootstrap_form_with(model: admin_user, url: "/test") do |form| + concat(form.text_field(:password)) + end expect(actual).to match_html(expected) end