Skip to content

Commit

Permalink
Expand README with examples and background
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Caudill committed Jan 16, 2010
1 parent a15305d commit 3df23bb
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 25 deletions.
25 changes: 0 additions & 25 deletions README.markdown

This file was deleted.

69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
LetItBe
=======

_Copying over instance variables is bad, mmm-kay?_

LetItBe helps you program to an interface, rather than an implementation in
your Rails controllers.

The fact of the matter is that sharing state via instance variables in
controllers promotes close coupling with views. LetItBe gives you a
declarative manner of exposing an interface to the state that controllers
contain and thereby decreasing coupling and improving your testability and
overall design.

The Particulars
---------------

`let` creates a method with the given name, evaluates the provided block (or
intuits a value when no block is passed) and memoizes the result. This method is
then declared as a `helper_method` so that views may have access to it and is
made unroutable as an action with `hide_action`.

Examples
--------

When no block is given, `let` attempts to intuit which resource you want to
acquire:

# Category.find(params[:category_id] || params[:id])
let(:category)

As the example shows, the symbol passed is used to guess the class name of the
object you want an instance of. Almost every controller has one of these. In the
RESTful controller paradigm, you might use this in `#show`, `#edit`, `#update`
or `#destroy`.

In the slightly more complicated scenario, you need to find an instance of an
object which doesn't map cleanly to `Object#find`:

let(:product){ category.products.find(params[:id]) }

In the RESTful controller paradigm, you'll again find yourself using this in
`#show`, `#edit`, `#update` or `#destroy`.

When the code has become complex enough to surpass a single line (and is not
appropriate to extract into a model method), use the `do...end` style of block:

let(:associated_products) do
product.associated.tap do |associated_products|
present(associated_products, :with => AssociatedProductPresenter)
end
end

Beware
------

This is an exceptionally simple tool, which provides a solitary solution. It
must be used in conjunction with solid design approaches ("Program to an
interface, not an implementation.") and accepted best practices (e.g. Fat Model,
Skinny Controller). In itself, it won't heal a bad design. It is meant only to
be a tool to use in improving the overall design of a Ruby on Rails system and
moreover to provide a standard implementation for an emerging best practice.

Documentation TODO
------------------

* Add an open-source license
* walk-through explanation of the actual implementation (using an existing,
popular OSS Rails app as an example for the refactor).

0 comments on commit 3df23bb

Please sign in to comment.