I have made 2 scripts in Ruby. The first program creates an .rtf file with cards (file with colored table with persons) from a list of people in text file. The second program does the same, but in an HTML file. In the first, I can use the gem library, but I'm not allowed to do so in the second.
My teacher said that in both cases, code could be two times shorter. He also said that I'm not organising stuff in class and methods; that could be a problem if I start to write more advanced codes in future. I'm asking where and how I could improve my code to be shorter and organised in classed/method. I placed my notes in the comments.
require 'rubygems'
require 'rtf'
include RTF
def card(t, person, style1, style2, i)
style = CharacterStyle.new
x = i/2.0.floor
y = i % 2
if x % 2 == 0
style = style1
t[x][y].shading_colour = $olive
else
style = style2
t[x][y].shading_colour = $maroon
end
person = person.split(";")
# I could bet that there's some way to automatically apply line_break command after all following lines.
t[x][y].apply(style) << "name: " + person[0]
t[x][y].line_break
t[x][y].apply(style) << "surname: " + person[1]
t[x][y].line_break
t[x][y].apply(style) << "date_of_birth: " + person[2]
t[x][y].line_break
t[x][y].apply(style) << "salary: " + person[3]
t[x][y].line_break
t[x][y].apply(style) << "phone: " + person[4]
t[x][y].line_break
t[x][y].apply(style) << "position: " + person[5]
t[x][y].line_break
t[x][y].apply(style) << "email: "+ person[6]
end
document = Document.new(Font.new(Font::ROMAN, 'Times New Roman'), nil, Document::CS_PC, Document::LC_POLISH)
# I don't like using a global variables there but applying them directly in method card would slow down whole script.
$maroon = Colour.new(125, 0, 0)
$olive = Colour.new(125, 125, 0)
style1 = CharacterStyle.new
style1.font = Font.new(Font::MODERN, 'Calibri')
style1.foreground = $maroon
style1.underline = true
style2 = CharacterStyle.new
style2.font = Font.new(Font::ROMAN, 'Times New Roman')
style2.bold = true
style2.foreground = $olive
people = []
f = open('base.txt', "r:UTF-8") { |f| f.read }
f.each_line { |ln| people << ln }
array = document.table(people.length/2.0.ceil,2, 4000,4000,4000)
# I don't like using "i" variable as cell counter of table. I would like to use some useful method instead of that.
i = 0
people.each {|person|
card(array, person, style1, style2, i)
i += 1
}
File.open('cards.rtf', 'w:UTF-8') {|f| f.write(document.to_rtf)}
Second program
def b(text)
"<b>#{text}</b>"
end
def array(document, person, i)
person = person.split(';')
# I don't like the "i" variable. I think there is an other simple way in ruby to do something diffrent in loop for every second element.
if i % 2 == 0
document << "<tr>"
color1 = 'maroon'
color2 = 'olive'
else
color1 = 'olive'
color2 = 'maroon'
end
# There would be great if i could organise array styles in methods.
document << "<td><p style='background-color:#{color1};font-family:arial;color:#{color2};font-size:20px;'>"
document << b("name: ") + person[0] + "<br />"
document << b("surname: ") + person[1] + "<br />"
document << b("date_of_birth: ") + person[2] + "<br />"
document << b("salary: ") + person[3] + "<br />"
document << b("phone: ") + person[4] + "<br />"
document << b("position: ") + person[5] + "<br />"
document << b("email: ") + person[6] + "<br />"
document << "</p></td>"
if i % 2 == 1
document << "</tr>"
end
end
people = []
f = open('base.txt', "r:UTF-8") { |f| f.read }
f.each_line { |ln| people << ln }
document = ''
# I would like to create document as an object of some class.
document <<
"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<meta content='text/html; charset=ISO-8859-2'
http-equiv='content-type'>
<title></title>
</head>
<body>
<table>"
i = 0
people.each { |person|
array(document, person, i)
i += 1
}
document <<
"</table>
</body>
</html>"
File.open('document.html', 'w:ISO-8859-2') { |f| f.write document }