ikRubyTuesday
ikRubyTuesday

Reputation: 3

create comma separated string in the First element of an array Ruby

So this may seem odd, and I have done quite a bit of googling, however, I am not really a programmer, (sysops) and trying to figure out how to pass data to the AWS API in the required format, which does seem a little odd.

So, working with resources in AWS, I need to pass tags which are keys and values. The key is a string. The value is a comma separated string, in the first element of an array. So in Ruby terms, looks like this.

{env => ["stage,qa,dev"]} 

and not

{env => ["stage","qa","dev"]}

I'm created an admittedly. not a very pretty little app that will allow me to run ssm documents on targeted instances in aws.

I can get the string into an array element using this class I created

class Tags

  attr_accessor :tags

  def initialize
    @tags    = {"env" => nil ,"os" => nil ,"group" => nil }
  end

  def set_values()
    puts "please enter value/s for the following keys, using spaces or commas for multiple values"
    @tags.each { |key,value|
    print "enter #{key} value/s: "
    @tags[key] = [gets.strip.chomp]
    @tags[key] = Validate.multi_value(tags[key])
    }
  end

end

I then call this Validate.multi_value passing in the created Array, but it spits an array of my string value back.

class Validate
  def self.multi_value(value)
      if value.any?{ |sub_string| sub_string.include?(",") || sub_string.include?(" ") }
         value = value[0].split(/[,\s]+/)
       return value
      else
       return value
     end

    end

end

Using pry, I've seen it gets for example ["stage dev qa"] then the if statement does work, then it spits out ["stage","dev","qa"].

and I need it to output ["stage,dev,qa"] but for the life of me, I can't make it work.

I hope that's clear.

If you have any suggestions, I'd be most grateful.

I'm not hugely experienced at ruby and the may be class methods that I've missed.

Upvotes: 0

Views: 1173

Answers (3)

Mejs
Mejs

Reputation: 13

What do you think about this?, everything gets treated in the Validates method. I don't know if you wanted to remove repeated values, but, just in case I did, so a

"this    string,, has too  many,,, , spaces"

will become

"this,string,has,too,many,spaces"

and not

"this,,,,string,,,has,too,,many,,,,,,spaces"

Here's the code

class Tags
  attr_accessor :tags

  # initializes the class (no change)
  #
  def initialize
    @tags = {"env" => nil ,"os" => nil ,"group" => nil }
  end

  # request and assign the values <- SOME CHANGES
  #
  def set_values
    puts "please enter value/s for the following keys, using spaces or commas for multiple values"
    @tags.each do |key,value|
      print "enter #{key} value/s: "
      @tags[key] = Validate.multi_value( gets )
    end
  end
end

class Validate
  # Sets the array
  #
  def self.multi_value(value)
    # Remove leading spaces, then remove special chars,
    # replace all spaces with commas, then remove repetitions
    #
    [ value.strip.delete("\n","\r","\t","\rn").gsub(" ", ",").squeeze(",") ]
  end
end

EDITED, thanks lacostenycoder

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110665

I see no point in creating a class here when a simple method would do.

def set_values
  ["env", "os", "group"].map do |tag|
    puts "Please enter values for #{tag}, using spaces or commas"
    print "to separate multiple values: "
    gets.strip.gsub(/[ ,]+/, ',')
  end
end

Suppose, when asked, the user enters, "stage dev,qa" (for"env"), "OS X" (for"OS") and "Hell's Angels" for "group". Then:

set_values
  #=> ["stage,dev,qa", "OS,X", "Hell's,Angels"]

If, as I suspect, you only wish to convert spaces to commas for "env" and not for "os" or "group", write:

def set_values 
  puts "Please enter values for env, using spaces or commas"
  print "to separate multiple values: "
   [gets.strip.gsub(/[ ,]+/, ',')] +
   ["os", "group"].map do |tag|
     print "Please enter value for #{tag}: "
     gets.strip
   end
end

set_values
  #=> ["stage,dev,ga", "OS X", "Hell's Angels"] 

See Array#map, String#gsub and Array#+.

gets.strip.gsub(/[ ,]+/, ',') merely chains the two operations s = gets.strip and s.gsub(/[ ,]+/, ','). Chaining is commonplace in Ruby.

The regular expression used by gsub reads, "match one or more spaces or commas", [ ,] being a character class, requiring one of the characters in the class be matched, + meaning that one or more of those spaces or commas are to be matched. If the string were "a , b,, c" there would be two matches, " , " and ",, "; gsub would convert both to a single comma.

Using print rather than puts displays the user's entry on the same line as the prompt, immediately after ": ", rather than on the next line. That is of course purely stylistic.

Often one would write gets.chomp rather than gets.strip. Both remove newlines and other whitespace at the end of the string, strip also removes any whitespace at the beginning of the string. strip is probably best in this case.

Upvotes: 0

Mark
Mark

Reputation: 6445

If your arrays are always coming through in the format ["stage dev qa"] then first we need to split the one string into the parts we want:

arr = ["stage dev qa"]
arr.split(' ')
=> ["stage", "dev", "qa"]

Then we need to join them with the comma:

arr.split(' ').join(',')
=> "stage,dev,qa"

And finally we need to wrap it in an array:

[arr.first.split(' ').join(',')]
=> ["stage,dev,qa"]

All together:

def transform_array(arr)
  [arr.first.split(' ').join(',')]
end

transform_array(['stage dev qa'])
=> ['stage,dev,qa']

More info: How do I convert an array of strings into a comma-separated string?

Upvotes: 2

Related Questions