[![Gem Version](https://badge.fury.io/rb/proc_extensions.png)](http://badge.fury.io/rb/proc_extensions) [![Build Status](https://travis-ci.org/dwhelan/proc_extensions.png?branch=master)](https://travis-ci.org/dwhelan/proc_extensions) [![Code Climate](https://codeclimate.com/github/dwhelan/proc_extensions/badges/gpa.svg)](https://codeclimate.com/github/dwhelan/proc_extensions) [![Coverage Status](https://coveralls.io/repos/dwhelan/proc_extensions/badge.svg?branch=master&service=github)](https://coveralls.io/github/dwhelan/proc_extensions?branch=master) ### ProcSource Class The gem includes the `ProcSource` class which provides access to the proc extensions without monkey patching the `Proc` class itself. You can create a `ProcSource` with either a proc as a parameter or by passing a block to `ProcSource`. ```ruby p = proc { |a| a.to_s } ps1 = ProcSource.new p ps2 = ProcSource.new { |b| b.to_s } ``` You can use the `raw_source` method to return the original source and the `source` method to return the *sanitized* version of the source. ```ruby ps1.source # => "proc { |a| a.to_s }" ps1.raw_source # => "proc { |a| a.to_s }" ps1.to_s # => "proc { |a| a.to_s }" ps1.inspect # => "proc { |a| a.to_s }" ps1 == ps2 # => false ps1.match ps2 # => true ``` You can create a `ProcSource` with no proc or with a `nil` proc and it will simply provide an empty string for `source` `raw_source`, `to_s` and `inspect`. And two `ProcSource` objects created like this will be considered equal. ```ruby ps1 = ProcSource.new ps2 = ProcSource.new nil ps1.source # => "" ps1.raw_source # => "" ps1.to_s # => "" ps1.inspect # => "" ps1 == ps2 # => true ps1.match ps2 # => true ``` # Proc Extensions Extensions to Proc support source extraction and comparison. Optionally methods can be added to the `Proc` class: * `inspect`: returns source code if it can be extracted * `source`, `raw_source`: returns source code * `==`: determines if two procs have exactly the same source code * `match`, `=~`: determines if two procs have the source code allowing for different parameter names The above methods are not automatically included into the `Proc` class. You need to explicitly include modules included in this gem. **Note** This gem uses the [sourcify](https://github.com/ngty/sourcify) gem to extact proc source code. The `sourcify` gem is no longer supported although it works as needed for the `proc_extensions` gem. ## Installation Add this line to your application's Gemfile: ```ruby gem 'proc_extensions' ``` And then execute: $ bundle Or install it yourself as: $ gem install proc_extensions ## Usage ``` require proc_extensions ``` ### Extensions to the Proc class #### inspect Method The `inspect` methods is added to `Proc` when `ProcExtensions::Inspect` is included with `Proc`: ```ruby Proc.include ProcExtensions::Inspect # Ruby 2 Proc.send :include, ProcExtensions::Inspect # Ruby 1.9.3 ``` The `inspect` method will return the source code for the proc. ```ruby p = proc { |a| a.to_s } l = lambda { |a| a.to_s } p.inspect # => "proc { |a| a.to_s }" l.inspect # => "lambda { |a| a.to_s }" ``` If the source code cannot be extracted then the original `Proc#inspect` method will be called: ```ruby # Can't get source if multiple procs declared on the same line p = proc { proc {} } p.inspect # => "#" ``` #### source Methods The `source` and `raw_source` methods are added to `Proc` when `ProcExtensions::Source` is included with `Proc`: ```ruby Proc.include ProcExtensions::Source # Ruby 2 Proc.send :include, ProcExtensions::Source # Ruby 1.9.3 ``` The `Proc#source` method will return the source code for the Proc with white space and comments removed. The `raw_source` method will return the original source. ```ruby p = proc { | a | a.to_s } p.source # "proc { |a| a.to_s }" p.raw_source # "proc { | a | a.to_s }" ``` Lambda source will have the prefix 'lambda' rather than 'proc': ```ruby l = lambda { |a| a.to_s } l.source # "lambda { |a| a.to_s }" ``` If the source cannot be extracted then an exception will be raised by the `sourcify` gem. #### match Methods The `match` and `=~` methods are added to `Proc` when `ProcExtensions::Match` is included with `Proc`: ```ruby Proc.include ProcExtensions::Match # Ruby 2 Proc.send :include, ProcExtensions::Match # Ruby 1.9.3 ``` The `match(other)` method will return `true` if the procs are the same proc or if the two procs have the same source code. The `=~` method is created as an alias for `match`. ```ruby proc1 = proc {} proc2 = proc {} proc3 = proc { |a| a.to_s } proc1.match(proc2) # => true proc1.match(proc3) # => false proc1 =~ proc2 # => true proc1 =~ proc3 # => false ``` The source code for two procs are considered equal if they have the same body even with different parameter names: ```ruby proc1 = proc { |a| a.to_s } proc2 = proc { |b| b.to_s } proc1.match(proc2) # => true ``` If the procs are created via `&:method` then they will be considered equal if they reference the same method: ```ruby proc1 = proc(&:to_s) proc2 = proc(&:to_s) proc3 = proc(&:to_a) proc1.match(proc2) # => true proc1.match(proc3) # => false ``` If the source code cannot be extracted from either proc then `false` will be returned: ```ruby # Can't get source if multiple procs declared on the same line proc1 = proc { proc {} } proc2 = proc { proc {} } proc1.match(proc2) # => false ``` ## Ruby Versions Supported * 1.9.3 * 2.0 * 2.1 * 2.2 ## Development To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/dwhelan/proc_extensions. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct. ## License The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).