Skip to content
Browse files

adding support for standard component options. see readme for more.

  • Loading branch information...
1 parent 2c77ecb commit 170bd3ba566d34a72ae03d6e8b9cd67e958e64da @cainlevy cainlevy committed May 14, 2008
Showing with 58 additions and 0 deletions.
  1. +32 −0 README
  2. +23 −0 lib/components.rb
  3. +3 −0 lib/components/base.rb
View
32 README
@@ -67,6 +67,38 @@ Assume two components:
Both methods on the ChildComponent class would first try and render "/app/components/child/one.erb", and if that file did not exist, would render "/app/components/parent/one.erb".
+=== Standard Argument Options
+
+You may find yourself constantly needing to pass a standard set of options to each component. If so, you can define a method on your controller that returns a hash of standard options that will be merged with the component arguments and passed to every component.
+
+Suppose a given component:
+
+ class GroupsComponent < Components::Base
+ def details(group_id, options = {})
+ @user = options[:user]
+ @group = Group.find(group_id)
+ render
+ end
+ end
+
+Then the following setup:
+
+ class GroupsController < ApplicationController
+ def show
+ render :text => component("groups/details", params[:id])
+ end
+
+ protected
+
+ def standard_component_options
+ {:user => current_user}
+ end
+ end
+
+Would expand to:
+
+ component("groups/details", params[:id], :user => current_user)
+
== Components Philosophy
I wrote this components plugin after evaluating a couple of existing ones, reflecting a bit, and either stealing or composing the following principles. I welcome all debate on the subject.
View
23 lib/components.rb
@@ -6,7 +6,16 @@ def self.render(name, component_args = [], options = {})
component.send(method, *component_args).to_s
end
+ def self.merge_standard_component_options!(args, standard_options)
+ if standard_options
+ args << {} unless args.last.is_a?(Hash)
+ args.last.reverse_merge!(standard_options)
+ end
+ end
+
module ActionController
+ protected
+
# Renders the named component with the given arguments. The component name must indicate both
# the component class and the class' action.
#
@@ -26,8 +35,21 @@ module ActionController
# end
# end
def component(name, *args)
+ Components.merge_standard_component_options!(args, standard_component_options)
Components.render(name, args, :form_authenticity_token => (form_authenticity_token if protect_against_forgery?))
end
+
+ # Override this method on your controller (probably your ApplicationController)
+ # to define common arguments for your components. For example, you may always
+ # want to provide the current user, in which case you could return {:user =>
+ # current_user} from this method.
+ #
+ # In order to use this, your component actions should accept an options hash
+ # as their last argument.
+ #
+ # I feel like this is a better solution than simply making request and
+ # session details directly available to the components.
+ def standard_component_options; end
end
module ActionView
@@ -48,6 +70,7 @@ module ActionView
# end
# end
def component(name, *args)
+ Components.merge_standard_component_options!(args, controller.send(:standard_component_options))
Components.render(name, args, :form_authenticity_token => (form_authenticity_token if protect_against_forgery?))
end
end
View
3 lib/components/base.rb
@@ -36,6 +36,9 @@ def logger #:nodoc:
protected
+ # See Components::ActionController#standard_component_options
+ def standard_component_options; end
+
# When the string your component must return is complex enough to warrant a template file,
# this will render that file and return the result. Any template engine (erb, haml, etc.)
# that ActionView is capable of using can be used for templating.

0 comments on commit 170bd3b

Please sign in to comment.
Something went wrong with that request. Please try again.