Created
December 8, 2015 19:41
-
-
Save eljojo/3682cdbde11f49d6a545 to your computer and use it in GitHub Desktop.
some playing with functional programming and ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A HashManipulation is a helper object. | |
# The idea is to aid when modifying hashes. | |
# changes = HashManipulation.new | |
# changes.key { |key| key.upcase } | |
# changes.value { |value| value.length } | |
# changes.("children" => [1, 2, 3]) # {"CHILDREN" => 3} | |
module Reports | |
class HashManipulation | |
def initialize | |
@key = -> (obj) { obj } | |
@value = -> (obj) { obj } | |
end | |
def key(&block) | |
@key = block | |
self | |
end | |
def value(&block) | |
@value = block | |
self | |
end | |
def call(obj) | |
obj.map do |key, value| | |
[@key.call(key), @value.call(value)] | |
end.to_h | |
end | |
def self.value(&block) | |
self.new.value(&block) | |
end | |
def self.key(&block) | |
self.new.key(&block) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A Pipe is intended to be simple way of doing function composition (?) | |
module Reports | |
class Pipe | |
def initialize(procs = []) | |
@procs = procs | |
end | |
delegate :<<, to: :@procs | |
def call(obj) | |
@procs.inject(obj) { |memo, func| func.(memo) } | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Reports | |
class RepeatSwitches | |
def initialize | |
@contract_data = ContractDatum.all.ordered.includes(:user) | |
end | |
def report | |
group_by_first_or_second_switch = procerize(:group_by) do |contract| | |
first_switch?(contract) ? "First Switch" : "Repeat Switch" | |
end | |
get_counts = HashManipulation.value {|values| values.length } | |
get_switches_count = HashManipulation.value do |contracts| | |
get_counts.(group_by_first_or_second_switch.(contracts)) | |
end | |
add_totals = HashManipulation.value do |hash| | |
hash.dup.tap do |res| | |
res["Total"] = hash.values.inject(:+) | |
end | |
end | |
pipe = Pipe.new | |
pipe << get_switches_count | |
pipe << add_totals | |
final_function = group_by_month(pipe) | |
final_function.(@contract_data) | |
end | |
def group_by_month(action) | |
group_by_month = procerize(:group_by) do |contract_datum| | |
ordered_at = contract_datum.ordered_at | |
[ordered_at.year, ordered_at.mon] | |
end | |
sort_by_first = -> (hash) { hash.sort_by(&:first).to_h } | |
humanize_month = HashManipulation.key{|(year, month)| "#{year}/#{month}" } | |
pipe = Pipe.new | |
pipe << group_by_month | |
pipe << action | |
pipe << sort_by_first | |
pipe << humanize_month | |
pipe | |
end | |
private | |
def first_switch?(contract_datum) | |
ordered_at = ContractDatum.arel_table[:ordered_at] | |
user_contracts = contract_datum.user.contract_data.ordered | |
user_contracts.where(ordered_at.lt(contract_datum.ordered_at)).empty? | |
end | |
def procerize(method, &block) | |
-> (obj) { obj.send(method, &block) } | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@bitboxer the intention still counts :)