From ee78b326223967e2bd8af4d0db9c0e668a6cff02 Mon Sep 17 00:00:00 2001 From: Jeanine Soterwood Date: Fri, 12 May 2023 13:43:46 -0700 Subject: [PATCH] Add option that allows stripping of whitespace for all values (#19) --- README.md | 18 +++++++++++++++++- lib/art_vandelay.rb | 15 ++++++++++++--- test/art_vandelay_test.rb | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a43dfbe..083ff8b 100644 --- a/README.md +++ b/README.md @@ -140,13 +140,14 @@ ArtVandelay::Import.new(model_name, **options) |Argument|Description| |--------|-----------| |`model_name`|The name of the model being imported. E.g. `:users`, `:user`, `"users"` or `"user"`| -|`**options`|A hash of options. Available options are `rollback:`| +|`**options`|A hash of options. Available options are `rollback:`, `strip:`| #### Options |Option|Description| |------|-----------| |`rollback:`|Whether the import should rollback if any of the records fails to save.| +|`strip:`|Strips leading and trailing whitespace from all values, including headers.| #### ArtVandelay::Import#csv @@ -221,6 +222,21 @@ result = ArtVandelay::Import.new(:users).csv(csv_string, attributes: {email_addr # => # ``` +##### Stripping whitespace + +```ruby +csv_string = CSV.generate do |csv| + csv << ["email_address ", " passcode "] + csv << [" george@vandelay_industries.com ", " bosco "] +end + +result = ArtVandelay::Import.new(:users, strip: true).csv(csv_string, attributes: {email_address: :email, passcode: :password}) +# => # + +result.rows_accepted +# => [{:row=>["george@vandelay_industries.com", "bosco"], :id=>1}] +``` + ## 🙏 Contributing 1. Run `./bin/setup`. diff --git a/lib/art_vandelay.rb b/lib/art_vandelay.rb index 1f01501..9241838 100644 --- a/lib/art_vandelay.rb +++ b/lib/art_vandelay.rb @@ -142,6 +142,7 @@ def initialize(rows_accepted:, rows_rejected:) def initialize(model_name, **options) @options = options.symbolize_keys @rollback = options[:rollback] + @strip = options[:strip] @model_name = model_name end @@ -164,7 +165,7 @@ def csv(csv_string, **options) private - attr_reader :model_name, :rollback + attr_reader :model_name, :rollback, :strip def active_record model_name.to_s.classify.constantize @@ -177,8 +178,16 @@ def build_csv(csv_string, headers) def build_params(row, attributes) attributes = attributes.stringify_keys - row.to_h.stringify_keys.transform_keys do |key| - attributes[key] || key + if strip + row.to_h.stringify_keys.transform_keys do |key| + attributes[key.strip] || key.strip + end.tap do |new_params| + new_params.transform_values!(&:strip) + end + else + row.to_h.stringify_keys.transform_keys do |key| + attributes[key] || key + end end end diff --git a/test/art_vandelay_test.rb b/test/art_vandelay_test.rb index 4b586cf..c4cf30b 100644 --- a/test/art_vandelay_test.rb +++ b/test/art_vandelay_test.rb @@ -336,6 +336,26 @@ class Import < ArtVandelayTest assert_equal "s3kure!", user_2.password end + test "it strips whitespace when strip configuration is passed" do + csv_string = CSV.generate do |csv| + csv << [" email ", " password "] + csv << [" email_1@example.com ", " s3krit "] + csv << [" email_2@example.com ", " s3kure! "] + end + + assert_difference("User.count", 2) do + ArtVandelay::Import.new(:users, strip: true).csv(csv_string) + end + + user_1 = User.find_by!(email: "email_1@example.com") + user_2 = User.find_by!(email: "email_2@example.com") + + assert_equal "email_1@example.com", user_1.email + assert_equal "s3krit", user_1.password + assert_equal "email_2@example.com", user_2.email + assert_equal "s3kure!", user_2.password + end + test "it sets the headers" do csv_string = CSV.generate do |csv| csv << %w[email_1@example.com s3krit] @@ -375,6 +395,26 @@ class Import < ArtVandelayTest assert_equal "s3kure!", user_2.password end + test "strips whitespace if strip configuration is passed when using custom attributes" do + csv_string = CSV.generate do |csv| + csv << ["email_address ", " passcode "] + csv << [" email_1@example.com ", " s3krit "] + csv << [" email_2@example.com", " s3kure! "] + end + + assert_difference("User.count", 2) do + ArtVandelay::Import.new(:users, strip: true).csv(csv_string, attributes: {:email_address => :email, "passcode" => "password"}) + end + + user_1 = User.find_by!(email: "email_1@example.com") + user_2 = User.find_by!(email: "email_2@example.com") + + assert_equal "email_1@example.com", user_1.email + assert_equal "s3krit", user_1.password + assert_equal "email_2@example.com", user_2.email + assert_equal "s3kure!", user_2.password + end + test "it no-ops if one record fails to save" do csv_string = CSV.generate do |csv| csv << %w[email password]