This memoized patterns happens all over the place. One example is in inherited_resources:
I have some similar code, but since I am working on a pure web service project, I'm not actually using any assigns. But the technique is similar. inherited_resource calls out methods that are sensible defaults most of the time. To customize it, you would override one of several of the hooks, such as object, collection, end_of_association_chain. But this looks a lot nicer using the let() syntax:
class ProjectsController < InheritedResources::Base
protected
def collection
@projects ||= end_of_association_chain.paginate(:page => params[:page])
end
end
class ProjectsController < InheritedResources::BaseAnd then I dropped this into app/concerns. This was actually extracted from my (working) Rails 3 web services project:
include Let
let(:collection) { @projects ||= end_of_association_chain.paginate(:page => params[:page]) }
end
# http://gist.github.com/453389I stole this from Rspec 2, then ripped out the documentation and refactored it using ActiveSupport::Concern. I added a line to make the let() bindings protected so it won't show up as an action for the controller. This is probably the behavior you'd want in non-controller anyways.
module Let
extend ActiveSupport::Concern
included do
extend Let::ClassMethods
end
private
def __memoized # :nodoc:
@__memoized ||= {}
end
module ClassMethods
def let(name, &block)
define_method(name) do
__memoized[name] ||= instance_eval(&block)
end
protected(name)
end
end
end
The neatest thing I had found about let() in Rspec was easily making an implicit DSL inside my spec. The fact that I can carry this over to my controller is simply too cool not to share.
Perhaps you would be interested in
ReplyDeletehttp://github.com/voxdolo/decent_exposure <--
Good on you for discovering this yourself though :)
How is replacing "protected" with "include Let", "def collection" with "let(:collection) { " and "end" with "}" a lot nicer?
ReplyDelete@rbxbx I've been using inherited_resources before Rails 2 but it's getting crufty. I'll check out decent_exposure.
ReplyDeleteDoes the expose declaration do an "assign"? Since writing this article, I've been using "assign", but as some of the other folks in the ATLRUG meetup have pointed out to me, it gets confusing with "#assigns".