active_helper 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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