Module: ProcMe
Overview
ProcMe is DRY and clean blocks for your code.
It provides four methods:
#fltr - checks object attribute values
['test', 'me', 'please'].select(&fltr(length: 4))
# => ['test']
#get - get object attribute values
['test', 'me', 'please'].map(&get(:upcase, :length))
# => [['TEST', 4], ['ME', 2'], ['PLEASE', 6]]
#call - call methods on object
['test', 'me', 'please'].map(&call(gsub: ['e', '*']))
# => ['t*st', 'm*', 'pl*as*']
#set - set object attribute values
S = Struct.new(:name)
arr = [S.new('test'), S.new('me')]
arr.each(&set(name: 'please'))
arr # => [#<struct S name="please">, #<struct S name="please">]
You can use the module as is:
['test', 'me', 'please'].select(&ProcMe.fltr(length: 4))
or include it and then use:
include ProcMe
['test', 'me', 'please'].select(&fltr(length: 4))
Instance Method Summary collapse
-
#call(*methods) ⇒ Proc
Constructs block, able to call methods on object.
-
#filter(attrs) ⇒ Proc
(also: #fltr)
Constructs block, able to check objects attribute values.
-
#get(*attrs) ⇒ Proc
Constructs block, able to receive attribute values from object.
-
#set(attrs) ⇒ Proc
Constructs block, able to set objects attribute values.
Instance Method Details
#call(*methods) ⇒ Proc
Constructs block, able to call methods on object
Use it like this:
some_array.each(&call(:method, other_method: [args]))
If you call only one method, block will return just a result of call for each object:
['test', 'me'].map(&call(sub: ['e', '*'])) # => ['t*st', 'm*']
If you call several methods, it would be array of results for each object:
['test', 'me'].map(&call(sub: ['e', '*'], index: 'e'))
# => [['t*st', 2], ['m*', 2]]
The latter example also shows that #call sends each method to object itself, not the result of previous method call.
115 116 117 118 119 120 121 122 |
# File 'lib/procme.rb', line 115 def call(*methods) h = methods.last.is_a?(Hash) ? methods.pop : {} hash = Hash[*methods.flat_map{|sym| [sym, []]}].merge(h) lambda do |o| ProcMe._singularize(hash.map{|k, v| o.send(k, *v)}) end end |
#filter(attrs) ⇒ Proc Also known as: fltr
Constructs block, able to check objects attribute values
Use it like this:
some_array.select(&fltr(attr: value, other_attr: other_value))
values are checked with #=== method, so you can do something like:
['some', 'strings'].select(&fltr(length: 3..5)) # => ['some']
or like this:
['other', 'strings'].select(&fltr(upcase: /^S/)) # => ['strings']
This approach has one gotcha:
# wrong
['some', 'strings'].select(&fltr(class: String)) # => []
# right
['some', 'strings'].select(&fltr(itself: String)) # => ['some', 'strings']
67 68 69 70 71 |
# File 'lib/procme.rb', line 67 def filter(attrs) lambda do |o| attrs.all?{|k, v| v === o.send(k)} # rubocop:disable Style/CaseEquality end end |
#get(*attrs) ⇒ Proc
Constructs block, able to receive attribute values from object
Use it like this:
some_array.map(&get(:attr, :other))
Extremely useful for sorting:
['John', 'Alice', 'jane'].sort_by(&get(:length, :downcase)
# => ['jane', 'John', 'Alice']
As with #call, ‘#get` returns array of results for several methods and one result for only one method (with is not very useful anyways, as `map(&get(:length))` is a full equivalent of `map(&:length)`).
143 144 145 146 147 |
# File 'lib/procme.rb', line 143 def get(*attrs) lambda do |o| ProcMe._singularize(attrs.map{|v| o.send(*v)}) end end |
#set(attrs) ⇒ Proc
Constructs block, able to set objects attribute values
Use it like this:
some_array.each(&set(attr: value))
84 85 86 87 88 89 |
# File 'lib/procme.rb', line 84 def set(attrs) lambda do |o| attrs.each{|k, v| o.send("#{k}=", v)} o end end |