# frozen_string_literal: true module PgEngine module FormHelper # rubocop:disable Metrics/CyclomaticComplexity def pg_form_for(object, *args, &block_passed) resource = object if object.is_a? PgEngine::BaseRecordDecorator object = object.target_object elsif object.is_a?(PgEngine::BaseRecord) && object.decorator_class.present? && object.decorator_class <= PgEngine::BaseRecordDecorator object = object.decorate.target_object end options = args.extract_options! options[:builder] = PgFormBuilder options[:html] ||= {} options[:html][:class] = if options[:html].key?(:class) ['pg-form', options[:html][:class]].compact else 'pg-form' end if resource.errors.any? options[:html][:data] ||= {} options[:html][:data][:errors] = resource.errors.details.to_json end if options[:render_errors].nil? options[:render_errors] = true end block_with_additives = lambda do |f| ret = ''.html_safe ret += f.mensajes_de_error if options[:render_errors] ret += capture(f, &block_passed) ret end simple_form_for(object, *(args << options), &block_with_additives) end # rubocop:enable Metrics/CyclomaticComplexity def url_change_format(url, formato) uri = URI.parse(url) uri.path = "#{uri.path}.#{formato}" uri.to_s end # This method creates a link with `data-id` `data-fields` attributes. # These attributes are used to create new instances of the nested fields through Javascript. def link_to_add_fields(name, form, association, required: false, view_path: nil) # view_path is required when rendering outside a controller flow # Takes an object (@person) and creates a new instance of its associated model (:addresses) # To better understand, run the following in your terminal: # rails c --sandbox # @person = Person.new # new_object = @person.send(:addresses).klass.new new_object = form.object.send(association).klass.new # Saves the unique ID of the object into a variable. # This is needed to ensure the key of the associated array is unique. # This is makes parsing the content in the `data-fields` attribute easier through Javascript. # We could use another method to achive this. id = new_object.object_id # https://api.rubyonrails.org/ fields_for(record_name, record_object = nil, fields_options = {}, &block) # record_name = :addresses # record_object = new_object # fields_options = { child_index: id } # child_index` is used to ensure the key of the associated array is unique, # and that it matched the value in the `data-id` attribute. # `person[addresses_attributes][child_index_value][_destroy]` fields = form.fields_for(association, new_object, child_index: id) do |builder| # `association.to_s.singularize + "_fields"` ends up evaluating to `address_fields` # The render function will then look for `views/people/_address_fields.html.erb` # The render function also needs to be passed the value of 'builder', because # `views/people/_address_fields.html.erb` needs this to render the form tags. render(view_path || "#{association.to_s.singularize}_fields", f: builder) end # This renders a simple link, but passes information into `data` attributes. # This info can be named anything we want, but in this case we chose `data-id:` and `data-fields:`. # The `id:` is from `new_object.object_id`. # The `fields:` are rendered from the `fields` blocks. # We use `gsub("\n", "")` to remove anywhite space from the rendered partial. # The `id:` value needs to match the value used in `child_index: id`. link_to( 'javascript:void(0)', class: 'link-to-add', data: { controller: 'nested', action: 'nested#addItem', id:, required:, fields: fields.gsub("\n", '') } ) do " #{name}".html_safe # rubocop:enable Rails/OutputSafety end end def link_to_remove(text = nil, &) if block_given? link_to('javascript:void(0)', class: 'link-to-remove text-danger-emphasis', title: 'Quitar', data: { controller: 'nested', action: 'nested#quitar' }, &) elsif text.present? link_to text, 'javascript:void(0)', class: 'link-to-remove text-danger-emphasis', title: 'Quitar', data: { controller: 'nested', action: 'nested#quitar' } else link_to 'javascript:void(0)', class: 'link-to-remove text-danger-emphasis', title: 'Quitar', data: { controller: 'nested', action: 'nested#quitar' } do ''.html_safe end end end end end