Skip to content

Instantly share code, notes, and snippets.

@dreamr
Last active December 18, 2015 21:19
Show Gist options
  • Save dreamr/5846372 to your computer and use it in GitHub Desktop.
Save dreamr/5846372 to your computer and use it in GitHub Desktop.
My stab at functional coding in Ruby!
# simply takes an array and joins it with --'s
format_log_line = ->(func) {
if func.kind_of?(Array)
func.flatten.compact.join(" -- ").concat("\n")
else
func
end
}
# write a file, functional stylee
write_file = ->(file, func) {
log_line = format_log_line.(func)
File.open(File.expand_path(file), "a") do |f|
f.write(log_line)
end
log_line
}
# log, but to a file (a printer)
to_file = ->(func, path) {
write_file.(path, [func, Time.now.to_s])
}
# log, but to a screen (a printer)
to_screen = ->(func) {
log_line = format_log_line.(func)
puts format_log_line.(func)
format_log_line.(func)
}
# log dat shit! (and choose a printer)
do_log = ->(printer) { printer }
# log as a functional enumerator
with_logging = ->(func, path) {
func.map {|item| do_log.(to_file.(item, path)) }
}
# print as a functional enumerator
with_printing = ->(func) {
do_log.(to_screen.(func))
}
##### ------ TESTS
require 'stringio'
require 'fileutils'
require 'timecop'
require 'minitest/spec'
require 'minitest/autorun'
def capture_stdout(&block)
original_stdout = $stdout
$stdout = fake = StringIO.new
begin
block.call
ensure
$stdout = original_stdout
end
fake.string
end
describe "Functional Logger" do
let(:messages) {
["Something went wrong!", "Oh shit, what now?", "Don't co-opt nil!"]
}
let(:log_path) { File.expand_path("../test.log", __FILE__) }
let(:log_text) { File.open(log_path, "r") {|f| f.read } }
describe "write_file" do
subject { write_file }
let(:text) { "Hello world!" }
end
describe "to_screen" do
subject { to_screen }
it "will send the log line with no date to STDOUT" do
capture_stdout {
subject.("Hello world!")
}.must_equal "Hello world!\n"
end
end
describe "to_file" do
subject { to_file }
it "will send the log line including the timestamp into the log file" do
Timecop.freeze do
subject.(messages, log_path)
assert log_text =~ /Something went wrong! -- Oh shit, what now\? -- Don't co-opt nil! -- #{Time.now}\n/
end
end
end
describe "do_log" do
subject { do_log }
describe "to_screen" do
let(:printer) { to_screen }
it "will send the log line with no date to STDOUT" do
capture_stdout {
subject.(printer).(messages)
}.must_equal "Something went wrong! -- Oh shit, what now? -- Don't co-opt nil!\n"
end
end
describe "to_file" do
let(:printer) { to_file }
it "will send the log line including the timestamp into the log file" do
Timecop.freeze do
subject.(printer).(messages, log_path)
assert log_text =~ /Something went wrong! -- Oh shit, what now\? -- Don't co-opt nil! -- #{Time.now}\n/
end
end
end
end
describe "with_printing" do
subject { messages }
it "must print to screen for each message" do
capture_stdout {
subject.map(&with_printing)
}.must_equal(
"Something went wrong!\n"+
"Oh shit, what now?\n"+
"Don't co-opt nil!\n"
)
end
end
describe "with_logging" do
subject { messages }
it "will send the log line including the timestamp into the log file" do
FileUtils.rm(log_path, :force => true)
Timecop.freeze do
with_logging.(subject.map, log_path)
File.open(log_path, "r") {|f| f.read }.must_equal(
"Something went wrong! -- #{Time.now}\n"+
"Oh shit, what now? -- #{Time.now}\n"+
"Don't co-opt nil! -- #{Time.now}\n"
)
end
end
end
end
# log to the screen!
#do_log.(to_screen.(messages))
# log to a file!
#do_log.(to_file.(messages, "~/test.log"))
# enumerate and print to screen
# messages.map(&with_printing)
# enumerate and print to log file
# with_logging.(messages.map, log_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment