Rubyists life made easier with composition operators.
Eugene Komissarov
Posted on August 23, 2019
If you write Ruby code and wandered into FP world you might just started writing those little tiny methods inside your classes/modules. And that was awesome to write code like this:
class Import
# Some code goes here...
def find_record(row)
[ Msa.find_or_initialize_by(region_name: row[:region_name], city: row[:city], state: row[:state], metro: row[:metro] ), row ]
end
# record is one of:
# Object - when record was found
# false - when record was not found
def update_record(record, attributes)
record.attributes = attributes
record
end
# record is one of:
# false
# ZipRegion
def validate_record(record)
case record
when false
[:error, nil]
else
validate_record!(record)
end
end
# record is ZipRegion object
def validate_record!(record)
if record.valid?
[:ok, record]
else
error(record.id, record.errors.messages)
[:error, record]
end
end
def persist_record!(validation, record)
case validation
when :ok
record.save
when :error
false
end
end
end
Yeah, I know there is YARD, and argument types are somewhat weird but at the time of coding, I was fascinated with Gregor Kiczales's HTDP courses (that was a ton of fun, sincerely recommend for every adventurous soul).
And next comes dreadful composition:
def process(row, index)
return if header_row?(row)
success(row[:region_name], persist_record!(*validate_record(update_record(*find_record(parse_row(row))))))
end
The pipeline is quite short but already hard to read. Luckily, in Ruby 2.6 we now have 2 composition operators: Proc#>> and its reverse sibling Proc#<<.
And, with a bit of refactoring composition method becomes:
def process(row, index)
return if header_row?(row)
composition = method(:parse_row) >>
method(:find_record) >>
method(:update_record) >>
method(:validate_record) >>
method(:persist_record!) >>
method(:success).curry[row[:region_name]]
composition.call(row)
Much nicier, don't you think? Ruby just became one step closer to FP-friendly languages family, let's hope there'll be more!
Posted on August 23, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.