Giter Club home page Giter Club logo

methodchain's Introduction

== Summary
methodchain - ruby helpers for method chaining: chain, tap, then, else, and, or
===
Easy ways to navigate around nil without creating local variables.
===
Initial blog post describing previous ideas:
http://blog.thoughtfolder.com/2008-03-16-navigating-nil-method-chaining-in-ruby.html

== Author and License
Copyright (c) 2008 Greg Weber, http://gregweber.info
Licensed under the MIT license

== Examples
=== ##then and ##else
==== old way
  person = nil
  name = person ? person.name : nil

==== new way
  name = person.then {|p| p.name}
  # or
  name = person.then {name}

not a huge savings. But sometimes the person variable is actually a function call, and then we must save it in a variable first.

==== old way
  def find(*args)
    # do some expensive database queries
  end

  person = find(:first)
  @phone = person && person.phone   # => nil

==== new way
  @phone = find(:first).then {phone}   # => nil
  
We have reduced a line of code and removed a local variable.
##else is the opposite of #then, and the two methods can be used together

  'a'.then{'b'} #=> 'b'
  nil.then{'b'}.else{'c'} #=> 'c'

==== message sending
The normal conditional for ##then and ##else is self

  if self # inside MethodChain#then
    # evaluate block
  end

##then and ##else allow message sending as the conditional.  See more examples of message sending with the MethodChain#chain examples below

  "not empty".then(:empty?) {"N/A"} # => "not empty"
           "".then(:empty?) {"N/A"} # => "N/A"

=== ##and, ##or
==== old way
Return a default value or the original value depending on whether multiple conditions are met
  Person = Struct.new(:phone )
  blank = Person.new('') # or {:phone => nil}
  blank.phone && (not blank.phone.empty?) ? blank.phone : "N/A" # => "N/A"
  p = Person.new('123')
  p.phone && (not p.phone.empty?) ? p.phone : "N/A" # => "123"

==== new way
  blank.phone.and {not empty?} || "N/A" # => "N/A"
  p.phone.and {not empty?} || "N/A" # => "123"


=== ##tap
if you don't already know about this method, look it up on the net.  The tap included here allows message sending.

==== old way
  arr = [1]
  arr.compact! # => nil
  arr.first # => 1

==== normal ##tap (still valid)
  [1].tap {|arr| arr.compact!}.first # => 1

==== new ##tap
  [1].tap(:compact!).first # => 1

==== normal ##tap (still valid)
  [1].tap {|arr| arr.compact!}.tap {|arr| arr * 2}.first # => 1

==== new ##tap
  [1].tap( :compact!, [:*, 2] ).first # => 1

You can also pass Procs as arguments
  [1].tap( :compact!, lambda{|arr| arr * 2} ).first # => 1


=== ##chain
chain is like tap, but instead of always returning self, it will return the result of the method call.
  [1].chain(:first) == [1].first

But there is an important difference- chain guards against certain results (by default it guards against nil and false)

==== old way
  customer = nil
  customer && customer.order && customer.order.id

==== new way
  customer.chain(:order, :id)
 
note that this is equivalent to

  customer.then {order}.then {id}

=== ##chain - Custom guards, multiple arguments, and Procs
==== old way - guarding against zero
  value = 0

  result = if value == 0 then value else
    tmp = value.abs

    if tmp == 0 then tmp else
      tmp * 20
    end
  end
  result # => 0

==== new way
  value.chain(:abs, [:*, 20]) {|s| s == 0 }   # => 0

Procs can be used, so this is equivalent to
  value.chain(:abs, lambda {|n| n * 20 }) {|s| s == 0 } # => 0

== Usage
  require 'rubygems'

=== import all MethodChain methods into Object

  require 'methodchain'

=== selectively import MethodChain methods

  require 'methodchain/not-included'

You can then include methodchain into selected classes, or you can use the module-import gem to include only certain methods

  gem install module-import

  require 'module-import'
  class Object
    import MethodChain, :chain  # I only want Object#chain
  end

import will still load all the private methods from the module:
- yield_or_eval
- send_as_function
- send_as_functions


== Implementation
There are no proxy objects and no use of method_missing- these are simply function calls, so it should be fast.

private methods:
* yield_or_eval: allows the two different block forms {|p| p.name} and {name}, where the first form yields self and the second form is called using instance_eval.
* send_as_function: allows symbols and arrays to be sent as messages, and calls yield_or_eval on Proc arguments
* send_as_functions:

  def send_arguments_as_functions *args
    args.each {|arg| send_as_function arg}
    self
  end

== Install
gem install methodchain

== Source
=== browser
http://github.com/gregwebs/methodchain/tree/master
=== repository
git clone git://github.com/gregwebs/methodchain.git

== Homepage
http://gregweber.info/projects/methodchain.html

== RDoc documentation
included with gem

methodchain's People

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.