brakeman 6.2.2 → 7.0.1
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/CHANGES.md +26 -0
- data/README.md +1 -1
- data/bundle/load.rb +10 -8
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/LICENSE.txt +33 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/NEWS.md +990 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/README.md +55 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/core_ext/array.rb +9 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/core_ext/string.rb +9 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/fields_converter.rb +96 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/input_record_separator.rb +18 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/parser.rb +1302 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/row.rb +757 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/table.rb +1055 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/version.rb +6 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv/writer.rb +209 -0
- data/bundle/ruby/3.1.0/gems/csv-3.3.3/lib/csv.rb +3017 -0
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/Changelog.md +4 -0
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/Gemfile +1 -0
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/list_renderer.rb +2 -2
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/menu.rb +7 -5
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/version.rb +1 -1
- data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline.rb +17 -12
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/config.rb +22 -26
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/history.rb +3 -3
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/ansi.rb +64 -111
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/dumb.rb +16 -2
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/windows.rb +77 -60
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io.rb +14 -0
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/base.rb +10 -4
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/emacs.rb +96 -96
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/vi_command.rb +182 -182
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/vi_insert.rb +137 -137
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_stroke.rb +26 -16
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/line_editor.rb +238 -404
- data/bundle/ruby/3.1.0/gems/reline-0.6.0/lib/reline/unicode.rb +415 -0
- data/bundle/ruby/3.1.0/gems/reline-0.6.0/lib/reline/version.rb +3 -0
- data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline.rb +18 -18
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/NEWS.md +74 -0
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/baseparser.rb +78 -48
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/pullparser.rb +4 -0
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/rexml.rb +1 -1
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/source.rb +61 -6
- data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/text.rb +15 -40
- data/bundle/ruby/3.1.0/gems/{ruby2ruby-2.5.1 → ruby2ruby-2.5.2}/History.rdoc +6 -0
- data/bundle/ruby/3.1.0/gems/{ruby2ruby-2.5.1 → ruby2ruby-2.5.2}/lib/ruby2ruby.rb +7 -4
- data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/History.rdoc +6 -0
- data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp.rb +1 -1
- data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp_processor.rb +1 -1
- data/bundle/ruby/3.1.0/gems/terminal-table-4.0.0/History.rdoc +149 -0
- data/bundle/ruby/3.1.0/gems/terminal-table-4.0.0/README.md +417 -0
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/cell.rb +9 -9
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/row.rb +18 -4
- data/bundle/ruby/3.1.0/gems/terminal-table-4.0.0/lib/terminal-table/separator.rb +66 -0
- data/bundle/ruby/3.1.0/gems/terminal-table-4.0.0/lib/terminal-table/style.rb +284 -0
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/table.rb +49 -18
- data/bundle/ruby/3.1.0/gems/terminal-table-4.0.0/lib/terminal-table/util.rb +13 -0
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/version.rb +1 -1
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table.rb +2 -2
- data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/terminal-table.gemspec +3 -4
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/creole.rb +2 -0
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/liquid.rb +0 -3
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/mapping.rb +3 -3
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/rdoc.rb +0 -8
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/template.rb +178 -27
- data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt.rb +9 -4
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/CHANGELOG.md +291 -0
- data/bundle/ruby/3.1.0/gems/{unicode-display_width-1.8.0 → unicode-display_width-3.1.4}/MIT-LICENSE.txt +1 -1
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/README.md +194 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/data/display_width.marshal.gz +0 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/constants.rb +10 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/emoji_support.rb +52 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/index.rb +34 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/no_string_ext.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/reline_ext.rb +14 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width/string_ext.rb +9 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-3.1.4/lib/unicode/display_width.rb +247 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/CHANGELOG.md +191 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/CODE_OF_CONDUCT.md +74 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/Gemfile +7 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/Gemfile.lock +33 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/MIT-LICENSE.txt +20 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/README.md +205 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/data/emoji.marshal.gz +0 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/data/generate_constants.rb +344 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/constants.rb +49 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_basic.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_emoji_keycap.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_include_mqe.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_include_mqe_uqe.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_picto.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_picto_no_emoji.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_possible.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_prop_component.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_prop_emoji.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_prop_modifier.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_prop_modifier_base.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_prop_presentation.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_text_presentation.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_valid.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_valid_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_well_formed.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated/regex_well_formed_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_basic.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_emoji_keycap.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_include_mqe.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_include_mqe_uqe.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_picto.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_picto_no_emoji.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_possible.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_prop_component.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_prop_emoji.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_prop_modifier.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_prop_modifier_base.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_prop_presentation.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_text_presentation.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_valid.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_valid_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_well_formed.rb +8 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/generated_native/regex_well_formed_include_text.rb +8 -0
- data/bundle/ruby/3.1.0/gems/{unicode-display_width-1.8.0/lib/unicode/display_width → unicode-emoji-4.0.4/lib/unicode/emoji}/index.rb +5 -3
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/lazy_constants.rb +56 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji/list.rb +13 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/lib/unicode/emoji.rb +111 -0
- data/bundle/ruby/3.1.0/gems/unicode-emoji-4.0.4/unicode-emoji.gemspec +22 -0
- data/lib/brakeman/app_tree.rb +29 -19
- data/lib/brakeman/checks/check_deserialize.rb +4 -1
- data/lib/brakeman/checks/check_evaluation.rb +45 -8
- data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -0
- data/lib/brakeman/checks/check_weak_rsa_key.rb +1 -1
- data/lib/brakeman/file_parser.rb +2 -1
- data/lib/brakeman/options.rb +12 -5
- data/lib/brakeman/processors/alias_processor.rb +9 -4
- data/lib/brakeman/processors/lib/file_type_detector.rb +9 -7
- data/lib/brakeman/report/ignore/config.rb +0 -1
- data/lib/brakeman/report/report_sarif.rb +122 -2
- data/lib/brakeman/rescanner.rb +40 -390
- data/lib/brakeman/scanner.rb +84 -51
- data/lib/brakeman/tracker/file_cache.rb +83 -0
- data/lib/brakeman/tracker.rb +19 -2
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman.rb +19 -2
- metadata +265 -199
- data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/terminfo.rb +0 -158
- data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/unicode.rb +0 -671
- data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/version.rb +0 -3
- data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/History.rdoc +0 -85
- data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/README.rdoc +0 -247
- data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/lib/terminal-table/separator.rb +0 -14
- data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/lib/terminal-table/style.rb +0 -79
- data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/erubis.rb +0 -51
- data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/maruku.rb +0 -10
- data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/wikicloth.rb +0 -12
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/CHANGELOG.md +0 -137
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/README.md +0 -124
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/data/display_width.marshal.gz +0 -0
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/constants.rb +0 -8
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/no_string_ext.rb +0 -7
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/string_ext.rb +0 -17
- data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width.rb +0 -51
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/AUTHORS +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/COPYING +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/LICENSE +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/README.md +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/TODO +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/highline.gemspec +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/builtin_styles.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/color_scheme.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/compatibility.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/custom_errors.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/import.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/io_console_compatible.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/list.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/menu/item.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/paginator.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/question/answer_converter.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/question.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/question_asker.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/simulate.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/statement.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/string.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/string_extensions.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/style.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/template_renderer.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/terminal/io_console.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/terminal/ncurses.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/terminal/unix_stty.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/terminal.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{highline-3.1.1 → highline-3.1.2}/lib/highline/wrapper.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/BSDL +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/COPYING +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/README.md +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/face.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/composite.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/kill_ring.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/unicode/east_asian_width.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/license_of_rb-readline +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/LICENSE.txt +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/README.md +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/attlistdecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/attribute.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/cdata.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/child.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/comment.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/doctype.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/document.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/dtd/attlistdecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/dtd/dtd.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/dtd/elementdecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/dtd/entitydecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/dtd/notationdecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/element.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/encoding.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/entity.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/formatters/default.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/formatters/pretty.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/formatters/transitive.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/functions.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/instruction.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/light/node.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/namespace.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/node.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/output.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parent.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parseexception.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/lightparser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/sax2parser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/streamparser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/treeparser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/ultralightparser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/parsers/xpathparser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/quickpath.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/sax2listener.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/security.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/streamlistener.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/undefinednamespaceexception.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/validation/relaxng.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/validation/validation.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/validation/validationexception.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/xmldecl.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/xmltokens.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/xpath.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml/xpath_parser.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.1}/lib/rexml.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{ruby2ruby-2.5.1 → ruby2ruby-2.5.2}/Manifest.txt +0 -0
- /data/bundle/ruby/3.1.0/gems/{ruby2ruby-2.5.1 → ruby2ruby-2.5.2}/README.rdoc +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/Manifest.txt +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/README.rdoc +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/composite_sexp_processor.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/pt_testcase.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp_matcher.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/strict_sexp.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/unique.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/Gemfile +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/LICENSE.txt +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/Manifest +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/Todo.rdoc +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/import.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-4.0.0}/lib/terminal-table/table_helper.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/COPYING +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/_emacs_org.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/_handlebars.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/_jbuilder.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/_org.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/asciidoc.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/babel.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/builder.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/cli.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/coffee.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/commonmarker.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/csv.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/erb.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/erubi.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/etanni.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/haml.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/kramdown.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/livescript.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/markaby.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/nokogiri.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/pandoc.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/pipeline.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/plain.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/prawn.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/radius.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/rdiscount.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/redcarpet.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/redcloth.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/rst-pandoc.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/sass.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/slim.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/string.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/typescript.rb +0 -0
- /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.6.0}/lib/tilt/yajl.rb +0 -0
@@ -0,0 +1,757 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
class CSV
|
6
|
+
# = \CSV::Row
|
7
|
+
# A \CSV::Row instance represents a \CSV table row.
|
8
|
+
# (see {class CSV}[../CSV.html]).
|
9
|
+
#
|
10
|
+
# The instance may have:
|
11
|
+
# - Fields: each is an object, not necessarily a \String.
|
12
|
+
# - Headers: each serves a key, and also need not be a \String.
|
13
|
+
#
|
14
|
+
# === Instance Methods
|
15
|
+
#
|
16
|
+
# \CSV::Row has three groups of instance methods:
|
17
|
+
# - Its own internally defined instance methods.
|
18
|
+
# - Methods included by module Enumerable.
|
19
|
+
# - Methods delegated to class Array.:
|
20
|
+
# * Array#empty?
|
21
|
+
# * Array#length
|
22
|
+
# * Array#size
|
23
|
+
#
|
24
|
+
# == Creating a \CSV::Row Instance
|
25
|
+
#
|
26
|
+
# Commonly, a new \CSV::Row instance is created by parsing \CSV source
|
27
|
+
# that has headers:
|
28
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
29
|
+
# table = CSV.parse(source, headers: true)
|
30
|
+
# table.each {|row| p row }
|
31
|
+
# Output:
|
32
|
+
# #<CSV::Row "Name":"foo" "Value":"0">
|
33
|
+
# #<CSV::Row "Name":"bar" "Value":"1">
|
34
|
+
# #<CSV::Row "Name":"baz" "Value":"2">
|
35
|
+
#
|
36
|
+
# You can also create a row directly. See ::new.
|
37
|
+
#
|
38
|
+
# == Headers
|
39
|
+
#
|
40
|
+
# Like a \CSV::Table, a \CSV::Row has headers.
|
41
|
+
#
|
42
|
+
# A \CSV::Row that was created by parsing \CSV source
|
43
|
+
# inherits its headers from the table:
|
44
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
45
|
+
# table = CSV.parse(source, headers: true)
|
46
|
+
# row = table.first
|
47
|
+
# row.headers # => ["Name", "Value"]
|
48
|
+
#
|
49
|
+
# You can also create a new row with headers;
|
50
|
+
# like the keys in a \Hash, the headers need not be Strings:
|
51
|
+
# row = CSV::Row.new([:name, :value], ['foo', 0])
|
52
|
+
# row.headers # => [:name, :value]
|
53
|
+
#
|
54
|
+
# The new row retains its headers even if added to a table
|
55
|
+
# that has headers:
|
56
|
+
# table << row # => #<CSV::Table mode:col_or_row row_count:5>
|
57
|
+
# row.headers # => [:name, :value]
|
58
|
+
# row[:name] # => "foo"
|
59
|
+
# row['Name'] # => nil
|
60
|
+
#
|
61
|
+
#
|
62
|
+
#
|
63
|
+
# == Accessing Fields
|
64
|
+
#
|
65
|
+
# You may access a field in a \CSV::Row with either its \Integer index
|
66
|
+
# (\Array-style) or its header (\Hash-style).
|
67
|
+
#
|
68
|
+
# Fetch a field using method #[]:
|
69
|
+
# row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
|
70
|
+
# row[1] # => 0
|
71
|
+
# row['Value'] # => 0
|
72
|
+
#
|
73
|
+
# Set a field using method #[]=:
|
74
|
+
# row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
|
75
|
+
# row # => #<CSV::Row "Name":"foo" "Value":0>
|
76
|
+
# row[0] = 'bar'
|
77
|
+
# row['Value'] = 1
|
78
|
+
# row # => #<CSV::Row "Name":"bar" "Value":1>
|
79
|
+
#
|
80
|
+
class Row
|
81
|
+
# :call-seq:
|
82
|
+
# CSV::Row.new(headers, fields, header_row = false) -> csv_row
|
83
|
+
#
|
84
|
+
# Returns the new \CSV::Row instance constructed from
|
85
|
+
# arguments +headers+ and +fields+; both should be Arrays;
|
86
|
+
# note that the fields need not be Strings:
|
87
|
+
# row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
|
88
|
+
# row # => #<CSV::Row "Name":"foo" "Value":0>
|
89
|
+
#
|
90
|
+
# If the \Array lengths are different, the shorter is +nil+-filled:
|
91
|
+
# row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0])
|
92
|
+
# row # => #<CSV::Row "Name":"foo" "Value":0 "Date":nil "Size":nil>
|
93
|
+
#
|
94
|
+
# Each \CSV::Row object is either a <i>field row</i> or a <i>header row</i>;
|
95
|
+
# by default, a new row is a field row; for the row created above:
|
96
|
+
# row.field_row? # => true
|
97
|
+
# row.header_row? # => false
|
98
|
+
#
|
99
|
+
# If the optional argument +header_row+ is given as +true+,
|
100
|
+
# the created row is a header row:
|
101
|
+
# row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true)
|
102
|
+
# row # => #<CSV::Row "Name":"foo" "Value":0>
|
103
|
+
# row.field_row? # => false
|
104
|
+
# row.header_row? # => true
|
105
|
+
def initialize(headers, fields, header_row = false)
|
106
|
+
@header_row = header_row
|
107
|
+
headers.each { |h| h.freeze if h.is_a? String }
|
108
|
+
|
109
|
+
# handle extra headers or fields
|
110
|
+
@row = if headers.size >= fields.size
|
111
|
+
headers.zip(fields)
|
112
|
+
else
|
113
|
+
fields.zip(headers).each(&:reverse!)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Internal data format used to compare equality.
|
118
|
+
attr_reader :row
|
119
|
+
protected :row
|
120
|
+
|
121
|
+
### Array Delegation ###
|
122
|
+
|
123
|
+
extend Forwardable
|
124
|
+
def_delegators :@row, :empty?, :length, :size
|
125
|
+
|
126
|
+
# :call-seq:
|
127
|
+
# row.initialize_copy(other_row) -> self
|
128
|
+
#
|
129
|
+
# Calls superclass method.
|
130
|
+
def initialize_copy(other)
|
131
|
+
super_return_value = super
|
132
|
+
@row = @row.collect(&:dup)
|
133
|
+
super_return_value
|
134
|
+
end
|
135
|
+
|
136
|
+
# :call-seq:
|
137
|
+
# row.header_row? -> true or false
|
138
|
+
#
|
139
|
+
# Returns +true+ if this is a header row, +false+ otherwise.
|
140
|
+
def header_row?
|
141
|
+
@header_row
|
142
|
+
end
|
143
|
+
|
144
|
+
# :call-seq:
|
145
|
+
# row.field_row? -> true or false
|
146
|
+
#
|
147
|
+
# Returns +true+ if this is a field row, +false+ otherwise.
|
148
|
+
def field_row?
|
149
|
+
not header_row?
|
150
|
+
end
|
151
|
+
|
152
|
+
# :call-seq:
|
153
|
+
# row.headers -> array_of_headers
|
154
|
+
#
|
155
|
+
# Returns the headers for this row:
|
156
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
157
|
+
# table = CSV.parse(source, headers: true)
|
158
|
+
# row = table.first
|
159
|
+
# row.headers # => ["Name", "Value"]
|
160
|
+
def headers
|
161
|
+
@row.map(&:first)
|
162
|
+
end
|
163
|
+
|
164
|
+
# :call-seq:
|
165
|
+
# field(index) -> value
|
166
|
+
# field(header) -> value
|
167
|
+
# field(header, offset) -> value
|
168
|
+
#
|
169
|
+
# Returns the field value for the given +index+ or +header+.
|
170
|
+
#
|
171
|
+
# ---
|
172
|
+
#
|
173
|
+
# Fetch field value by \Integer index:
|
174
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
175
|
+
# table = CSV.parse(source, headers: true)
|
176
|
+
# row = table[0]
|
177
|
+
# row.field(0) # => "foo"
|
178
|
+
# row.field(1) # => "bar"
|
179
|
+
#
|
180
|
+
# Counts backward from the last column if +index+ is negative:
|
181
|
+
# row.field(-1) # => "0"
|
182
|
+
# row.field(-2) # => "foo"
|
183
|
+
#
|
184
|
+
# Returns +nil+ if +index+ is out of range:
|
185
|
+
# row.field(2) # => nil
|
186
|
+
# row.field(-3) # => nil
|
187
|
+
#
|
188
|
+
# ---
|
189
|
+
#
|
190
|
+
# Fetch field value by header (first found):
|
191
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
192
|
+
# table = CSV.parse(source, headers: true)
|
193
|
+
# row = table[0]
|
194
|
+
# row.field('Name') # => "Foo"
|
195
|
+
#
|
196
|
+
# Fetch field value by header, ignoring +offset+ leading fields:
|
197
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
198
|
+
# table = CSV.parse(source, headers: true)
|
199
|
+
# row = table[0]
|
200
|
+
# row.field('Name', 2) # => "Baz"
|
201
|
+
#
|
202
|
+
# Returns +nil+ if the header does not exist.
|
203
|
+
def field(header_or_index, minimum_index = 0)
|
204
|
+
# locate the pair
|
205
|
+
finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc
|
206
|
+
pair = @row[minimum_index..-1].public_send(finder, header_or_index)
|
207
|
+
|
208
|
+
# return the field if we have a pair
|
209
|
+
if pair.nil?
|
210
|
+
nil
|
211
|
+
else
|
212
|
+
header_or_index.is_a?(Range) ? pair.map(&:last) : pair.last
|
213
|
+
end
|
214
|
+
end
|
215
|
+
alias_method :[], :field
|
216
|
+
|
217
|
+
#
|
218
|
+
# :call-seq:
|
219
|
+
# fetch(header) -> value
|
220
|
+
# fetch(header, default) -> value
|
221
|
+
# fetch(header) {|row| ... } -> value
|
222
|
+
#
|
223
|
+
# Returns the field value as specified by +header+.
|
224
|
+
#
|
225
|
+
# ---
|
226
|
+
#
|
227
|
+
# With the single argument +header+, returns the field value
|
228
|
+
# for that header (first found):
|
229
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
230
|
+
# table = CSV.parse(source, headers: true)
|
231
|
+
# row = table[0]
|
232
|
+
# row.fetch('Name') # => "Foo"
|
233
|
+
#
|
234
|
+
# Raises exception +KeyError+ if the header does not exist.
|
235
|
+
#
|
236
|
+
# ---
|
237
|
+
#
|
238
|
+
# With arguments +header+ and +default+ given,
|
239
|
+
# returns the field value for the header (first found)
|
240
|
+
# if the header exists, otherwise returns +default+:
|
241
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
242
|
+
# table = CSV.parse(source, headers: true)
|
243
|
+
# row = table[0]
|
244
|
+
# row.fetch('Name', '') # => "Foo"
|
245
|
+
# row.fetch(:nosuch, '') # => ""
|
246
|
+
#
|
247
|
+
# ---
|
248
|
+
#
|
249
|
+
# With argument +header+ and a block given,
|
250
|
+
# returns the field value for the header (first found)
|
251
|
+
# if the header exists; otherwise calls the block
|
252
|
+
# and returns its return value:
|
253
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
254
|
+
# table = CSV.parse(source, headers: true)
|
255
|
+
# row = table[0]
|
256
|
+
# row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo"
|
257
|
+
# row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
|
258
|
+
def fetch(header, *varargs)
|
259
|
+
raise ArgumentError, "Too many arguments" if varargs.length > 1
|
260
|
+
pair = @row.assoc(header)
|
261
|
+
if pair
|
262
|
+
pair.last
|
263
|
+
else
|
264
|
+
if block_given?
|
265
|
+
yield header
|
266
|
+
elsif varargs.empty?
|
267
|
+
raise KeyError, "key not found: #{header}"
|
268
|
+
else
|
269
|
+
varargs.first
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# :call-seq:
|
275
|
+
# row.has_key?(header) -> true or false
|
276
|
+
#
|
277
|
+
# Returns +true+ if there is a field with the given +header+,
|
278
|
+
# +false+ otherwise.
|
279
|
+
def has_key?(header)
|
280
|
+
!!@row.assoc(header)
|
281
|
+
end
|
282
|
+
alias_method :include?, :has_key?
|
283
|
+
alias_method :key?, :has_key?
|
284
|
+
alias_method :member?, :has_key?
|
285
|
+
alias_method :header?, :has_key?
|
286
|
+
|
287
|
+
#
|
288
|
+
# :call-seq:
|
289
|
+
# row[index] = value -> value
|
290
|
+
# row[header, offset] = value -> value
|
291
|
+
# row[header] = value -> value
|
292
|
+
#
|
293
|
+
# Assigns the field value for the given +index+ or +header+;
|
294
|
+
# returns +value+.
|
295
|
+
#
|
296
|
+
# ---
|
297
|
+
#
|
298
|
+
# Assign field value by \Integer index:
|
299
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
300
|
+
# table = CSV.parse(source, headers: true)
|
301
|
+
# row = table[0]
|
302
|
+
# row[0] = 'Bat'
|
303
|
+
# row[1] = 3
|
304
|
+
# row # => #<CSV::Row "Name":"Bat" "Value":3>
|
305
|
+
#
|
306
|
+
# Counts backward from the last column if +index+ is negative:
|
307
|
+
# row[-1] = 4
|
308
|
+
# row[-2] = 'Bam'
|
309
|
+
# row # => #<CSV::Row "Name":"Bam" "Value":4>
|
310
|
+
#
|
311
|
+
# Extends the row with <tt>nil:nil</tt> if positive +index+ is not in the row:
|
312
|
+
# row[4] = 5
|
313
|
+
# row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
|
314
|
+
#
|
315
|
+
# Raises IndexError if negative +index+ is too small (too far from zero).
|
316
|
+
#
|
317
|
+
# ---
|
318
|
+
#
|
319
|
+
# Assign field value by header (first found):
|
320
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
321
|
+
# table = CSV.parse(source, headers: true)
|
322
|
+
# row = table[0]
|
323
|
+
# row['Name'] = 'Bat'
|
324
|
+
# row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
|
325
|
+
#
|
326
|
+
# Assign field value by header, ignoring +offset+ leading fields:
|
327
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
328
|
+
# table = CSV.parse(source, headers: true)
|
329
|
+
# row = table[0]
|
330
|
+
# row['Name', 2] = 4
|
331
|
+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
|
332
|
+
#
|
333
|
+
# Append new field by (new) header:
|
334
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
335
|
+
# table = CSV.parse(source, headers: true)
|
336
|
+
# row = table[0]
|
337
|
+
# row['New'] = 6
|
338
|
+
# row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
|
339
|
+
def []=(*args)
|
340
|
+
value = args.pop
|
341
|
+
|
342
|
+
if args.first.is_a? Integer
|
343
|
+
if @row[args.first].nil? # extending past the end with index
|
344
|
+
@row[args.first] = [nil, value]
|
345
|
+
@row.map! { |pair| pair.nil? ? [nil, nil] : pair }
|
346
|
+
else # normal index assignment
|
347
|
+
@row[args.first][1] = value
|
348
|
+
end
|
349
|
+
else
|
350
|
+
index = index(*args)
|
351
|
+
if index.nil? # appending a field
|
352
|
+
self << [args.first, value]
|
353
|
+
else # normal header assignment
|
354
|
+
@row[index][1] = value
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
#
|
360
|
+
# :call-seq:
|
361
|
+
# row << [header, value] -> self
|
362
|
+
# row << hash -> self
|
363
|
+
# row << value -> self
|
364
|
+
#
|
365
|
+
# Adds a field to +self+; returns +self+:
|
366
|
+
#
|
367
|
+
# If the argument is a 2-element \Array <tt>[header, value]</tt>,
|
368
|
+
# a field is added with the given +header+ and +value+:
|
369
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
370
|
+
# table = CSV.parse(source, headers: true)
|
371
|
+
# row = table[0]
|
372
|
+
# row << ['NAME', 'Bat']
|
373
|
+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
|
374
|
+
#
|
375
|
+
# If the argument is a \Hash, each <tt>key-value</tt> pair is added
|
376
|
+
# as a field with header +key+ and value +value+.
|
377
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
378
|
+
# table = CSV.parse(source, headers: true)
|
379
|
+
# row = table[0]
|
380
|
+
# row << {NAME: 'Bat', name: 'Bam'}
|
381
|
+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
|
382
|
+
#
|
383
|
+
# Otherwise, the given +value+ is added as a field with no header.
|
384
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
385
|
+
# table = CSV.parse(source, headers: true)
|
386
|
+
# row = table[0]
|
387
|
+
# row << 'Bag'
|
388
|
+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
|
389
|
+
def <<(arg)
|
390
|
+
if arg.is_a?(Array) and arg.size == 2 # appending a header and name
|
391
|
+
@row << arg
|
392
|
+
elsif arg.is_a?(Hash) # append header and name pairs
|
393
|
+
arg.each { |pair| @row << pair }
|
394
|
+
else # append field value
|
395
|
+
@row << [nil, arg]
|
396
|
+
end
|
397
|
+
|
398
|
+
self # for chaining
|
399
|
+
end
|
400
|
+
|
401
|
+
# :call-seq:
|
402
|
+
# row.push(*values) -> self
|
403
|
+
#
|
404
|
+
# Appends each of the given +values+ to +self+ as a field; returns +self+:
|
405
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
406
|
+
# table = CSV.parse(source, headers: true)
|
407
|
+
# row = table[0]
|
408
|
+
# row.push('Bat', 'Bam')
|
409
|
+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
|
410
|
+
def push(*args)
|
411
|
+
args.each { |arg| self << arg }
|
412
|
+
|
413
|
+
self # for chaining
|
414
|
+
end
|
415
|
+
|
416
|
+
#
|
417
|
+
# :call-seq:
|
418
|
+
# delete(index) -> [header, value] or nil
|
419
|
+
# delete(header) -> [header, value] or empty_array
|
420
|
+
# delete(header, offset) -> [header, value] or empty_array
|
421
|
+
#
|
422
|
+
# Removes a specified field from +self+; returns the 2-element \Array
|
423
|
+
# <tt>[header, value]</tt> if the field exists.
|
424
|
+
#
|
425
|
+
# If an \Integer argument +index+ is given,
|
426
|
+
# removes and returns the field at offset +index+,
|
427
|
+
# or returns +nil+ if the field does not exist:
|
428
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
429
|
+
# table = CSV.parse(source, headers: true)
|
430
|
+
# row = table[0]
|
431
|
+
# row.delete(1) # => ["Name", "Bar"]
|
432
|
+
# row.delete(50) # => nil
|
433
|
+
#
|
434
|
+
# Otherwise, if the single argument +header+ is given,
|
435
|
+
# removes and returns the first-found field with the given header,
|
436
|
+
# of returns a new empty \Array if the field does not exist:
|
437
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
438
|
+
# table = CSV.parse(source, headers: true)
|
439
|
+
# row = table[0]
|
440
|
+
# row.delete('Name') # => ["Name", "Foo"]
|
441
|
+
# row.delete('NAME') # => []
|
442
|
+
#
|
443
|
+
# If argument +header+ and \Integer argument +offset+ are given,
|
444
|
+
# removes and returns the first-found field with the given header
|
445
|
+
# whose +index+ is at least as large as +offset+:
|
446
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
447
|
+
# table = CSV.parse(source, headers: true)
|
448
|
+
# row = table[0]
|
449
|
+
# row.delete('Name', 1) # => ["Name", "Bar"]
|
450
|
+
# row.delete('NAME', 1) # => []
|
451
|
+
def delete(header_or_index, minimum_index = 0)
|
452
|
+
if header_or_index.is_a? Integer # by index
|
453
|
+
@row.delete_at(header_or_index)
|
454
|
+
elsif i = index(header_or_index, minimum_index) # by header
|
455
|
+
@row.delete_at(i)
|
456
|
+
else
|
457
|
+
[ ]
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
# :call-seq:
|
462
|
+
# row.delete_if {|header, value| ... } -> self
|
463
|
+
#
|
464
|
+
# Removes fields from +self+ as selected by the block; returns +self+.
|
465
|
+
#
|
466
|
+
# Removes each field for which the block returns a truthy value:
|
467
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
468
|
+
# table = CSV.parse(source, headers: true)
|
469
|
+
# row = table[0]
|
470
|
+
# row.delete_if {|header, value| value.start_with?('B') } # => true
|
471
|
+
# row # => #<CSV::Row "Name":"Foo">
|
472
|
+
# row.delete_if {|header, value| header.start_with?('B') } # => false
|
473
|
+
#
|
474
|
+
# If no block is given, returns a new Enumerator:
|
475
|
+
# row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
|
476
|
+
def delete_if(&block)
|
477
|
+
return enum_for(__method__) { size } unless block_given?
|
478
|
+
|
479
|
+
@row.delete_if(&block)
|
480
|
+
|
481
|
+
self # for chaining
|
482
|
+
end
|
483
|
+
|
484
|
+
# :call-seq:
|
485
|
+
# self.fields(*specifiers) -> array_of_fields
|
486
|
+
#
|
487
|
+
# Returns field values per the given +specifiers+, which may be any mixture of:
|
488
|
+
# - \Integer index.
|
489
|
+
# - \Range of \Integer indexes.
|
490
|
+
# - 2-element \Array containing a header and offset.
|
491
|
+
# - Header.
|
492
|
+
# - \Range of headers.
|
493
|
+
#
|
494
|
+
# For +specifier+ in one of the first four cases above,
|
495
|
+
# returns the result of <tt>self.field(specifier)</tt>; see #field.
|
496
|
+
#
|
497
|
+
# Although there may be any number of +specifiers+,
|
498
|
+
# the examples here will illustrate one at a time.
|
499
|
+
#
|
500
|
+
# When the specifier is an \Integer +index+,
|
501
|
+
# returns <tt>self.field(index)</tt>L
|
502
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
503
|
+
# table = CSV.parse(source, headers: true)
|
504
|
+
# row = table[0]
|
505
|
+
# row.fields(1) # => ["Bar"]
|
506
|
+
#
|
507
|
+
# When the specifier is a \Range of \Integers +range+,
|
508
|
+
# returns <tt>self.field(range)</tt>:
|
509
|
+
# row.fields(1..2) # => ["Bar", "Baz"]
|
510
|
+
#
|
511
|
+
# When the specifier is a 2-element \Array +array+,
|
512
|
+
# returns <tt>self.field(array)</tt>L
|
513
|
+
# row.fields('Name', 1) # => ["Foo", "Bar"]
|
514
|
+
#
|
515
|
+
# When the specifier is a header +header+,
|
516
|
+
# returns <tt>self.field(header)</tt>L
|
517
|
+
# row.fields('Name') # => ["Foo"]
|
518
|
+
#
|
519
|
+
# When the specifier is a \Range of headers +range+,
|
520
|
+
# forms a new \Range +new_range+ from the indexes of
|
521
|
+
# <tt>range.start</tt> and <tt>range.end</tt>,
|
522
|
+
# and returns <tt>self.field(new_range)</tt>:
|
523
|
+
# source = "Name,NAME,name\nFoo,Bar,Baz\n"
|
524
|
+
# table = CSV.parse(source, headers: true)
|
525
|
+
# row = table[0]
|
526
|
+
# row.fields('Name'..'NAME') # => ["Foo", "Bar"]
|
527
|
+
#
|
528
|
+
# Returns all fields if no argument given:
|
529
|
+
# row.fields # => ["Foo", "Bar", "Baz"]
|
530
|
+
def fields(*headers_and_or_indices)
|
531
|
+
if headers_and_or_indices.empty? # return all fields--no arguments
|
532
|
+
@row.map(&:last)
|
533
|
+
else # or work like values_at()
|
534
|
+
all = []
|
535
|
+
headers_and_or_indices.each do |h_or_i|
|
536
|
+
if h_or_i.is_a? Range
|
537
|
+
index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin :
|
538
|
+
index(h_or_i.begin)
|
539
|
+
index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end :
|
540
|
+
index(h_or_i.end)
|
541
|
+
new_range = h_or_i.exclude_end? ? (index_begin...index_end) :
|
542
|
+
(index_begin..index_end)
|
543
|
+
all.concat(fields.values_at(new_range))
|
544
|
+
else
|
545
|
+
all << field(*Array(h_or_i))
|
546
|
+
end
|
547
|
+
end
|
548
|
+
return all
|
549
|
+
end
|
550
|
+
end
|
551
|
+
alias_method :values_at, :fields
|
552
|
+
|
553
|
+
# :call-seq:
|
554
|
+
# index(header) -> index
|
555
|
+
# index(header, offset) -> index
|
556
|
+
#
|
557
|
+
# Returns the index for the given header, if it exists;
|
558
|
+
# otherwise returns +nil+.
|
559
|
+
#
|
560
|
+
# With the single argument +header+, returns the index
|
561
|
+
# of the first-found field with the given +header+:
|
562
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
563
|
+
# table = CSV.parse(source, headers: true)
|
564
|
+
# row = table[0]
|
565
|
+
# row.index('Name') # => 0
|
566
|
+
# row.index('NAME') # => nil
|
567
|
+
#
|
568
|
+
# With arguments +header+ and +offset+,
|
569
|
+
# returns the index of the first-found field with given +header+,
|
570
|
+
# but ignoring the first +offset+ fields:
|
571
|
+
# row.index('Name', 1) # => 1
|
572
|
+
# row.index('Name', 3) # => nil
|
573
|
+
def index(header, minimum_index = 0)
|
574
|
+
# find the pair
|
575
|
+
index = headers[minimum_index..-1].index(header)
|
576
|
+
# return the index at the right offset, if we found one
|
577
|
+
index.nil? ? nil : index + minimum_index
|
578
|
+
end
|
579
|
+
|
580
|
+
# :call-seq:
|
581
|
+
# row.field?(value) -> true or false
|
582
|
+
#
|
583
|
+
# Returns +true+ if +value+ is a field in this row, +false+ otherwise:
|
584
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
585
|
+
# table = CSV.parse(source, headers: true)
|
586
|
+
# row = table[0]
|
587
|
+
# row.field?('Bar') # => true
|
588
|
+
# row.field?('BAR') # => false
|
589
|
+
def field?(data)
|
590
|
+
fields.include? data
|
591
|
+
end
|
592
|
+
|
593
|
+
include Enumerable
|
594
|
+
|
595
|
+
# :call-seq:
|
596
|
+
# row.each {|header, value| ... } -> self
|
597
|
+
#
|
598
|
+
# Calls the block with each header-value pair; returns +self+:
|
599
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
600
|
+
# table = CSV.parse(source, headers: true)
|
601
|
+
# row = table[0]
|
602
|
+
# row.each {|header, value| p [header, value] }
|
603
|
+
# Output:
|
604
|
+
# ["Name", "Foo"]
|
605
|
+
# ["Name", "Bar"]
|
606
|
+
# ["Name", "Baz"]
|
607
|
+
#
|
608
|
+
# If no block is given, returns a new Enumerator:
|
609
|
+
# row.each # => #<Enumerator: #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz">:each>
|
610
|
+
def each(&block)
|
611
|
+
return enum_for(__method__) { size } unless block_given?
|
612
|
+
|
613
|
+
@row.each(&block)
|
614
|
+
|
615
|
+
self # for chaining
|
616
|
+
end
|
617
|
+
|
618
|
+
alias_method :each_pair, :each
|
619
|
+
|
620
|
+
# :call-seq:
|
621
|
+
# row == other -> true or false
|
622
|
+
#
|
623
|
+
# Returns +true+ if +other+ is a /CSV::Row that has the same
|
624
|
+
# fields (headers and values) in the same order as +self+;
|
625
|
+
# otherwise returns +false+:
|
626
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
627
|
+
# table = CSV.parse(source, headers: true)
|
628
|
+
# row = table[0]
|
629
|
+
# other_row = table[0]
|
630
|
+
# row == other_row # => true
|
631
|
+
# other_row = table[1]
|
632
|
+
# row == other_row # => false
|
633
|
+
def ==(other)
|
634
|
+
return @row == other.row if other.is_a? CSV::Row
|
635
|
+
@row == other
|
636
|
+
end
|
637
|
+
|
638
|
+
# :call-seq:
|
639
|
+
# row.to_h -> hash
|
640
|
+
#
|
641
|
+
# Returns the new \Hash formed by adding each header-value pair in +self+
|
642
|
+
# as a key-value pair in the \Hash.
|
643
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
644
|
+
# table = CSV.parse(source, headers: true)
|
645
|
+
# row = table[0]
|
646
|
+
# row.to_h # => {"Name"=>"foo", "Value"=>"0"}
|
647
|
+
#
|
648
|
+
# Header order is preserved, but repeated headers are ignored:
|
649
|
+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
|
650
|
+
# table = CSV.parse(source, headers: true)
|
651
|
+
# row = table[0]
|
652
|
+
# row.to_h # => {"Name"=>"Foo"}
|
653
|
+
def to_h
|
654
|
+
hash = {}
|
655
|
+
each do |key, _value|
|
656
|
+
hash[key] = self[key] unless hash.key?(key)
|
657
|
+
end
|
658
|
+
hash
|
659
|
+
end
|
660
|
+
alias_method :to_hash, :to_h
|
661
|
+
|
662
|
+
# :call-seq:
|
663
|
+
# row.deconstruct_keys(keys) -> hash
|
664
|
+
#
|
665
|
+
# Returns the new \Hash suitable for pattern matching containing only the
|
666
|
+
# keys specified as an argument.
|
667
|
+
def deconstruct_keys(keys)
|
668
|
+
if keys.nil?
|
669
|
+
to_h
|
670
|
+
else
|
671
|
+
keys.to_h { |key| [key, self[key]] }
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
alias_method :to_ary, :to_a
|
676
|
+
|
677
|
+
# :call-seq:
|
678
|
+
# row.deconstruct -> array
|
679
|
+
#
|
680
|
+
# Returns the new \Array suitable for pattern matching containing the values
|
681
|
+
# of the row.
|
682
|
+
def deconstruct
|
683
|
+
fields
|
684
|
+
end
|
685
|
+
|
686
|
+
# :call-seq:
|
687
|
+
# row.to_csv -> csv_string
|
688
|
+
#
|
689
|
+
# Returns the row as a \CSV String. Headers are not included:
|
690
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
691
|
+
# table = CSV.parse(source, headers: true)
|
692
|
+
# row = table[0]
|
693
|
+
# row.to_csv # => "foo,0\n"
|
694
|
+
def to_csv(**options)
|
695
|
+
fields.to_csv(**options)
|
696
|
+
end
|
697
|
+
alias_method :to_s, :to_csv
|
698
|
+
|
699
|
+
# :call-seq:
|
700
|
+
# row.dig(index_or_header, *identifiers) -> object
|
701
|
+
#
|
702
|
+
# Finds and returns the object in nested object that is specified
|
703
|
+
# by +index_or_header+ and +specifiers+.
|
704
|
+
#
|
705
|
+
# The nested objects may be instances of various classes.
|
706
|
+
# See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
|
707
|
+
#
|
708
|
+
# Examples:
|
709
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
710
|
+
# table = CSV.parse(source, headers: true)
|
711
|
+
# row = table[0]
|
712
|
+
# row.dig(1) # => "0"
|
713
|
+
# row.dig('Value') # => "0"
|
714
|
+
# row.dig(5) # => nil
|
715
|
+
def dig(index_or_header, *indexes)
|
716
|
+
value = field(index_or_header)
|
717
|
+
if value.nil?
|
718
|
+
nil
|
719
|
+
elsif indexes.empty?
|
720
|
+
value
|
721
|
+
else
|
722
|
+
unless value.respond_to?(:dig)
|
723
|
+
raise TypeError, "#{value.class} does not have \#dig method"
|
724
|
+
end
|
725
|
+
value.dig(*indexes)
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
# :call-seq:
|
730
|
+
# row.inspect -> string
|
731
|
+
#
|
732
|
+
# Returns an ASCII-compatible \String showing:
|
733
|
+
# - Class \CSV::Row.
|
734
|
+
# - Header-value pairs.
|
735
|
+
# Example:
|
736
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
737
|
+
# table = CSV.parse(source, headers: true)
|
738
|
+
# row = table[0]
|
739
|
+
# row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
|
740
|
+
def inspect
|
741
|
+
str = ["#<", self.class.to_s]
|
742
|
+
each do |header, field|
|
743
|
+
str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) <<
|
744
|
+
":" << field.inspect
|
745
|
+
end
|
746
|
+
str << ">"
|
747
|
+
begin
|
748
|
+
str.join('')
|
749
|
+
rescue # any encoding error
|
750
|
+
str.map do |s|
|
751
|
+
e = Encoding::Converter.asciicompat_encoding(s.encoding)
|
752
|
+
e ? s.encode(e) : s.force_encoding("ASCII-8BIT")
|
753
|
+
end.join('')
|
754
|
+
end
|
755
|
+
end
|
756
|
+
end
|
757
|
+
end
|