Module: FoxTail::Concerns::Formable

Constant Summary collapse

FORM_OPTIONS =
%i[
  object_name method_name namespace object
  skip_default_ids allow_method_names_outside_object
  value_array object_index
].freeze

Instance Method Summary collapse

Instance Method Details

#add_default_id(attributes: html_attributes) ⇒ Object



116
117
118
119
120
121
122
123
124
# File 'app/components/fox_tail/concerns/formable.rb', line 116

def add_default_id(attributes: html_attributes)
  return if skip_default_ids?

  if attributes.key? :id
    attributes[:id] = attributes[:id] ? "#{namespace}_#{attributes[:id]}" : namespace if namespace?
  else
    attributes[:id] = tag_id
  end
end

#add_default_name(attributes: html_attributes) ⇒ Object



112
113
114
# File 'app/components/fox_tail/concerns/formable.rb', line 112

def add_default_name(attributes: html_attributes)
  attributes[:name] = tag_name unless attributes.key? :name
end

#add_default_name_and_id(attributes: html_attributes) ⇒ Object



107
108
109
110
# File 'app/components/fox_tail/concerns/formable.rb', line 107

def add_default_name_and_id(attributes: html_attributes)
  add_default_name attributes: attributes
  add_default_id attributes: attributes
end

#add_default_name_and_id_for_value(value, attributes: html_attributes) ⇒ Object



87
88
89
90
# File 'app/components/fox_tail/concerns/formable.rb', line 87

def add_default_name_and_id_for_value(value, attributes: html_attributes)
  add_default_name attributes: attributes
  attributes[:id] = tag_id_for_value value, attributes: attributes unless attributes.key? :id
end

#field_id(method, *suffixes, namespace: self.namespace, index: object_index) ⇒ Object



126
127
128
# File 'app/components/fox_tail/concerns/formable.rb', line 126

def field_id(method, *suffixes, namespace: self.namespace, index: object_index)
  view_context.field_id(object_name, method, *suffixes, namespace: namespace.presence, index: index.presence).presence
end

#field_name(method, *methods, multiple: false, index: object_index) ⇒ Object



130
131
132
# File 'app/components/fox_tail/concerns/formable.rb', line 130

def field_name(method, *methods, multiple: false, index: object_index)
  view_context.field_name(object_name, method, *methods, index: index.presence, multiple: !!multiple).presence
end

#initializeObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/components/fox_tail/concerns/formable.rb', line 25

def initialize(*)
  super

  options[:object_name] = object_name.to_s.dup if object_name?
  options[:method_name] = method_name.to_s.dup if method_name?

  return unless object_name?

  object_name.sub!(/\[\]$/, "") || object_name.sub!(/\[\]\]$/, "]")

  if Regexp.last_match
    @generate_indexed_names = true
    @auto_index = retrieve_autoindex
  else
    @generate_indexed_names = false
    @auto_index = nil
  end
end

#name_and_id_indexObject



44
45
46
47
48
49
50
# File 'app/components/fox_tail/concerns/formable.rb', line 44

def name_and_id_index
  if options.key? :object_index
    object_index.presence || ""
  elsif @generate_indexed_names
    @auto_index || ""
  end
end

#object_errors?(methods = object_errors_for) ⇒ Boolean

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
# File 'app/components/fox_tail/concerns/formable.rb', line 158

def object_errors?(methods = object_errors_for)
  return false if methods.blank?

  object = convert_to_model self.object
  return false if object.blank?

  methods.any? { |m| object.errors[m].present? }
end

#object_errors_forObject



154
155
156
# File 'app/components/fox_tail/concerns/formable.rb', line 154

def object_errors_for
  (Array(method_name) + Array(options[:errors_for])).compact_blank.uniq
end

#objectify_options(options) ⇒ Object



167
168
169
# File 'app/components/fox_tail/concerns/formable.rb', line 167

def objectify_options(options)
  options.merge self.options.slice(*FORM_OPTIONS)
end

#retrieve_autoindexObject



65
66
67
68
69
70
71
72
73
# File 'app/components/fox_tail/concerns/formable.rb', line 65

def retrieve_autoindex
  unless object.respond_to?(:to_param)
    raise ArgumentError, <<~MSG
      object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}
    MSG
  end

  object.to_param
end

#sanitized_method_nameObject



142
143
144
# File 'app/components/fox_tail/concerns/formable.rb', line 142

def sanitized_method_name
  @sanitized_method_name ||= method_name.presence&.delete_suffix("?")
end

#sanitized_value(value) ⇒ Object



146
147
148
# File 'app/components/fox_tail/concerns/formable.rb', line 146

def sanitized_value(value)
  value.to_s.gsub(/[\s.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
end

#tag_idObject



138
139
140
# File 'app/components/fox_tail/concerns/formable.rb', line 138

def tag_id
  field_id method_name, index: name_and_id_index, namespace: namespace
end

#tag_id_for_value(value, attributes = html_attributes) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'app/components/fox_tail/concerns/formable.rb', line 92

def tag_id_for_value(value, attributes = html_attributes)
  if value.nil?
    tag_id
  else
    specified_id = attributes[:id]
    id = tag_id

    if specified_id.blank? && id.present?
      "#{id}_#{sanitized_value(tag_value)}"
    else
      tag_id
    end
  end
end

#tag_nameObject



134
135
136
# File 'app/components/fox_tail/concerns/formable.rb', line 134

def tag_name
  field_name sanitized_method_name, multiple: value_array?, index: name_and_id_index
end

#translator(value: nil, scope: nil, default: "") ⇒ Object



150
151
152
# File 'app/components/fox_tail/concerns/formable.rb', line 150

def translator(value: nil, scope: nil, default: "")
  FoxTail::Translator.new object, object_name, method_name, value: value, scope: scope, default: default
end

#value_before_type_castObject



75
76
77
78
79
80
81
82
83
84
85
# File 'app/components/fox_tail/concerns/formable.rb', line 75

def value_before_type_cast
  return if object.nil?

  method_before_type_cast = "#{method_name}_before_type_cast"

  if value_came_from_user? && object.respond_to?(method_before_type_cast)
    object.public_send(method_before_type_cast)
  else
    value_from_object
  end
end

#value_came_from_user?Boolean

Returns:

  • (Boolean)


60
61
62
63
# File 'app/components/fox_tail/concerns/formable.rb', line 60

def value_came_from_user?
  method_came_from_user = "#{method_name}_came_from_user?"
  !object.respond_to?(method_came_from_user) || object.public_send(method_came_from_user)
end

#value_from_objectObject



52
53
54
55
56
57
58
# File 'app/components/fox_tail/concerns/formable.rb', line 52

def value_from_object
  if @allow_method_names_outside_object
    object.public_send method_name if object.respond_to?(method_name)
  else
    object&.public_send method_name
  end
end