active_helper 0.2.0 → 0.2.1

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