Created
December 5, 2011 22:17
-
-
Save avdi/1435647 to your computer and use it in GitHub Desktop.
Revisions
-
Avdi Grimm revised this gist
Dec 5, 2011 . 1 changed file with 18 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -76,3 +76,21 @@ def gross? result # => "yum" # Man for some reason I'm hungry for a sandwich now. # P.S. The number of keywords Ruby will let you also use as method # names is frankly a little shocking. Here's Object#if: class Object def if(predicate) if predicate.to_proc.(self) yield(self) else self end end end result = sandwich.if(:gross?){|s| s.contents.delete(:liver); s }.get_into_my_belly! result # => "yum" -
Avdi Grimm created this gist
Dec 5, 2011 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,78 @@ def maybe_a_sandwich nil end # Methods that might return nil are annoying. We want to write a nice # confident chain: result = nil result = maybe_a_sandwich.add_horseradish.get_into_my_belly! rescue $! result # => #<NoMethodError: undefined method `add_horseradish' for nil:NilClass> # But then we find out it might return nil and have to rewrite it with # special-case handling: class NoSandwich def method_missing(*) self end def to_s "I'm so hungry!" end end sandwich = (maybe_a_sandwich || NoSandwich.new) result = sandwich.add_horseradish.get_into_my_belly! result # => I'm so hungry! # It would be cool if we could just insert the special case into the # chain. class Object def when(matcher) if matcher === self then yield(self) else self end end end result = maybe_a_sandwich.when(nil){NoSandwich.new}.add_horseradish.get_into_my_belly! result # => I'm so hungry! # I can think of lots of other uses for this. Like a special case for # an empty collection: def sandwiches [] end result = begin sandwiches.when(->(c){c.empty?}){raise "Out of sandwiches!"}.each do |s| s.get_into_my_belly! end rescue $! end result # => #<RuntimeError: Out of sandwiches!> # Or a modifying filter: class Sandwich attr_accessor :contents def get_into_my_belly! "yum" end def gross? contents.include?(:liver) end end sandwich = Sandwich.new sandwich.contents = [:roast_beef, :swiss_chees, :liver] result = sandwich.when(->(s){s.gross?}){|s| s.contents.delete(:liver); s }.get_into_my_belly! result # => "yum" # Man for some reason I'm hungry for a sandwich now.