Create JSON of one dimension Ruby - ruby

I want to have this:
["(GKA) GOROKA, GOROKA, PAPUA NEW
GUINEA"]
instead of:
[
[
"(GKA)",
"GOROKA",
"GOROKA",
"PAPUA NEW GUINEA"
] ]
I have this code so far:
#aeropuertos = ""
f = File.open("./public/aeropuertos/aeropuertos.cvs", "r")
f.each_line { |line|
fields = line.split(':')
if (fields[2] == "N/A")
#line = "(" << fields[1] << ")" << ",," << fields[3] << "," << fields[4]
else
#line = "(" << fields[1] << ")" << "," << fields[2] << "," << fields[3] << "," << fields[4]
end
#aeropuertos += #line << "\n"
}
return CSV.parse(#aeropuertos).to_json
What should I do?

#aeropuertos = ""
f = File.open("./public/aeropuertos/aeropuertos.cvs", "r")
f.each_line { |line|
fields = line.split(':')
if (fields[2] == "N/A")
#line = "(" << fields[1] << ")" << ",," << fields[3] << "," << fields[4]
else
#line = "(" << fields[1] << ")" << "," << fields[2] << "," << fields[3] << "," << fields[4]
end
#aeropuertos += #line << "\n"
}
res = []
CSV.parse(#aeropuertos).each do |c|
res << c.join(',')
end
return res.to_json

There's no need for the CSV parser. Just create the structure you want as you read each line. That is, instead of making a large string in #aeropuertos and parsing it with a CSV parser, make #aeropuertos an array, and add each #line to the array.
So, instead of this:
#aeropuertos += #line << "\n"
Do this:
#aeropuertos << #line
But be sure to say this at the beginning:
#aeropuertos = []

Related

How to fix incompatible character encodings: UTF-8 and ASCII-8BIT

The issue is with the 'chap << "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"' line.
chaps = []
ctoc = "toc1\x00"
ctoc << [3, chapters.size].pack("CC")
chapters.each_with_index do |ch, i|
num = i+1
title = ch[:title]
description = ch[:description]
link = ch[:link]
ctoc << "ch#{num}\x00"
chap = "ch#{num}\x00"
chap << [ch[:start]*1000, ch[:end]*1000].pack("NN");
chap << "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
title_tag = [title.encode("utf-16")].pack("a*");
chap << "TIT2"
chap << [title_tag.size+1].pack("N")
chap << "\x00\x00\x01"
chap << title_tag
chaps << chap
end
I have added the following to the top of the file but that didn't fix the issue. Any other ideas to try?
# encoding: utf-8

How to make sure REXML::Formatters::Pretty uses \t instead of white-space for indentation

It seems to me that there's no way of making sure REXML::Formatters::Pretty can use \t instead of white-space for the indentation strategy in the XML Tree. The only thing I can do is to define how many white spaces are used per indentation level.
Am I wrong?
Not sure why REXML library does not provide you with this option since it could definitely support it internally but you can just roll your own formatter:
module REXML
module Formatters
class Prettier < Pretty
attr_accessor :style
def initialize(indentation = 2, indent_style =" ", ie_hack=false)
#style = indent_style
super(indentation,ie_hack)
end
protected
def write_element(node, output)
output << style*#level
output << "<#{node.expanded_name}"
node.attributes.each_attribute do |attr|
output << " "
attr.write( output )
end unless node.attributes.empty?
if node.children.empty?
if #ie_hack
output << " "
end
output << "/"
else
output << ">"
# If compact and all children are text, and if the formatted output
# is less than the specified width, then try to print everything on
# one line
skip = false
if compact
if node.children.inject(true) {|s,c| s & c.kind_of?(Text)}
string = ""
old_level = #level
#level = 0
node.children.each { |child| write( child, string ) }
#level = old_level
if string.length < #width
output << string
skip = true
end
end
end
unless skip
output << "\n"
#level += #indentation
node.children.each { |child|
next if child.kind_of?(Text) and child.to_s.strip.length == 0
write( child, output )
output << "\n"
}
#level -= #indentation
output << style*#level
end
output << "</#{node.expanded_name}"
end
output << ">"
end
def write_text( node, output )
s = node.to_s()
s.gsub!(/\s/,' ')
s.squeeze!(" ")
s = wrap(s, #width - #level)
s = indent_text(s, #level, style, true)
output << (style*#level + s)
end
def write_comment( node, output)
output << style * #level
Default.instance_method(:write_comment).bind(self).call(node,output)
end
def write_cdata( node, output)
output << style * #level
Default.instance_method(:write_cdata).bind(self).call(node,output)
end
end
end
end
Now you can specify your own indentation level and a indent style e.g.
require "rexml/document"
include REXML
string = <<EOF
<mydoc>
<someelement attribute="nanoo">Text, text, text</someelement>
</mydoc>
EOF
doc = Document.new string
f = Formatters::Prettier(2,"h")
f.write(doc,$stdout)
#<mydoc>
#hh<someelement attribute='nanoo'>
#hhhhText, text, text
#hh</someelement>
#</mydoc>
I used "h" to show how the indentation works as \t will not show up in $stdout but in you case this would be
f = Formatters::Prettier(1,"\t")

Create a symlink using ruby

I am trying to create a symlink for the created file but I get an error like File exists - (/etc/nginx/sites-available/sushant.com, /etc/nginx/sites-enabled/sushant.com) (Errno::EEXIST)
Here is my code
require 'fileutils'
open('/etc/hosts') do |f|
matches = []
vhosts = []
f.readlines.each do |lines|
matches << lines if lines =~ /.*.com/
end
matches.each do |val|
val.split.each do |x|
vhosts << x if x =~ /.*.com/
end
end
vhosts.each do |domain|
#put the path to sites-enabled
unless File.file? "/etc/nginx/sites-available/#{domain}"
open("/etc/nginx/sites-available/#{domain}", 'w') do |g|
g << "server { \n"
g << "\tlisten 80 default_server;\n"
g << "\tlisten [::]:80 default_server ipv6only=on;\n"
g << "\troot /usr/share/nginx/html;\n"
g << "\tindex index.html index.htm;\n"
g << "\tserver_name localhost;\n"
g << "\tlocation / {\n"
g << "\t\ttry_files $uri $uri/ =404;\n"
g << "\t}\n"
g << "}\n"
g << "server {\n"
g << "\tpassenger_ruby /path/to/ruby;\n"
g << "\trails_env development;\n"
g << "\tlisten 80;\n"
g << "\tserver_name #{domain};\n"
g << "\troot /usr/share/nginx/html/#{domain}/public;\n"
g << "\tpassenger_enabled on;\n"
g << "}\n"
end
File.symlink "/etc/nginx/sites-available/#{domain}", "/etc/nginx/sites-enabled/#{domain}"
end
end
p vhosts
end
Why is the EEXIST error occurs after I run the script? Am I missing out on something?
I have found out that I should have placed File.symlink "/etc/nginx/sites-available/#{domain}", "/etc/nginx/sites-enabled/#{domain}" first then the action to create the file.

Ruby cycle to alternate table row colors getting duplicates

I am trying to alternate colors every row but I am getting duplicate rows
def output_restaurant_table(restaurants=[])
print " " + "Name".ljust(30)
print " " + "Cuisine".ljust(20)
print " " + "Price".rjust(26) + "\n"
puts "-" * 80
restaurants.each do |rest|
line = " " << rest.name.titleize.ljust(30)
line << " " + rest.cuisine.titleize.ljust(20)
line << " " + rest.formatted_price.rjust(26)
x = [:red, :white]
x.cycle(1) { |x| output_action_header(line, :black, x) }
end
puts "No listings found" if restaurants.empty?
puts "-" * 80
end
If I try to move it out
If I had to guess - it's restarting the cycle every time you do another restaurant because of that line.
Try moving the x = [:red, :white] line outside of the restaurants.each loop (above it).
def output_restaurant_table(restaurants=[])
print " " + "Name".ljust(30)
print " " + "Cuisine".ljust(20)
print " " + "Price".rjust(26) + "\n"
puts "-" * 80
# this is where you instantiate the set of things that will be cycled through.
# You don't want to do this for every loop or the cycle will start over
# every time you go through the loop (starting at the beginning every time)
x = [:red, :white].cycle
restaurants.each do |rest|
line = " " << rest.name.titleize.ljust(30)
line << " " + rest.cuisine.titleize.ljust(20)
line << " " + rest.formatted_price.rjust(26)
# this is where you are saying "get me the next value of this cycle"
x.next { |x| output_action_header(line, :black, x) }
end
puts "No listings found" if restaurants.empty?
puts "-" * 80
end

no implicit conversion of nil into String error

I have a ruby script that will create two files by taking and merging values from another file.
#Resources
require 'rubygems'
require 'csv'
col_date = []
col_constant1 = []
col_constant2 = []
col_appYear = []
col_statsDesc = []
col_keyStats =[]
col_weeklyTotal=[]
weekly_total = []
fname = "finalStats.csv" #variable for capture file
finalStatsFile = File.open(fname, "w") #write to capture file
fname2 = "weeklyStats.csv"
weeklyStatsFile = File.open(fname2, "w")
CSV.foreach('compareData.csv', converters: :numeric) do |row|
weekly_total << row[0] - row[1]
weekly_total.each do |data|
data << weekly_total.shift
weeklyStatsFile.puts data
end
end
#retrieve stats from original document
CSV.foreach("autoCapture.csv") {|row| col_date << row[0]}
CSV.foreach("autoCapture.csv") {|row| col_constant1 << row[1]}
CSV.foreach("autoCapture.csv") {|row| col_appYear << row[2]}
CSV.foreach("autoCapture.csv") {|row| col_statsDesc << row[3]}
CSV.foreach("autoCapture.csv") {|row| col_constant2 << row[4]}
CSV.foreach("autoCapture.csv") {|row| col_keyStats << row[5]}
CSV.foreach("weeklyStats.csv") {|row| col_weeklyTotal << row[0]}
col_date.zip(col_constant1, col_appYear, col_statsDesc, col_constant2, col_keyStats, col_weeklyTotal).each do |col_date, col_constant1, col_appYear, col_statsDesc, col_constant2,
col_keyStats, col_weeklyTotal|
finalStatsFile.puts col_date+", "+col_constant1+", "+ col_appYear+", "+col_statsDesc+", "+col_constant2+", "+col_keyStats+", "+col_weeklyTotal
end
In one file I wish to subtract the values in row[1] from the values in row[0] to create a new 'weekly_total' value. I then output this array of values in a file called weeklyStats.csv. This will output a column of values fine.
However, I want to join these values with another set from another file (autoCapture.csv) and when I try to zip them as arrays so that they read across in corresponding rows I get the error:
weeklyStats_csv.rb:42:in `+': no implicit conversion of nil into String (TypeError)
from weeklyStats_csv.rb:42:in `block in <main>'
from weeklyStats_csv.rb:40:in `each'
from weeklyStats_csv.rb:40:in `<main>'
I gather this means that the array zip will not catch an exception if the one of the values is nil and therefore cannot convert to string. The problem is, I have tried converting weekly_total to string and array as I thought that it may be the problem (a mismatch of types) but I just dont where to go from here. Can anyone help?
One of (or more) values in string
finalStatsFile.puts col_date+", "+col_constant1+", "+ col_appYear+", "+col_statsDesc+", "+col_constant2+", "+col_keyStats+", "+col_weeklyTotal
became nil. To fix the output you should explicitly cast them to strings:
finalStatsFile.puts col_date.to_s + ", " +
col_constant1.to_s + ", " +
col_appYear.to_s + ", " +
col_statsDesc.to_s + ", " +
col_constant2.to_s + ", " +
col_keyStats.to_s + ", " +
col_weeklyTotal.to_s
BTW, the whole clause might be rewritten in more rubyish manner:
finalStatsFile.puts [ col_date,
col_constant1,
col_appYear,
col_statsDesc,
col_constant2,
col_keyStats,
col_weeklyTotal ].map(&:to_s).join(', ')

Resources