active_helper 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.textile CHANGED
@@ -17,6 +17,13 @@ methods are _delegated_ to the helper instances
17
17
 
18
18
  Note that ActiveHelper is a generic helper framework. Not coupled to anything like Rails or Merb. Not providing any concrete helpers. Feel free to use clean helpers in _any_ framework (including Rails and friends)!
19
19
 
20
+ h2. Installation
21
+
22
+ <pre>
23
+ > gem install active_helper
24
+ </pre>
25
+
26
+
20
27
  h2. Example
21
28
 
22
29
  Let's use the bloody MVC-View example as we find in Rails or Merb (Sinatra, too?).
@@ -11,15 +11,39 @@ module ActiveHelper
11
11
 
12
12
  class << self
13
13
  # Add public methods to the helper's interface. Only methods listed here will
14
- # be used to expand the target.
14
+ # be imported into the target.
15
+ #
16
+ # Example:
17
+ # class UrlHelper < ActiveHelper::Base
18
+ # provides :url_for, :link_to
15
19
  def provides(*methods)
16
20
  helper_methods.push(*methods)
17
21
  end
18
22
 
23
+ # Define a dependency to another ActiveHelper. All provided methods by the needed
24
+ # helper will be imported into the helper that called needs.
25
+ #
26
+ # Example:
27
+ # class UrlHelper < ActiveHelper::Base
28
+ # needs TagHelper
29
+ #
30
+ # will import #tag into UrlHelper.
19
31
  def needs(*methods)
20
32
  parent_readers.push(*methods).uniq!
21
33
  end
22
34
 
35
+ # Define a dependency to methods in target. Calls to that methods will be delegated
36
+ # simply back to target.
37
+ #
38
+ # Note: This can also be used to call a helper method from a non-ActiveHelper, which
39
+ # was preliminary included in target.
40
+ #
41
+ # Example:
42
+ # class UrlHelper < ActiveHelper::Base
43
+ # uses controller
44
+ #
45
+ # will deletegate calls to #controller to target (i.e. the view instance that #use's
46
+ # UrlHelper).
23
47
  def uses(*classes)
24
48
  class_helpers.push(*classes).uniq!
25
49
  end
@@ -31,23 +55,24 @@ module ActiveHelper
31
55
 
32
56
  def initialize(parent=nil)
33
57
  @parent = parent
34
- extend SingleForwardable
35
- add_parent_readers!
36
- add_class_helpers!
58
+ setup_delegator_strategy! # in GenericMethods.
59
+ delegate_parent_readers!
60
+ use_class_helpers!
37
61
  end
38
62
 
39
- def use(helper_class)
40
- use_for(helper_class, parent) # in GenericMethods.
63
+ def use(*classes)
64
+ use_for(classes, parent) # in GenericMethods.
41
65
  end
42
66
 
43
67
  protected
44
68
  # Delegates methods declared with #needs back to parent.
45
- def add_parent_readers!
69
+ def delegate_parent_readers!
46
70
  return if @parent.blank? or self.class.parent_readers.blank?
47
- def_delegator(:@parent, self.class.parent_readers)
71
+ delegate_methods_to(self.class.parent_readers, :@parent) # in GenericMethods.
48
72
  end
49
73
 
50
- def add_class_helpers!
74
+ # Imports foreign methods from other use'd helpers.
75
+ def use_class_helpers!
51
76
  self.class.class_helpers.each { |helper| use helper }
52
77
  end
53
78
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module ActiveHelper
4
- VERSION = '0.1.0'.freeze
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/active_helper.rb CHANGED
@@ -4,20 +4,28 @@ require 'forwardable'
4
4
 
5
5
  module ActiveHelper
6
6
  module GenericMethods
7
- def use_for(helper_class, target)
8
- extend ::SingleForwardable
9
-
10
- helper_ivar_name = ivar_name_for(helper_class)
11
- helper_instance = helper_class.new(target)
12
-
13
- instance_variable_set(helper_ivar_name, helper_instance)
14
- helper_class.helper_methods.each do |meth|
15
- def_delegator helper_ivar_name, meth
7
+ def use_for(classes, target)
8
+ classes.each do |helper_class|
9
+ helper_ivar_name = ivar_name_for(helper_class)
10
+ helper_instance = helper_class.new(target)
11
+
12
+ instance_variable_set(helper_ivar_name, helper_instance)
13
+ delegate_methods_to(helper_class.helper_methods, helper_ivar_name)
16
14
  end
17
15
  end
18
16
 
19
17
  protected
20
- # Unique ivar name for the helper class in the expanding target.
18
+ def setup_delegator_strategy!
19
+ extend SingleForwardable
20
+ end
21
+
22
+ # Implements the actual delegation.
23
+ def delegate_methods_to(methods, ivar)
24
+ return if methods.blank?
25
+ def_delegators ivar, *methods
26
+ end
27
+
28
+ # Unique ivar name for the helper instance in the expanding target.
21
29
  def ivar_name_for(object)
22
30
  ('@__active_helper_'+("#{object.to_s}".underscore.gsub(/[\/<>@#:]/, ""))).to_sym
23
31
  end
@@ -25,10 +33,20 @@ module ActiveHelper
25
33
 
26
34
 
27
35
  include GenericMethods
28
- # Expands the target *instance* with the provided methods from +helper_class+ by delegating 'em back to a private helper
29
- # Expands only the helped instance itself, not the class.
30
- def use (helper_class)
31
- use_for(helper_class, self)
36
+ # Imports the provided methods from +classes+ into the target *instance* (the receiver).
37
+ # All new methods in the target will be delegated back to the helpers.
38
+ #
39
+ # Note: Imports only into the helped instance itself, not the class.
40
+ #
41
+ # Example:
42
+ # class View
43
+ # end
44
+ #
45
+ # view = View.new
46
+ # view.use UrlHelper, DataMapperHelper
47
+ def use (*classes)
48
+ setup_delegator_strategy!
49
+ use_for(classes, self)
32
50
  end
33
51
  end
34
52
 
@@ -1,6 +1,15 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  class ActiveHelperTest < Test::Unit::TestCase
4
+ class GreedyHelper < ::ActiveHelper::Base
5
+ provides :eat
6
+ end
7
+
8
+ class ThirstyHelper < ::ActiveHelper::Base
9
+ provides :drink, :booze
10
+ end
11
+
12
+
4
13
  def helper_mock(*args)
5
14
  Class.new(::ActiveHelper::Base).new(*args)
6
15
  end
@@ -136,7 +145,7 @@ class ActiveHelperTest < Test::Unit::TestCase
136
145
  assert_respond_to @helper.class, :uses
137
146
  assert ! @helper.respond_to?(:eat)
138
147
 
139
- class GreedyHelper < ::ActiveHelper::Base; provides :eat; end
148
+
140
149
  end
141
150
 
142
151
  context "#use" do
@@ -151,6 +160,20 @@ class ActiveHelperTest < Test::Unit::TestCase
151
160
  @helper.use GreedyHelper
152
161
  assert_equal @target, helper_in(GreedyHelper, @helper).parent # parent of used handler is target, not the using handler!
153
162
  end
163
+
164
+ should "accept multiple helper classes" do
165
+ @helper.use GreedyHelper, ThirstyHelper
166
+ assert_respond_to @helper, :eat
167
+ assert_respond_to @helper, :drink
168
+ assert_respond_to @helper, :booze
169
+ end
170
+
171
+ should "accept empty helpers with no methods" do
172
+ @empty_helper = helper_mock
173
+ @helper.use @empty_helper.class
174
+ assert helper_in(@empty_helper.class, @helper)
175
+ end
176
+
154
177
  end
155
178
 
156
179
  context "#uses" do
@@ -209,8 +232,6 @@ class ActiveHelperTest < Test::Unit::TestCase
209
232
 
210
233
  @target = @target_class.new
211
234
  assert ! @target.respond_to?(:eat)
212
-
213
- class GreedyHelper < ::ActiveHelper::Base; provides :eat; end
214
235
  end
215
236
 
216
237
  context "#use" do
@@ -223,6 +244,13 @@ class ActiveHelperTest < Test::Unit::TestCase
223
244
  @target.use GreedyHelper
224
245
  assert_equal @target, helper_in(GreedyHelper, @target).parent
225
246
  end
247
+
248
+ should "accept multiple helper classes" do
249
+ @target.use GreedyHelper, ThirstyHelper
250
+ assert_respond_to @target, :eat
251
+ assert_respond_to @target, :drink
252
+ assert_respond_to @target, :booze
253
+ end
226
254
  end
227
255
 
228
256
  #context "#uses" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-30 00:00:00 +02:00
12
+ date: 2010-04-01 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency