Skip to content

Instantly share code, notes, and snippets.

@david
Created August 3, 2012 13:34
Show Gist options
  • Save david/3247739 to your computer and use it in GitHub Desktop.
Save david/3247739 to your computer and use it in GitHub Desktop.
Lunacy? Or OO?
# Deciding how to handle a collection based on its size.
#
# Inspired by http://silkandspinach.net/2012/07/06/hexagonal-rails-hiding-the-finders/
#
# See below for usage
module Demux
def demux(demux, outputs = nil, &block)
if outputs && block_given?
raise ArgumentError, "Pass either a block or an object, not both"
elsif outputs
demux.demux_outputs outputs
elsif block_given?
demux.demux_block &block
else
raise ArgumentError, "Pass either a block or an object"
end
demux
end
end
module SizeDemux
include Demux
# Inspect collection size and pick the appropriate line.
#
# Available lines:
# * zero - if the collection is empty
# * non_zero(collection) - if the collection is not empty
# * one(element) - if the collection has a single element
# * many(collection) - if the collection has more than one element
#
# Usage:
#
# collection.demux_size do |outputs|
# outputs.zero { ... }
# outputs.non_zero { |collection| ... }
# ...
# end
#
# # or
#
# class Demuxed
# def zero
# ...
# end
#
# def non_zero(collection)
# ...
# end
# end
#
# collection.demux_size(Demuxed.new)
#
def demux_size(outputs = nil, &block)
demux(SizeDemux.new(self), outputs, &block)
end
class SizeDemux
LINES = %w(zero non_zero one many)
def initialize(collection)
@collection = collection
end
def demux_block
yield self
end
def demux_outputs(outputs)
LINES.each do |line|
send(line) { |*args| outputs.send(line, *args) }
end
end
def zero
yield if @collection.size == 0
end
def non_zero
yield @collection if @collection.size > 0
end
def one
yield @collection.first if @collection.size == 1
end
def many
yield @collection if @collection.size > 1
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment