importance 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/importance/imports_controller.rb +62 -74
- data/app/views/importance/imports/map.html.erb +8 -8
- data/config/locales/de.yml +11 -1
- data/config/locales/en.yml +11 -1
- data/config/locales/fr.yml +11 -1
- data/config/locales/it.yml +11 -1
- data/lib/importance/configuration.rb +46 -2
- data/lib/importance/version.rb +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 495f2f10d4834e86a1224ba0368b4642fb136c371dc79f635cd5d2187be756f9
         | 
| 4 | 
            +
              data.tar.gz: 9971a1b0c872ab7a4f1b705ff3b105b9217d95a7c1030043053f69a1ae95fc53
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f73128060f9b98baac9959e8a3f94ba3e061d019b7b2d06df6145afaec892ff4271a4f4b34052c4ac700010f52ef3603da750327e20006e0f40539a4b2dbdc10
         | 
| 7 | 
            +
              data.tar.gz: 131100a75c3ea0b074f3a097d759b77bd582b549c7206e469c7a180ce3b716c576bfa25fdaf0183d7b899cdce48c9297af9e71296f41d2af9021bddb65d99d4e
         | 
| @@ -6,125 +6,113 @@ module Importance | |
| 6 6 | 
             
                # Form submission target. Persist the file and redirect to the mapping page.
         | 
| 7 7 | 
             
                def submit
         | 
| 8 8 | 
             
                  upload = params[:file]
         | 
| 9 | 
            +
                  session[:redirect_url] = params[:redirect_url]
         | 
| 10 | 
            +
                  session[:importer] = params[:importer].to_sym
         | 
| 9 11 |  | 
| 10 | 
            -
                   | 
| 12 | 
            +
                  if upload.nil?
         | 
| 13 | 
            +
                    flash[:alert] = t("importance.errors.no_file")
         | 
| 14 | 
            +
                    redirect_to session[:redirect_url] and return
         | 
| 15 | 
            +
                  end
         | 
| 11 16 |  | 
| 12 17 | 
             
                  upload_extension = File.extname(upload.original_filename).downcase
         | 
| 13 18 | 
             
                  supported_extensions = [ ".xlsx", ".xls", ".csv" ]
         | 
| 14 19 |  | 
| 15 | 
            -
                   | 
| 20 | 
            +
                  if !supported_extensions.include?(upload_extension)
         | 
| 21 | 
            +
                    flash[:alert] = t("importance.errors.invalid_file_type", types: supported_extensions.join(", "))
         | 
| 22 | 
            +
                    redirect_to session[:redirect_url] and return
         | 
| 23 | 
            +
                  end
         | 
| 16 24 |  | 
| 17 25 | 
             
                  system_tmp_dir = Dir.tmpdir
         | 
| 18 26 | 
             
                  upload_path = upload.tempfile.path
         | 
| 19 27 | 
             
                  persist_filename = "#{SecureRandom.uuid}#{upload_extension}"
         | 
| 20 28 |  | 
| 21 29 | 
             
                  persist_path =  File.join(system_tmp_dir, persist_filename)
         | 
| 30 | 
            +
                  session[:path] = persist_path
         | 
| 22 31 |  | 
| 23 | 
            -
                   | 
| 32 | 
            +
                  if !File.exist?(upload_path)
         | 
| 33 | 
            +
                    flash[:alert] = t("importance.errors.no_file")
         | 
| 34 | 
            +
                    redirect_to session[:redirect_url] and return
         | 
| 35 | 
            +
                  end
         | 
| 24 36 |  | 
| 25 37 | 
             
                  FileUtils.mv(upload_path, persist_path)
         | 
| 26 38 |  | 
| 27 | 
            -
                  session[:path] = persist_path
         | 
| 28 | 
            -
                  session[:importer] = params[:importer].to_sym
         | 
| 29 | 
            -
                  session[:redirect_url] = params[:redirect_url]
         | 
| 30 | 
            -
             | 
| 31 39 | 
             
                  redirect_to map_path
         | 
| 32 40 | 
             
                end
         | 
| 33 41 |  | 
| 34 42 | 
             
                # Mapping page. Load headers and samples, display the form.
         | 
| 35 43 | 
             
                def map
         | 
| 36 | 
            -
                   | 
| 37 | 
            -
             | 
| 38 | 
            -
                  raise ArgumentError, "Importer cannot be nil" if importer.nil?
         | 
| 44 | 
            +
                  @layout = "Importance::#{Importance.configuration.layout.to_s.camelize}Layout".constantize
         | 
| 45 | 
            +
                  @importer = Importance.configuration.importers[session[:importer].to_sym]
         | 
| 39 46 |  | 
| 40 | 
            -
                   | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                   | 
| 44 | 
            -
                  @full_count = worksheet.count - 1
         | 
| 47 | 
            +
                  if @importer.nil?
         | 
| 48 | 
            +
                    flash[:alert] = t("importance.errors.no_importer")
         | 
| 49 | 
            +
                    redirect_to session[:redirect_url] and return
         | 
| 50 | 
            +
                  end
         | 
| 45 51 |  | 
| 46 | 
            -
                  @ | 
| 47 | 
            -
                  @layout = "Importance::#{Importance.configuration.layout.to_s.camelize}Layout".constantize
         | 
| 52 | 
            +
                  @importer.add_spreadsheet(session[:path])
         | 
| 48 53 | 
             
                end
         | 
| 49 54 |  | 
| 50 55 | 
             
                # Import page. Load the file according to the mapping and import it.
         | 
| 51 56 | 
             
                # Mappings param is of the form mappings[excel_column_idx] = target_attribute
         | 
| 52 57 | 
             
                # mappings[0] = "first_name", mappings[1] = "", mappings[2] = "last_name" ...
         | 
| 53 58 | 
             
                def import
         | 
| 54 | 
            -
                   | 
| 55 | 
            -
                   | 
| 56 | 
            -
             | 
| 57 | 
            -
                  raise ArgumentError, "Mapping cannot be nil" if mappings.nil?
         | 
| 59 | 
            +
                  @layout = "Importance::#{Importance.configuration.layout.to_s.camelize}Layout".constantize
         | 
| 60 | 
            +
                  @importer = Importance.configuration.importers[session[:importer].to_sym]
         | 
| 58 61 |  | 
| 59 | 
            -
                  if importer. | 
| 60 | 
            -
                     | 
| 62 | 
            +
                  if @importer.nil?
         | 
| 63 | 
            +
                    flash[:alert] = t("importance.errors.no_importer")
         | 
| 64 | 
            +
                    render :map and return
         | 
| 61 65 | 
             
                  end
         | 
| 62 66 |  | 
| 63 | 
            -
                   | 
| 64 | 
            -
                    records_to_import = []
         | 
| 67 | 
            +
                  @importer.add_spreadsheet(session[:path])
         | 
| 65 68 |  | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                        instance_exec(records_to_import, &importer.perform_callback)
         | 
| 71 | 
            -
                        records_to_import = []
         | 
| 72 | 
            -
                      end
         | 
| 73 | 
            -
                    end
         | 
| 69 | 
            +
                  if params[:mappings].nil?
         | 
| 70 | 
            +
                    flash[:alert] = t("importance.errors.no_mappings")
         | 
| 71 | 
            +
                    render :map and return
         | 
| 72 | 
            +
                  end
         | 
| 74 73 |  | 
| 75 | 
            -
             | 
| 76 | 
            -
                      instance_exec(records_to_import, &importer.perform_callback)
         | 
| 77 | 
            -
                    end
         | 
| 74 | 
            +
                  @mappings = params[:mappings].permit!.to_h.map { |k, v| [ k.to_i, v ] }.to_h
         | 
| 78 75 |  | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
                     | 
| 82 | 
            -
                      redirect_to (session[:redirect_url] || main_app.root_path), notice: "Import completed."
         | 
| 83 | 
            -
                    end
         | 
| 76 | 
            +
                  @importer.importer_attributes.each do |attribute|
         | 
| 77 | 
            +
                    next if !attribute.options[:required]
         | 
| 78 | 
            +
                    next if @mappings.values.include?(attribute.key.to_s)
         | 
| 84 79 |  | 
| 85 | 
            -
             | 
| 86 | 
            -
                     | 
| 87 | 
            -
                      instance_exec(e, &importer.error_callback)
         | 
| 88 | 
            -
                    end
         | 
| 80 | 
            +
                    flash[:alert] = t("importance.errors.missing_mapping", attribute: attribute.labels.first)
         | 
| 81 | 
            +
                    render :map and return
         | 
| 89 82 | 
             
                  end
         | 
| 90 | 
            -
                end
         | 
| 91 83 |  | 
| 92 | 
            -
             | 
| 84 | 
            +
                  @mappings.each do |column_index, attribute_name|
         | 
| 85 | 
            +
                    next if attribute_name == ""
         | 
| 86 | 
            +
                    next if @mappings.values.count(attribute_name) <= 1
         | 
| 93 87 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 88 | 
            +
                    flash[:alert] = t("importance.errors.duplicate_mapping", attribute: attribute_name)
         | 
| 89 | 
            +
                    render :map and return
         | 
| 90 | 
            +
                  end
         | 
| 97 91 |  | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                def each_processed_row(mappings)
         | 
| 101 | 
            -
                  workbook = Roo::Spreadsheet.open(session[:path], { csv_options: { encoding: "bom|utf-8" } })
         | 
| 102 | 
            -
                  worksheet = workbook.sheet(0)
         | 
| 103 | 
            -
                  worksheet.each_with_index do |row, idx|
         | 
| 104 | 
            -
                    next if idx == 0 # Skip header row
         | 
| 105 | 
            -
                    record = process_row(row, mappings)
         | 
| 106 | 
            -
                    next if record.empty? || record.values.all? { |v| v.nil? || v.to_s.strip.empty? }
         | 
| 107 | 
            -
                    yield record
         | 
| 92 | 
            +
                  if @importer.setup_callback
         | 
| 93 | 
            +
                    instance_exec(&@importer.setup_callback)
         | 
| 108 94 | 
             
                  end
         | 
| 109 | 
            -
                end
         | 
| 110 95 |  | 
| 111 | 
            -
             | 
| 112 | 
            -
                # and a mapping of the form {"0"=>"first_name", "1"=>"last_name", "2"=>"", "3"=>"", "4"=>"", "5"=>"email"}
         | 
| 113 | 
            -
                # into a record of the form { first_name: "Hans", last_name: "Robert", email: "hr@apple.com" }
         | 
| 114 | 
            -
                def process_row(row, mappings)
         | 
| 115 | 
            -
                  record = {}
         | 
| 96 | 
            +
                  records_to_import = []
         | 
| 116 97 |  | 
| 117 | 
            -
                   | 
| 118 | 
            -
                     | 
| 119 | 
            -
             | 
| 120 | 
            -
                     | 
| 98 | 
            +
                  @importer.each_processed_row(session[:path], @mappings) do |record|
         | 
| 99 | 
            +
                    records_to_import << record
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    if @importer.batch && records_to_import.size >= @importer.batch
         | 
| 102 | 
            +
                      instance_exec(records_to_import, &@importer.perform_callback)
         | 
| 103 | 
            +
                      records_to_import = []
         | 
| 104 | 
            +
                    end
         | 
| 121 105 | 
             
                  end
         | 
| 122 106 |  | 
| 123 | 
            -
                   | 
| 124 | 
            -
             | 
| 107 | 
            +
                  if records_to_import.any?
         | 
| 108 | 
            +
                    instance_exec(records_to_import, &@importer.perform_callback)
         | 
| 109 | 
            +
                  end
         | 
| 125 110 |  | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 111 | 
            +
                  if @importer.teardown_callback
         | 
| 112 | 
            +
                    instance_exec(&@importer.teardown_callback)
         | 
| 113 | 
            +
                  else
         | 
| 114 | 
            +
                    redirect_to (session[:redirect_url] || main_app.root_path), notice: t("importance.success.import_completed")
         | 
| 115 | 
            +
                  end
         | 
| 128 116 | 
             
                end
         | 
| 129 117 | 
             
              end
         | 
| 130 118 | 
             
            end
         | 
| @@ -4,32 +4,32 @@ | |
| 4 4 | 
             
                <table class="importance-table <%= @layout.table_class %>">
         | 
| 5 5 | 
             
                  <thead>
         | 
| 6 6 | 
             
                    <tr>
         | 
| 7 | 
            -
                      <% @file_headers.each_with_index do |file_header, file_header_idx| %>
         | 
| 7 | 
            +
                      <% @importer.file_headers.each_with_index do |file_header, file_header_idx| %>
         | 
| 8 8 | 
             
                        <th>
         | 
| 9 9 | 
             
                          <%= t('importance.use_column_as') %>
         | 
| 10 10 | 
             
                          <%
         | 
| 11 | 
            -
                            attribute_mappings = Importance::Header.match_attributes_to_headers(@importer_attributes, @file_headers)
         | 
| 12 | 
            -
                            default_value = Importance::Header.default_value_for_header(file_header, attribute_mappings)
         | 
| 11 | 
            +
                            attribute_mappings = Importance::Header.match_attributes_to_headers(@importer.importer_attributes, @importer.file_headers)
         | 
| 12 | 
            +
                            default_value = (@mappings && @mappings[file_header_idx]) || Importance::Header.default_value_for_header(file_header, attribute_mappings)
         | 
| 13 13 | 
             
                          %>
         | 
| 14 14 | 
             
                          <%= form.select "mappings[#{file_header_idx}]",
         | 
| 15 15 | 
             
                                          options_for_select(
         | 
| 16 16 | 
             
                                            [[t('importance.ignore'), ""]] + 
         | 
| 17 | 
            -
                                            @importer_attributes.map { |attr| [attr.labels.first, attr.key] },
         | 
| 17 | 
            +
                                            @importer.importer_attributes.map { |attr| [attr.labels.first, attr.key] },
         | 
| 18 18 | 
             
                                            default_value
         | 
| 19 19 | 
             
                                          ), {}, class: @layout.select_class %>
         | 
| 20 20 | 
             
                        </th>
         | 
| 21 21 | 
             
                      <% end %>
         | 
| 22 22 | 
             
                    </tr>
         | 
| 23 23 | 
             
                    <tr>
         | 
| 24 | 
            -
                      <% @file_headers.each do |file_header| %>
         | 
| 24 | 
            +
                      <% @importer.file_headers.each do |file_header| %>
         | 
| 25 25 | 
             
                        <th><%= file_header %></th>
         | 
| 26 26 | 
             
                      <% end %>
         | 
| 27 27 | 
             
                    </tr>
         | 
| 28 28 | 
             
                  </thead>
         | 
| 29 29 | 
             
                  <tbody>
         | 
| 30 | 
            -
                    <% @samples.each do |sample| %>
         | 
| 30 | 
            +
                    <% @importer.samples.each do |sample| %>
         | 
| 31 31 | 
             
                      <tr>
         | 
| 32 | 
            -
                        <% @file_headers.each_with_index do |file_header, file_header_idx| %>
         | 
| 32 | 
            +
                        <% @importer.file_headers.each_with_index do |file_header, file_header_idx| %>
         | 
| 33 33 | 
             
                          <td><%= sample[file_header_idx] %></td>
         | 
| 34 34 | 
             
                        <% end %>
         | 
| 35 35 | 
             
                      </tr>
         | 
| @@ -38,7 +38,7 @@ | |
| 38 38 | 
             
                </table>
         | 
| 39 39 | 
             
              </div>
         | 
| 40 40 | 
             
              <p>
         | 
| 41 | 
            -
                <%= t('importance.import_description', count: @samples.count, full_count: @full_count) %>
         | 
| 41 | 
            +
                <%= t('importance.import_description', count: @importer.samples.count, full_count: @importer.full_count) %>
         | 
| 42 42 | 
             
              </p>
         | 
| 43 43 | 
             
            <% end %>
         | 
| 44 44 |  | 
    
        data/config/locales/de.yml
    CHANGED
    
    | @@ -3,4 +3,14 @@ de: | |
| 3 3 | 
             
                use_column_as: Spalte verwenden als
         | 
| 4 4 | 
             
                ignore: Ignorieren
         | 
| 5 5 | 
             
                import: Importieren
         | 
| 6 | 
            -
                import_description:  | 
| 6 | 
            +
                import_description: Es werden %{count} von %{full_count} Beispieldatensätzen angezeigt.
         | 
| 7 | 
            +
                errors:
         | 
| 8 | 
            +
                  no_importer: Kein Importer ausgewählt.
         | 
| 9 | 
            +
                  no_file: Keine Datei hochgeladen.
         | 
| 10 | 
            +
                  invalid_file_type: Ungültiger Dateityp. Erlaubt sind %{types}.
         | 
| 11 | 
            +
                  no_mappings: Keine Zuordnungen angegeben.
         | 
| 12 | 
            +
                  duplicate_mapping: Attribut %{attribute} wird mehrfach verwendet.
         | 
| 13 | 
            +
                  import_failed: Import fehlgeschlagen. %{error}.
         | 
| 14 | 
            +
                  missing_mapping: Fehlende Zuordnung für erforderliches Attribut %{attribute}.
         | 
| 15 | 
            +
                success:
         | 
| 16 | 
            +
                  import_completed: Import abgeschlossen.
         | 
    
        data/config/locales/en.yml
    CHANGED
    
    | @@ -3,4 +3,14 @@ en: | |
| 3 3 | 
             
                use_column_as: Use column as
         | 
| 4 4 | 
             
                ignore: Ignore
         | 
| 5 5 | 
             
                import: Import
         | 
| 6 | 
            -
                import_description:  | 
| 6 | 
            +
                import_description: Showing %{count} of %{full_count} sample records.
         | 
| 7 | 
            +
                errors:
         | 
| 8 | 
            +
                  no_importer: No importer selected.
         | 
| 9 | 
            +
                  no_file: No file uploaded.
         | 
| 10 | 
            +
                  invalid_file_type: Invalid file type. Allowed types are %{types}.
         | 
| 11 | 
            +
                  no_mappings: No mappings provided.
         | 
| 12 | 
            +
                  duplicate_mapping: Attribute %{attribute} is used multiple times.
         | 
| 13 | 
            +
                  import_failed: Import failed. %{error}.
         | 
| 14 | 
            +
                  missing_mapping: Missing mapping for required attribute %{attribute}.
         | 
| 15 | 
            +
                success:
         | 
| 16 | 
            +
                  import_completed: Import completed.
         | 
    
        data/config/locales/fr.yml
    CHANGED
    
    | @@ -3,4 +3,14 @@ fr: | |
| 3 3 | 
             
                use_column_as: Utiliser la colonne comme
         | 
| 4 4 | 
             
                ignore: Ignorer
         | 
| 5 5 | 
             
                import: Importer
         | 
| 6 | 
            -
                import_description:  | 
| 6 | 
            +
                import_description: Affichage de %{count} sur %{full_count} exemples d'enregistrements.
         | 
| 7 | 
            +
                errors:
         | 
| 8 | 
            +
                  no_importer: Aucun importateur sélectionné.
         | 
| 9 | 
            +
                  no_file: Aucune fichier téléchargé.
         | 
| 10 | 
            +
                  invalid_file_type: Type de fichier invalide. Les types autorisés sont %{types}.
         | 
| 11 | 
            +
                  no_mappings: Aucune correspondance fournie.
         | 
| 12 | 
            +
                  duplicate_mapping: L'attribut %{attribute} est utilisé plusieurs fois.
         | 
| 13 | 
            +
                  import_failed: Import échoué. %{error}.
         | 
| 14 | 
            +
                  missing_mapping: Correspondance manquante pour l'attribut requis %{attribute}.
         | 
| 15 | 
            +
                success:
         | 
| 16 | 
            +
                  import_completed: Import terminé.
         | 
    
        data/config/locales/it.yml
    CHANGED
    
    | @@ -3,4 +3,14 @@ it: | |
| 3 3 | 
             
                use_column_as: Utilizzare come
         | 
| 4 4 | 
             
                ignore: Ignora
         | 
| 5 5 | 
             
                import: Importare
         | 
| 6 | 
            -
                import_description:  | 
| 6 | 
            +
                import_description: Mostrati %{count} di %{full_count} record di esempio.
         | 
| 7 | 
            +
                errors:
         | 
| 8 | 
            +
                  no_importer: Nessun importatore selezionato.
         | 
| 9 | 
            +
                  no_file: Nessun file caricato.
         | 
| 10 | 
            +
                  invalid_file_type: Tipo di file non valido. I tipi consentiti sono %{types}.
         | 
| 11 | 
            +
                  no_mappings: Nessuna mappatura fornita.
         | 
| 12 | 
            +
                  duplicate_mapping: L'attributo %{attribute} è utilizzato più volte.
         | 
| 13 | 
            +
                  import_failed: Import fallito. %{error}.
         | 
| 14 | 
            +
                  missing_mapping: Mappatura mancante per l'attributo obbligatorio %{attribute}.
         | 
| 15 | 
            +
                success:
         | 
| 16 | 
            +
                  import_completed: Import completato.
         | 
| @@ -29,11 +29,12 @@ module Importance | |
| 29 29 | 
             
                  @teardown_callback = nil
         | 
| 30 30 | 
             
                  @error_callback = nil
         | 
| 31 31 | 
             
                  @batch = false
         | 
| 32 | 
            +
                  @worksheet = nil
         | 
| 32 33 | 
             
                  instance_eval(&block) if block_given?
         | 
| 33 34 | 
             
                end
         | 
| 34 35 |  | 
| 35 | 
            -
                def attribute(key, labels)
         | 
| 36 | 
            -
                  @attributes << OpenStruct.new(key: key, labels: labels)
         | 
| 36 | 
            +
                def attribute(key, labels, options = {})
         | 
| 37 | 
            +
                  @attributes << OpenStruct.new(key: key, labels: labels, options: options)
         | 
| 37 38 | 
             
                end
         | 
| 38 39 |  | 
| 39 40 | 
             
                def batch_size(size)
         | 
| @@ -55,6 +56,49 @@ module Importance | |
| 55 56 | 
             
                def error(&block)
         | 
| 56 57 | 
             
                  @error_callback = block
         | 
| 57 58 | 
             
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def add_spreadsheet(path)
         | 
| 61 | 
            +
                  workbook = Roo::Spreadsheet.open(path, { csv_options: { encoding: "bom|utf-8" } })
         | 
| 62 | 
            +
                  @worksheet = workbook.sheet(0)
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def file_headers
         | 
| 66 | 
            +
                  @worksheet.row(1)
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                def samples
         | 
| 70 | 
            +
                  @worksheet.parse[1..5]
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def full_count
         | 
| 74 | 
            +
                  @worksheet.count - 1
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # Yields each processed row (a hash of attribute => value) to the given block.
         | 
| 78 | 
            +
                # Skips empty rows (all values nil or empty).
         | 
| 79 | 
            +
                def each_processed_row(path, mappings)
         | 
| 80 | 
            +
                  @worksheet.each_with_index do |row, idx|
         | 
| 81 | 
            +
                    next if idx == 0 # Skip header row
         | 
| 82 | 
            +
                    record = process_row(row, mappings)
         | 
| 83 | 
            +
                    next if record.empty? || record.values.all? { |v| v.nil? || v.to_s.strip.empty? }
         | 
| 84 | 
            +
                    yield record
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                # Turn a row of the form ["Hans", "Robert", 1970, "male", "Apple Inc.", "hr@apple.com"]
         | 
| 89 | 
            +
                # and a mapping of the form {"0"=>"first_name", "1"=>"last_name", "2"=>"", "3"=>"", "4"=>"", "5"=>"email"}
         | 
| 90 | 
            +
                # into a record of the form { first_name: "Hans", last_name: "Robert", email: "hr@apple.com" }
         | 
| 91 | 
            +
                def process_row(row, mappings)
         | 
| 92 | 
            +
                  record = {}
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  mappings.each do |column_index, attribute_name|
         | 
| 95 | 
            +
                    next if attribute_name.nil? || attribute_name == ""
         | 
| 96 | 
            +
                    value = row[column_index.to_i]
         | 
| 97 | 
            +
                    record[attribute_name.to_sym] = value
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  record
         | 
| 101 | 
            +
                end
         | 
| 58 102 | 
             
              end
         | 
| 59 103 |  | 
| 60 104 | 
             
              def self.configure
         | 
    
        data/lib/importance/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: importance
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.2. | 
| 4 | 
            +
              version: 0.2.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Lukas_Skywalker
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2025-10- | 
| 11 | 
            +
            date: 2025-10-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         |