Permalink
Browse files

Allow Proc calls for the :from option.

  • Loading branch information...
1 parent 16db8ef commit 784e946928aea912fd9ff0537c544bbb43eff934 Michael Bleigh committed Jul 28, 2008
Showing with 37 additions and 7 deletions.
  1. +20 −2 README
  2. +15 −3 lib/action_controller/fetches.rb
  3. +1 −1 test/fetcher_test_helper.rb
  4. +1 −1 test/fetches_test.rb
View
@@ -1,11 +1,22 @@
-== Fetches ==
+= Fetches
Fetches is a simple extension to ActionController that allows you to DRY up your
model fetching with a simple, intuitive syntax. Rather than creating helpers or
manually finding records each time an action is processed, simply add a call to
'fetches' in your controller and it will take care of the rest.
-== Example ==
+== Installation
+
+Fetches is available as a gem as well as in traditional plugin format. To install
+as a gem, add this to your environment.rb:
+
+ config.gem 'mbleigh-fetches', :source => 'http://gems.github.com', :lib => "fetches"
+
+To install it as a traditional plugin:
+
+ script/plugin install git://github.com/mbleigh/fetches.git
+
+== Example
class UsersController < ApplicationController
fetches :user
@@ -26,6 +37,13 @@ It's very simple, and can also be extended to meet more complex demands, such as
author # equivalent to User.find_by_login(params[:user_id])
end
end
+
+You may also pass a Proc into the "from" option in order to fetch from
+a more complex set of requirements:
+
+ class UsersController < ApplicationController
+ fetches :user, :from => Proc.new{ |c| c.params[:user_id] || c.params[:id] }
+ end
The helper method generated memoizes (initializes once then doesn't make additional
calls to the database) and is available both in the controller and the view.
@@ -5,6 +5,10 @@ def self.included(base)
@@default_fetcher_options = { :using => "find",
:from => :id }
cattr_accessor :default_fetcher_options
+
+ def self.fetchers
+ read_inheritable_attribute(:fetchers) || write_inheritable_attribute(:fetchers, {})
+ end
# Automatically creates a helper method to fetch a memoized record based on
# a passed-in parameter.
@@ -21,10 +25,16 @@ def self.included(base)
# fetches :article
# end
#
+ # # Example with Proc-based 'from'
+ # class UsersController < ApplicationController
+ # fetches :user, :from => Proc.new{ |c| c.params[:user_id] || c.params[:id] }
+ # end
+ #
# Options:
#
# - +as+: the name of the helper method to generate (default is the model name)
- # - +from+: the parameter passed into the finder method (default is +:id+)
+ # - +from+: the parameter passed into the finder method (default is +:id+).
+ # May also be passed as a +Proc+ that evaluates against a controller argument.
# - +using+: the class method name to use as a finder (default is +"find"+)
#
# Default options may be specified by setting them in an initializer. Example:
@@ -34,15 +44,17 @@ def self.fetches(model_name, options = {})
method_name = options.delete(:as) || default_fetcher_options[:as] || model_name.to_s
finder = options.delete(:using) || default_fetcher_options[:using]
from = options.delete(:from) || default_fetcher_options[:from]
-
klass = self.respond_to?(:class_eval) ? self : self.metaclass
+ fetchers[method_name.to_sym] = from
klass.class_eval <<-EOS, __FILE__, __LINE__
def #{method_name}
if defined?(@#{method_name})
@#{method_name}
else
- @#{method_name} = #{model_name.to_s.classify}.#{finder.to_s}(params[#{from.inspect}])
+ fetcher = self.class.fetchers[:#{method_name}]
+ from = fetcher.is_a?(Proc) ? fetcher.call(self) : params[fetcher]
+ @#{method_name} = #{model_name.to_s.classify}.#{finder.to_s}(from)
end
end
EOS
@@ -7,7 +7,7 @@ def self.find(some_integer)
when 2
"two worked"
else
- raise ActiveRecord::RecordNotFound, "Couldn't find FetchTestModel with ID=#{some_integer.to_i}"
+ raise "Couldn't find FetchTestModel with ID=#{some_integer.to_i}"
end
end
@@ -20,6 +20,6 @@ def test_basics
controller.params = {:id => 2}
assert_equal "two worked", controller.fetch_test_model
controller.params = {:id => 3}
- assert_throws(ActiveRecord::RecordNotFound)
+ assert_throws(Exception)
end
end

0 comments on commit 784e946

Please sign in to comment.