kaspernj/simple_form_ransack

View on GitHub
lib/simple_form_ransack/attribute_inspector.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Inpect the model namespace for labels based on Ransack-names in order to generate labels for inputs.
class SimpleFormRansack::AttributeInspector
  def initialize(args)
    @args = args
    @ransack_name = args.fetch(:name)
    @name_parts = @ransack_name.to_s.split("_")
    @instance = args.fetch(:instance)
    @clazz = args.fetch(:clazz)
    @as = args.fetch(:as)
    @debug = args[:debug]

    @generated_name_classes = []
    @models = []
    @current_clazz = @clazz
    @name_builtup = []

    research unless attribute_directly?
  end

  # Loop through the name parts and inspectors reflections with it.
  def research
    @name_parts.each_with_index do |name_part, index|
      @name_builtup << name_part

      # The last part should be the attribute name.
      if index == @name_parts.length - 1
        attribute_result = attribute_by_builtup
        next unless attribute_result

        @attribute = attribute_result.fetch(:name)
        break
      end

      # Try next - maybe next key need to be added? (which is common!)
      reflection_result = reflection_by_builtup
      next unless reflection_result

      @name_builtup = []
      reflection = reflection_result.fetch(:reflection)

      @current_clazz = reflection.klass
      @generated_name_classes << {clazz: @current_clazz, reflection:}
    end
  end

  # Returns true if a complicated label could be generated and simple form should not do this itself.
  def generated_label?
    return true if @attribute && @generated_name_classes.any?

    false
  end

  # Generates the complicated label and returns it.
  def generated_label
    @generated_label = ""

    if @generated_name_classes.last
      clazz = @generated_name_classes.last.fetch(:clazz)
      reflection = @generated_name_classes.last.fetch(:reflection)

      if reflection.collection?
        @generated_label << clazz.model_name.human(count: 2)
      else
        @generated_label << clazz.model_name.human
      end
    end

    add_id_to_generated_label
    @generated_label
  end

private

  def add_id_to_generated_label
    if @attribute == "id" && @as != "string"
      # Don't add "id" to label, because it is being shown as a collection
    else
      @generated_label << " " unless @generated_label.empty?
      @generated_label << @current_clazz.human_attribute_name(@attribute).to_s.downcase
    end
  end

  def reflection_by_builtup
    total_name = @name_builtup.join("_")
    result = @current_clazz.reflections.find { |name, _reflection| name.to_s == total_name }
    return {name: result[0], reflection: result[1]} if result

    false
  end

  def attribute_by_builtup
    total_name = @name_builtup.join("_")
    result = @current_clazz.attribute_names.find { |name| name.to_s == total_name }
    return {name: result} if result

    false
  end

  def attribute_directly?
    @clazz.attribute_names.find { |name| name.to_s == @ransack_name.to_s }
  end
end