Why does yaml.dump add quotes this key-value pair - ruby-on-rails

I'm trying to write a new entry to a rails database.yml and for some reason I'm getting quotes around this entry
db_yml => {'new_env' => {'database' => 'database_name', '<<' => '*defaults' }}
File.open("#{RAILS_ROOT}/config/database.yml", "a") {|f| YAML.dump(db_yml, f)}
returns
---
new_env:
database: database_name
"<<": "*defaults"
I don't know why the "---" and the quotes around the defaults are returned, any thoughts on how to prevent?
thanks!

<< and * have special meaning in YAML.
Quotes are used to show that << is not merge and * is not an alias.

the --- is just to mark the start of YAML dump.
The double quote around << it's because can be interpretate in YAML format. So it's escape.

Related

Removing double quotes from the beging and end of an array in Ruby

I have an array stored in a file, when I read this file to variable in Ruby it returns double quotes at the beginning and end of the array. I use Ruby 2.7.0
irb
irb(main):065:0> ports = IO.read('/ports_values')
irb(main):066:0> ports
=> "['127.0.0.1:6601:6601', '127.0.0.1:8000:8000', '127.0.0.1:7200:7200', '127.0.0.1:9201:9201', '5606:5606', '6304:6504', '6305:6505']"
But what I need this:
irb(main):066:0> ports
=> ['127.0.0.1:6601:6601', '127.0.0.1:8000:8000', '127.0.0.1:7200:7200', '127.0.0.1:9201:9201', '5606:5606', '6304:6504', '6305:6505']
without double quotes and I tried this ,but it did not work
irb(main):067:0> ports.gsub /"/, ' '
=> "['127.0.0.1:6601:6601', '127.0.0.1:8000:8000', '127.0.0.1:7200:7200', '127.0.0.1:9201:9201', '5606:5606', '6304:6504', '6305:6505']"
a = "['127.0.0.1:6601:6601', '127.0.0.1:8000:8000', '127.0.0.1:7200:7200', '127.0.0.1:9201:9201', '5606:5606', '6304:6504', '6305:6505']"
a.slice(1..-2).split(",").map{ |b| b.strip.gsub("'","")}
o/p: ["127.0.0.1:6601:6601", "127.0.0.1:8000:8000", "127.0.0.1:7200:7200", "127.0.0.1:9201:9201", "5606:5606", "6304:6504", "6305:6505"]

How to read a CSV that contains double quotes (")

I have a CSV File that looks like this
"url","id","role","url","deadline","availability","location","my_type","keywords","source","external_id","area","area (1)"
"https://myurl.com","123456","This a string","https://myurl.com?source=5&param=1","31-01-2020","1","Location´s Place","another_string, my_string","key1, key2, key3","anotherString","145129","Place in Earth",""
It has 13 columns.
The issue is that I get each row with a \" and I don't want that. Also, I get 16 columns back in the read.
This is what I have done
csv = CSV.new(File.open('myfile.csv'), quote_char:"\x00", force_quotes:false)
csv.read[1]
Output:
["\"https://myurl.com\"", "\"123456\"", "\"This a string\"", "\"https://myurl.com?source=5&param=1\"", "\"31-01-2020\"", "\"1\"", "\"Location´s Place\"", "\"another_string", " my_string\"", "\"key1", " key2", " key3\"", "\"anotherString\"", "\"145129\"", "\"Place in Earth\"", "\"\""]
The file you showed is a standard CSV file. There is nothing special needed. Just delete all those unnecessary arguments:
csv = CSV.new(File.open('myfile.csv'))
csv.read[1]
#=> [
# "https://myurl.com",
# "123456",
# "This a string",
# "https://myurl.com?source=5&param=1",
# "31-01-2020",
# "1",
# "Location´s Place",
# "another_string, my_string",
# "key1, key2, key3",
# "anotherString",
# "145129",
# "Place in Earth",
# ""
# ]
force_quotes doesn't do anything in your code, because it controls whether or not the CSV library will quote all fields when writing CSV. You are reading, not writing, so this argument is useless.
quote_char: "\x00" is clearly wrong, since the quote character in the example you posted is clearly " not NUL.
quote_char: '"' would be correct, but is not necessary, since it is the default.

Improper indentation in converting ruby hash to yaml

I am trying to convert ruby hash object to YAML format using YAML.dump(obj) but I am getting improper indentation even after using dump options.
I have below executable ruby script :
#!/usr/bin/ruby
require "yaml"
require "erb"
context_path = ARGV[0]
context = YAML.load_file(context_path)['context']
def get_yaml(obj)
YAML.dump( obj['imports']['external_repositories']['credentials'] ).sub(/.*?\n/,'')
end
The value of - obj['imports']['external_repositories']['credentials'] is
{"iacbox"=>{"basic"=>{"name"=>"", "password"=>""}}, "nexus"=>{"basic"=>{"name"=>"cpreader", "password"=>"swordfish"}}}
Note : I used the sub method to remove "---" at the start of the output
The ERB template calls the above get_yaml method as :
credentials:
<%= get_yaml( context ) %>
The output that is coming is :
credentials:
iacbox:
basic:
name: ''
password: ''
nexus:
basic:
name: cpreader
password: swordfish
while I am expecting the output as :
credentials:
iacbox:
basic:
name: ''
password: ''
nexus:
basic:
name: cpreader
password: swordfish
How can I get the expected output from a dump?
I think the easiest thing for you to do here is just put the credentials key also in the Hash, i.e. change your template snippet so that it is one line:
<%= get_yaml( context ) %>
And change your get_yaml method to be:
def get_yaml(obj)
YAML.dump({'credentials' => obj['imports']['external_repositories']['credentials']})
.sub(/.*?\n/,'')
end
If that doesn't work for you, for example, if you have additional keys underneath the credentials key that you haven't mentioned, you could also do something like this:
def get_yaml(obj)
YAML.dump(obj['imports']['external_repositories']['credentials'])
.sub(/^---\n/,'')
.gsub(/\n/m,"\n ")
end
Where gsub(/\n/m,"\n ") replaces all newlines with a newline plus two spaces.

String start with # return with backslash in rails console in some case

In console of rails 4.2.7, I have the following test:
[45] pry(main)> '#$'
=> "\#$"
[46] pry(main)> '##'
=> "\##"
[47] pry(main)> '#!'
=> "#!"
[48] pry(main)> '#ab'
=> "#ab"
It seems rails will only put a "\" before the string when there is an # or $ after #.
The problem leads me to this test is that I have a erb file that render a data attribute with an array of json:
data-xx="<%= [{xx: '#$', yy: 'yy'}.to_json, {zz: 'zzz'}.to_json] %>"
Then in chrome console, it will give the unexpected result as
$("#entry_show_modal_template").data('xx')
"["{\"xx\":\"\#$\",\"yy\":\"yy\"}", "{\"zz\":\"zzz\"}"]"
And when I change xx value from #! or some other string, the result will be ok as an array
$("#entry_show_modal_template").data('xx')
["{"xx":"#!","yy":"yy"}", "{"zz":"zzz"}"]
Does someone know if it is true and why it has such difference?
And it there any way to tackle this problem?
This is not true.
In '#{...}' hash will also be escaped. This is done to prevent recursive/implicit string interpolation.
Look:
$a = 'hello'
"#$a"
#⇒ "hello"
The problem is already solved by ruby for you. Just use the produced string as is and don’t be fooled by the way it is printed out in console.
"\#$".length
#⇒ 2
"\#$" == '#$'
#⇒ true
"\#$"[0]
#⇒ "#"
#mudasobwa's explaination is correct
According to your situation you should try in this way
===> In rails console
json_values = [{xx: '#$', yy: 'yy'}, {zz: 'zzz'}].to_json
===> In chrome console
result = JSON.parse(json_values)
you will get expected array, its just ruby technique to handle string interpolation thing

Illegal quoting on line using FasterCSV in ruby 1.8.7

I am facing "Illegal quoting" error when parse the content from SQL dump and the dump file is in the format of TXT with tab (\t) separator.
require 'rubygems'
require 'faster_csv'
begin
FasterCSV.foreach(excel_file, :quote_char => '"',:col_sep =>'\t', :row_sep =>:auto, :headers => :first_row) do |row|
col= row.to_s.split(/\t/)
if col[3]!="" or !col[3].empty?
color_value=col[3].to_s.capitalize
#Inser Color
color=Color.find_or_create_by_name(:name=>color_value)
elsif col[3].empty?
color_id= nil
end
end
rescue Exception => e
puts e
end
The program executed and run successfully but there is an invalid data present like
below (#font-face ...) mean execution terminated with error of "Illegal quoting on line 3.
ID Name code comments
1 white 234 good
2 Black 222
3 red 343 #font-face { font-family: "Verdana"; .....}
Can any one suggest me how to skip when invalid data occurs in column ?
Thanks in advance.
I'm not sure if this will solve the error you are seeing, but you need to use double quotes around escaped characters, e.g.:
:col_sep => "\t"
FasterCSV isn't very kind to badly formatted data.
I don't know that there is a solution for this.
However - if your example file doesn't actually contain any quoting using "
then perhaps just use a different quot_char (eg ')
You can use the ASCII code for the NULL character -- \0x00 -- as such:
FasterCSV.foreach(excel_file, :quote_char => '\0x00',:col_sep =>'\t', :row_sep =>:auto, :headers => :first_row) do |row|
...
end
You can find a chart of some ASCII chars here: http://www.bluesock.org/~willg/dev/ascii.html

Resources