davearonson/hook_lying_syncer

View on GitHub
README.md

Summary

Maintainability
Test Coverage
hook_lying_syncer
=================

[![Code Climate](https://codeclimate.com/github/davearonson/hook_lying_syncer/badges/gpa.svg)](https://codeclimate.com/github/davearonson/hook_lying_syncer)
[![Test Coverage](https://codeclimate.com/github/davearonson/hook_lying_syncer/badges/coverage.svg)](https://codeclimate.com/github/davearonson/hook_lying_syncer/coverage)
[![Build Status](https://travis-ci.org/davearonson/hook_lying_syncer.png)](https://travis-ci.org/davearonson/hook_lying_syncer)

This project presents a way for Ruby coders to keep ```method_missing``` and
```respond_to_missing?``` in sync.

## Background

The whole idea of finding a way to automagically keep ```method_missing``` and
```respond_to_missing?``` in sync, was originally inspired by [Avdi
Grimm](http://about.avdi.org/)'s [blog
post](http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/)
about the need to sync them.  I came up with a quick and dirty hack, and a
still-hacky improvement that seems to have been mangled by a blog platform
change or some such.

Then at RubyConf 2014, [Betsy Haibel](http://betsyhaibel.com/) gave a talk on
metaprogramming, including the need.  That inspired me to take another whack at
it, this time using the different approach shown in this repo (essentially, a
decorator class).

I got some suggestions and other help from [Chris
Hoffman](https://github.com/yarmiganosca), mainly in figuring out that I
shouldn't do the in-block object access the way I was trying to!  :-)


## Caveats

This requires the Ruby version to be at least 1.9.  Eventually I might put some
work into figuring out why many tests fail with 1.8, but for now, call it a
Ruby 1.9+ gem.  Check [its Travis CI status
page](https://travis-ci.org/davearonson/hook_lying_syncer) to see which
versions of Ruby it has been tested against; currently that's 1.9.2, 1.9.3,
2.0.0, 2.1.0, 2.1.1, 2.1.2, JRuby in 1.9 mode, and Rubinius 2.1.1.


## Installation

Add this line to your application's Gemfile:

```ruby
gem 'hook_lying_syncer'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install hook_lying_syncer



## Usage

Create a HookLyingSyncer by passing it something to wrap, a lambda to extract
the the subparts of interest from a method name (passed to ```method_missing```
or ```respond_to_missing?```), and a block to execute when there are matches.

* The "something to wrap" can be any object, even a class.  Note however that
  if you wrap a class, that will not affect its instances!  You can affect
  future instances by using a wrapper to override .new, but if you need to
  affect _extant_ instances, you have to wrap them yourself.

* The lambda must return an Array with some truthy content (or at least
  _something_ that responds positively to #any?) if the method name is one
  you're interested in, and either an empty Array (or at least _something_ that
  responds negatively to #any?) or something falsey (i.e., false or nil)
  otherwise.  If you are not comfortable making lambdas, feel free to copy the
  lambda_maker method in the tests.

* The block will be called when the lambda indicates that a method of interest
  has been called.  The block will receive three arguments: the original object
  the HookLyingSyncer wrapped, the matches returned by the lambda, and the list
  of arguments (if any) passed in the method call.

See the tests for examples.

Also, please remember, just because you *can* use this, doesn't mean you
*should*!  Ask your doctor if metaprogramming is right for you.  Side effects
may include difficulty debugging and loss of greppability.


## Changes

| Version | Change |
|---|---|
| 0.0.1 | Initial release |
| 0.0.2 | Better compatibility w/ 1.9; declare 1.8 incompatible in README |
| 0.0.3 | Declare 1.8 incompatible in gemspec (duh!) |
| 0.0.4 | Fix poorly written dependency versions in gemspec |


## Contributing

1. Fork it ( https://github.com/davearonson/hook_lying_syncer/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request