active_helper 0.2.0 → 0.2.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
@@ -10,10 +10,10 @@ Helpers suck. They've always sucked, and they will suck on if we keep them in mo
10
10
  ActiveHelper is an attempt to pack helpers into *classes*. This brings us a few benefits
11
11
 
12
12
  * *inheritance* helpers can be derived other helpers
13
- * *delegation* helpers are no longer mixed into a target- the targets @use@ the helper, where the new
13
+ * *delegation* helpers are no longer mixed into a target- the targets @import@ the helper, where the new
14
14
  methods are _delegated_ to the helper instances
15
15
  * *proper encapsulation* helpers don't rely blindly on instance variables - a helper defines its @needs@, the target has to provide readers
16
- * *interfaces* a helper clearly @provides@ methods and might @use@ additional helpers
16
+ * *interfaces* a helper clearly @provides@ methods and might @import@ additional helpers
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
 
@@ -38,12 +38,14 @@ The view wants to render tags using the TagHelper.
38
38
  <pre>
39
39
  class View
40
40
  include ActiveHelper
41
+ import TagHelper
41
42
  end
42
43
 
43
- > view.use TagHelper
44
44
  </pre>
45
45
 
46
- To pull-in ("import") a helper we invoke @use@ on the target instance.
46
+ To pull-in a helper we invoke @import@ in the target class.
47
+
48
+ Note that you can also use @import@ on an object to limit the helper's scope to that instance, only.
47
49
 
48
50
 
49
51
  h3. Interfaces
@@ -84,7 +86,7 @@ end
84
86
  That's _a bit_ cleaner than blindly including 30 helper modules in another helper in another helper, isn't it?
85
87
 
86
88
  <pre>
87
- > view.use FormHelper
89
+ > view.import FormHelper
88
90
  > view.tag(:form) # => "<form>"
89
91
  > view.form('apotomo.de') # => "<form action=apotomo.de>"
90
92
  </pre>
@@ -109,7 +111,7 @@ In ActiveHelper this is slightly different.
109
111
  <pre>
110
112
  class FormHelper < TagHelper
111
113
  provides :form_tag
112
- uses UrlHelper
114
+ import UrlHelper
113
115
 
114
116
  def form_tag(destination)
115
117
  destination = url_for(destination) # in UrlHelper.
@@ -120,9 +122,9 @@ end
120
122
 
121
123
  Hmm, our _FormHelper_ is already derived from _ActiveHelper_, how do we import additional methods?
122
124
 
123
- Easy as well, the helper class @uses@ it.
125
+ Easy as well, the helper class @import@s it.
124
126
 
125
- So we have to know _#url_for_ is located in the _UrlHelper_ and we even have to declare our helper @uses@ another one.
127
+ So we have to know _#url_for_ is located in the _UrlHelper_ and we even have to @import@ that one.
126
128
  That's a good thing for a) *code tidiness*, b) *good architecture* and c) *debugging*.
127
129
 
128
130
  How would the _UrlHelper_ look like?
@@ -183,10 +185,41 @@ Now, does it work?
183
185
 
184
186
  Yeah.
185
187
 
188
+ h2. Rails Bindings
189
+
190
+ Use ActiveHelper in your Rails app! Assuming you'd be writing a helper for text munging, you would
191
+
192
+ 1. Write your helper and put it in @app/active_helpers/text_munging_helper.rb@.
193
+
194
+ <pre>
195
+ class TextMungingHelper < ActiveHelper::Base
196
+ provides :munge
197
+
198
+ def munge(text)
199
+ text.rot13
200
+ end
201
+ end
202
+ </pre>
203
+
204
+ 2. Prepare your controller.
205
+
206
+ <pre>
207
+ class StupidController < ActionController::Base
208
+ active_helper TextMungingHelper
209
+ </pre>
210
+
211
+ 3. Use the imported methods in your views, just as you know it from other helpers.
212
+
213
+ <pre>
214
+ <p>
215
+ Your Email is <%= munge @user.email %>.
216
+ </p>
217
+ </pre>
218
+
219
+
186
220
  h2. Concepts
187
221
  * Helpers are instances, when accessing a raw @@ivar@ it refers to their own instance variables
188
222
  * Dependencies between different helpers and between the target (e.g. a _View_ instance) are modelled with OOP strategies: Inheritance and the declarative @#needs@.
189
- * Naturally helpers can @use@ other helpers on instance level, a helper class @uses@ supporting helpers.
190
223
 
191
224
  h2. License
192
225
 
data/Rakefile CHANGED
@@ -2,7 +2,7 @@
2
2
  require 'rake'
3
3
  require 'rake/testtask'
4
4
  require 'rake/rdoctask'
5
- require File.join(File.dirname(__FILE__), 'lib', 'active_helper', 'version')
5
+ require File.join(File.dirname(__FILE__), 'lib', 'active_helper')
6
6
 
7
7
  desc 'Default: run unit tests.'
8
8
  task :default => :test
data/lib/active_helper.rb CHANGED
@@ -1,8 +1,11 @@
1
+ gem 'activesupport', '~>2.3'
1
2
  require 'active_support'
2
3
  require 'forwardable'
3
4
 
4
5
 
5
6
  module ActiveHelper
7
+ VERSION = '0.2.1'
8
+
6
9
  module GenericMethods
7
10
  def use_for(classes, target)
8
11
  classes.each do |helper_class|
@@ -44,10 +47,36 @@ module ActiveHelper
44
47
  #
45
48
  # view = View.new
46
49
  # view.use UrlHelper, DataMapperHelper
47
- def use (*classes)
50
+ def import(*classes)
48
51
  setup_delegator_strategy!
49
52
  use_for(classes, self)
50
53
  end
54
+ alias_method :use, :import
55
+
56
+ module ClassMethods
57
+ include GenericMethods
58
+
59
+ # Imports the provided methods from +classes+ into the target (the receiver).
60
+ # All imported helper methods in the target will be delegated back to the helpers.
61
+ #
62
+ # Example:
63
+ # class View
64
+ # uses UrlHelper, DataMapperHelper
65
+ # end
66
+ def import(*classes)
67
+ setup_delegator_strategy!
68
+ use_for(classes, self)
69
+ end
70
+
71
+ protected
72
+ def setup_delegator_strategy!
73
+ extend Forwardable
74
+ end
75
+ end
76
+
77
+ def self.included(base)
78
+ base.extend ClassMethods
79
+ end
51
80
  end
52
81
 
53
82
  require 'active_helper/base'
@@ -60,9 +60,10 @@ module ActiveHelper
60
60
  use_class_helpers!
61
61
  end
62
62
 
63
- def use(*classes)
63
+ def import(*classes)
64
64
  use_for(classes, parent) # in GenericMethods.
65
65
  end
66
+ alias_method :use, :import
66
67
 
67
68
  protected
68
69
  # Delegates methods declared with #needs back to parent.
@@ -19,7 +19,7 @@ class ActionController::Base
19
19
 
20
20
  def initialize_template_class_with_active_helper(response)
21
21
  initialize_template_class_without_active_helper(response)
22
- response.template.use *self.class.active_helpers
22
+ response.template.import *self.class.active_helpers
23
23
  end
24
24
 
25
25
  alias_method_chain :initialize_template_class, :active_helper
@@ -39,12 +39,12 @@ class ActiveHelperTest < Test::Unit::TestCase
39
39
  should "delegate the method to the parent when called" do
40
40
  @helper_class.instance_eval { needs :bottle }
41
41
  @helper = @helper_class.new(@target)
42
- @target.use @helper.class
42
+ @target.import @helper.class
43
43
 
44
44
  assert_equal "cheers!", @helper.bottle
45
45
  end
46
46
 
47
- # DiningHelper.use GreedyHelper
47
+ # DiningHelper.import GreedyHelper
48
48
  #
49
49
  # GreedyHelper
50
50
  # needs :bottle
@@ -56,14 +56,14 @@ class ActiveHelperTest < Test::Unit::TestCase
56
56
  @greedy_class.instance_eval { needs :bottle }
57
57
 
58
58
  @dining = helper_mock(@target)
59
- @dining.use @greedy_class
59
+ @dining.import @greedy_class
60
60
 
61
61
  assert_equal 'cheers!', helper_in(@greedy_class, @dining).bottle
62
62
  end
63
63
  end
64
64
  end
65
65
 
66
- context "With #parent_readers and #uses," do
66
+ context "With #parent_readers and #import," do
67
67
  setup do
68
68
  @target = Object.new
69
69
  @target.class.instance_eval { include ::ActiveHelper }
@@ -131,29 +131,29 @@ class ActiveHelperTest < Test::Unit::TestCase
131
131
 
132
132
  context "On a Helper" do
133
133
  setup do
134
- assert_respond_to ::ActiveHelper::Base, :uses
134
+ assert_respond_to ::ActiveHelper::Base, :import
135
135
  @helper = Class.new(::ActiveHelper::Base).new
136
- assert_respond_to @helper.class, :uses
136
+ assert_respond_to @helper.class, :import
137
137
  assert ! @helper.respond_to?(:eat)
138
138
 
139
139
 
140
140
  end
141
141
 
142
- context "#use" do
142
+ context "#import" do
143
143
  should "delegate the new Helper methods" do
144
- @helper.use GreedyHelper
144
+ @helper.import GreedyHelper
145
145
  assert_respond_to @helper, :eat
146
146
  end
147
147
 
148
148
  should "set @parent => @target in the used Helper" do
149
149
  @target = Object.new
150
150
  @helper = Class.new(::ActiveHelper::Base).new(@target)
151
- @helper.use GreedyHelper
151
+ @helper.import GreedyHelper
152
152
  assert_equal @target, helper_in(GreedyHelper, @helper).parent # parent of used handler is target, not the using handler!
153
153
  end
154
154
 
155
155
  should "accept multiple helper classes" do
156
- @helper.use GreedyHelper, ThirstyHelper
156
+ @helper.import GreedyHelper, ThirstyHelper
157
157
  assert_respond_to @helper, :eat
158
158
  assert_respond_to @helper, :drink
159
159
  assert_respond_to @helper, :booze
@@ -161,7 +161,7 @@ class ActiveHelperTest < Test::Unit::TestCase
161
161
 
162
162
  should "accept empty helpers with no methods" do
163
163
  @empty_helper = helper_mock
164
- @helper.use @empty_helper.class
164
+ @helper.import @empty_helper.class
165
165
  assert helper_in(@empty_helper.class, @helper)
166
166
  end
167
167
 
@@ -196,14 +196,14 @@ class ActiveHelperTest < Test::Unit::TestCase
196
196
  end
197
197
 
198
198
  should "respond to the new delegated Helper methods" do
199
- @helper.class.uses GreedyHelper
199
+ @helper.class.import GreedyHelper
200
200
  assert_respond_to @helper.class.new, :eat
201
201
  end
202
202
 
203
203
  should "inherit helper methods to ancestors" do
204
204
  class DiningHelper < ::ActiveHelper::Base
205
205
  provides :drink
206
- uses GreedyHelper
206
+ import GreedyHelper
207
207
 
208
208
  def drink;end
209
209
  end
@@ -219,50 +219,44 @@ class ActiveHelperTest < Test::Unit::TestCase
219
219
  setup do
220
220
  @target_class = Class.new(Object) # don't pollute Object directly.
221
221
  @target_class.instance_eval { include ::ActiveHelper }
222
- assert_respond_to @target_class, :use
222
+ assert_respond_to @target_class, :import
223
223
 
224
224
  @target = @target_class.new
225
225
  assert ! @target.respond_to?(:eat)
226
226
  end
227
227
 
228
- context "#use" do
228
+ context "#import" do
229
229
  should "delegate new delegated helper methods" do
230
- @target.use GreedyHelper
230
+ @target.import GreedyHelper
231
231
  assert_respond_to @target, :eat
232
232
  end
233
233
 
234
234
  should "set @parent => @target in the used Helper" do
235
- @target.use GreedyHelper
235
+ @target.import GreedyHelper
236
236
  assert_equal @target, helper_in(GreedyHelper, @target).parent
237
237
  end
238
238
 
239
239
  should "accept multiple helper classes" do
240
- @target.use GreedyHelper, ThirstyHelper
240
+ @target.import GreedyHelper, ThirstyHelper
241
241
  assert_respond_to @target, :eat
242
242
  assert_respond_to @target, :drink
243
243
  assert_respond_to @target, :booze
244
244
  end
245
245
  end
246
246
 
247
- #context "#uses" do
248
- # should "delegate new delegated helper methods" do
249
- # @target.class.uses GreedyHelper
250
- # assert_respond_to @target, :eat
251
- # end
252
- #
253
- # should "inherit helper methods to non-helper class" do
254
- # class DiningHelper < ::ActiveHelper::Base
255
- # provides :drink
256
- # uses GreedyHelper
257
- #
258
- # def drink;end
259
- # end
260
- #
261
- # @helper = Class.new(DiningHelper).new
262
- # assert_respond_to @helper, :eat # from uses GreedyHelper.
263
- # assert_respond_to @helper, :drink # from DiningHelper inheritance.
264
- # end
265
- #end
247
+ context "Class#import" do
248
+ should "delegate helper methods" do
249
+ @target.class.import GreedyHelper
250
+ assert_respond_to @target, :eat
251
+ end
252
+
253
+ should "accept multiple helper classes" do
254
+ @target.class.import GreedyHelper, ThirstyHelper
255
+ assert_respond_to @target, :eat
256
+ assert_respond_to @target, :drink
257
+ assert_respond_to @target, :booze
258
+ end
259
+ end
266
260
  end
267
261
 
268
262
  context "#ivar_name_for" do
data/test/rails_test.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
+ gem 'actionpack', '~>2.3'
3
4
  require 'action_controller'
4
5
  require 'action_view'
5
6
  require 'active_helper/rails' # usually happens in active_helper.rb
metadata CHANGED
@@ -1,12 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_helper
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 0
9
- version: 0.2.0
4
+ version: 0.2.1
10
5
  platform: ruby
11
6
  authors:
12
7
  - Nick Sutterer
@@ -14,23 +9,19 @@ autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
11
 
17
- date: 2010-04-10 00:00:00 +02:00
12
+ date: 2010-06-17 00:00:00 +02:00
18
13
  default_executable:
19
14
  dependencies:
20
15
  - !ruby/object:Gem::Dependency
21
16
  name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
24
20
  requirements:
25
21
  - - ">="
26
22
  - !ruby/object:Gem::Version
27
- segments:
28
- - 2
29
- - 3
30
- - 0
31
23
  version: 2.3.0
32
- type: :runtime
33
- version_requirements: *id001
24
+ version:
34
25
  description: Finally - helpers with proper encapsulation, delegation, interfaces and inheritance!
35
26
  email: apotonick@gmail.com
36
27
  executables: []
@@ -45,7 +36,6 @@ files:
45
36
  - lib/active_helper.rb
46
37
  - lib/active_helper/base.rb
47
38
  - lib/active_helper/rails.rb
48
- - lib/active_helper/version.rb
49
39
  - rails/init.rb
50
40
  - test/active_helper_test.rb
51
41
  - test/helpers/helpers.rb
@@ -64,20 +54,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
64
54
  requirements:
65
55
  - - ">="
66
56
  - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
57
  version: "0"
58
+ version:
70
59
  required_rubygems_version: !ruby/object:Gem::Requirement
71
60
  requirements:
72
61
  - - ">="
73
62
  - !ruby/object:Gem::Version
74
- segments:
75
- - 0
76
63
  version: "0"
64
+ version:
77
65
  requirements: []
78
66
 
79
67
  rubyforge_project:
80
- rubygems_version: 1.3.6
68
+ rubygems_version: 1.3.5
81
69
  signing_key:
82
70
  specification_version: 3
83
71
  summary: Finally - helpers with proper encapsulation, delegation, interfaces and inheritance!
@@ -1,5 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ActiveHelper
4
- VERSION = '0.2.0'
5
- end