Skip to content

Instantly share code, notes, and snippets.

@Ross-Hunter
Forked from zdennis/report-exercise.rb
Last active December 14, 2015 04:09
Show Gist options
  • Save Ross-Hunter/5026674 to your computer and use it in GitHub Desktop.
Save Ross-Hunter/5026674 to your computer and use it in GitHub Desktop.
#
# The goal of this exercise is work on identifying abstraction which helps simplify, document,
# and separate the concerns going on in file.
#
# Exercise:
# * Find related ideas in the below code
# * Abstract them out (methods, modules, classes, etc, you pick!)
# * If you find multiple ways, then do a separate gist for each way.
# * Rinse repeat until you see no other ways.
#
# Note: there is not enough of the code-base to run this code, so in order to run
# the code you'll have to implement the missing pieces.
require 'rubygems'
require 'active_record'
# Lib
module ShipLogReportFormatter
def self.for(format)
string_format = format.to_s
formatter_string = string_format.capitalize + "ReportFormatter"
if ShipLogReportFormatter.const_defined?(formatter_string)
formatter = ShipLogReportFormatter.const_get(formatter_string)
else
raise "Unknown report format: #{string_format}"
end
formatter
end
class ReportFormatter
attr_reader :report
def initialize(report)
@report = report
end
end
class PlainReportFormatter < ReportFormatter
def generate
output = []
output << "###### #{report.title} ######"
report.text.each do |line|
output << line
end
output.join "\n"
end
end
class HtmlReportFormatter < ReportFormatter
def generate
output = "<html>"
output << " <head>"
output << " <title>#{report.title}</title>"
output << " </head>"
output << " <body>"
report.text.each do |line|
output << " <p>#{line}</p>"
end
output << " </body>"
output << "</html>"
output
end
end
class JsonReportFormatter < ReportFormatter
def generate
output = { title: report.title, lines: [] }
report.text.each do |line|
output[:lines] << line
end
output
end
end
end
# Implementation
class ShipLogReport
attr_accessor :title, :text
def initialize(ship, start_date, end_date)
@ship = ship
@title = "#{@ship.name} Report"
logs = ship.logs_for_range(start_date, end_date)
@text = logs.map do |log|
status = "#{log.date}: #{log.message} (#{log.alert_level})"
end
end
def generate(format)
formatter = ShipLogReportFormatter.for(format)
formatter.new(self).generate
end
end
class Ship
attr_accessor :name
def initialize(name)
@name = name
end
def logs_for_range(start_date, end_date)
# logs.where(
# :date => start_date..end_date,
# :state => "active"
# ).order("date DESC")
logs = [
Log.new("Yo YO YO", "High"),
Log.new("What is up?", "Low"),
Log.new("Nothing", "Medium")
]
end
end
class Log
attr_accessor :date, :message, :alert_level, :state
def initialize(message, alert_level)
@date = Time.now
@message = message
@alert_level = alert_level
@state = "active"
end
end
# Run it!
ship = Ship.new("U.S.S Enterprise")
report = ShipLogReport.new(ship, Time.new(Time.now.year), Time.now)
puts report.generate(ARGV.shift.to_sym)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment