context_exposer 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +13 -1
- data/README.md +186 -16
- data/lib/context_exposer.rb +15 -0
- data/lib/context_exposer/base_controller.rb +67 -47
- data/lib/context_exposer/cached_resource_controller.rb +10 -0
- data/lib/context_exposer/integrations.rb +8 -0
- data/lib/context_exposer/integrations/base.rb +15 -0
- data/lib/context_exposer/integrations/key_filter.rb +30 -0
- data/lib/context_exposer/integrations/with_decent_exposure.rb +19 -0
- data/lib/context_exposer/integrations/with_decorates_before.rb +31 -0
- data/lib/context_exposer/integrations/with_instance_vars.rb +19 -0
- data/lib/context_exposer/macros.rb +17 -0
- data/lib/context_exposer/patch/decorates_before_rendering.rb +179 -0
- data/lib/context_exposer/rails_config.rb +3 -0
- data/lib/context_exposer/resource_controller.rb +30 -8
- data/lib/context_exposer/version.rb +1 -1
- data/lib/context_exposer/view_context.rb +1 -1
- data/spec/app/items_spec.rb +36 -0
- data/spec/app/posts_spec.rb +29 -1
- data/spec/context_exposer/expose_resource_spec.rb +51 -38
- data/spec/context_exposer/expose_spec.rb +11 -10
- data/spec/dummy/app/controllers/items_controller.rb +12 -0
- data/spec/dummy/app/controllers/posts_controller.rb +3 -4
- data/spec/dummy/app/views/items/index.html.erb +2 -0
- data/spec/dummy/app/views/items/show.html.erb +2 -0
- data/spec/dummy/app/views/posts/index.html.erb +2 -1
- data/spec/dummy/app/views/posts/show.html.erb +2 -1
- data/spec/dummy/config/initializers/context_exposer.rb +1 -0
- data/spec/dummy/config/routes.rb +1 -57
- data/spec/dummy/log/test.log +483 -0
- data/spec/dummy_spec_helper.rb +82 -0
- data/spec/spec_helper.rb +13 -1
- data/spec/support/decorators/base_decorator.rb +22 -0
- data/spec/support/decorators/item_decorator.rb +11 -0
- data/spec/support/decorators/post_decorator.rb +5 -0
- data/spec/support/models/base.rb +18 -0
- data/spec/support/models/base/clazz_methods.rb +29 -0
- data/spec/support/models/item.rb +9 -0
- data/spec/support/models/post.rb +5 -0
- metadata +38 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cff7846013a27d16f62e455b571af3336ea88531
|
4
|
+
data.tar.gz: d7b782a83befc4da2b8ffa9a145eff505734d303
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47926e8db084652454e11b10b82e949618809ed3a1b9141c98b5830dae93a5e771fe79aca837a7a1520062710b9c3fe5f4a7cf63366942048db414391b7e1f36
|
7
|
+
data.tar.gz: 191e35391a9271b9cc3a3dea8e2429fee8ebb0c6788ade0feb2f9c449303c280fc6bcf26c3d2bf3151db1dcc94db809fff341c87fcd9a91a0717a885785e7553
|
data/Gemfile
CHANGED
@@ -4,5 +4,17 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
gem 'rails', '>= 3.1'
|
7
|
+
gem "rspec", '>= 2.0', group: [:test, :development]
|
7
8
|
gem "rspec-rails", '>= 2.0', group: [:test, :development]
|
8
|
-
gem 'pry', group: [:development]
|
9
|
+
gem 'pry', group: [:development]
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'capybara', '>= 2.0'
|
13
|
+
gem 'spork-rails', '>= 3.0'
|
14
|
+
|
15
|
+
gem 'decent_exposure'
|
16
|
+
gem 'decorates_before_rendering', github: 'ohwillie/decorates_before_rendering'
|
17
|
+
|
18
|
+
# gem 'factory_girl_rails', '>= 3.0'
|
19
|
+
# gem 'database_cleaner', '>= 0.7'
|
20
|
+
end
|
data/README.md
CHANGED
@@ -7,6 +7,14 @@ No more pollution of the View with content helper methods or even worse, instanc
|
|
7
7
|
|
8
8
|
The Context object will by default be an instance of `ContextExposer::ViewContext`, but you can subclass this baseclass to add you own logic for more complex scenarios. This also allows for a more modular approach, where you can easily share or subclass logic between different view contexts. Nice!
|
9
9
|
|
10
|
+
The gem comes with integrations ready for easy migration or symbiosis with existing strategies (and gems), such as:
|
11
|
+
|
12
|
+
* exposing of instance variables (Rails default strategy)
|
13
|
+
* decent_exposure gem (expose methods)
|
14
|
+
* decorates_before_rendering gem (expose decorated instance vars)
|
15
|
+
|
16
|
+
For more on integration (and migration path) see below ;)
|
17
|
+
|
10
18
|
## Installation
|
11
19
|
|
12
20
|
Add this line to your application's Gemfile:
|
@@ -36,15 +44,44 @@ class PostsController < ActionController::Base
|
|
36
44
|
end
|
37
45
|
```
|
38
46
|
|
47
|
+
The view will have the methods exposed and available on the `ctx` object.
|
48
|
+
|
39
49
|
HAML view example
|
40
50
|
|
41
51
|
```haml
|
42
52
|
%h1 Posts
|
43
|
-
=
|
53
|
+
= ctx.posts.each do |post|
|
44
54
|
%h2 = post.name
|
45
55
|
```
|
46
56
|
|
47
|
-
You can also
|
57
|
+
You can also have the exposed methods automatically cache the result in an instance variable, by using the `expose_cached` variant.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
class PostsController < ActionController::Base
|
61
|
+
include ContextExposer::BaseController
|
62
|
+
|
63
|
+
expose_cached(:post) { Post.find params[:id] }
|
64
|
+
expose_cached(:posts) { Post.find params[:id] }
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
This is especially useful if used in combination with `decorates_before_rendering`, which only works on cached objects.
|
69
|
+
|
70
|
+
## Macros
|
71
|
+
|
72
|
+
You can also choose to use the class macros made available on `ActionController::Base` as Rails loads.
|
73
|
+
|
74
|
+
Use `:base` or `resource` or your custom extension to include the ContextExposer controller module of your choice. The macro `context_exposer :base` is equivalent to writing `include ContextExposer::BaseController`
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
class PostsController < ActionController::Base
|
78
|
+
context_exposer :base
|
79
|
+
```
|
80
|
+
|
81
|
+
## Sublclassing and customizing the ViewContext
|
82
|
+
|
83
|
+
You can also define your own subclass of `ViewContext` and designate an instance of this custom class as your "exposed" target, via `view_ctx_class`method.
|
84
|
+
You can also override the class method of the same name for custom class name construction behavior ;)
|
48
85
|
|
49
86
|
Example:
|
50
87
|
|
@@ -52,10 +89,16 @@ Example:
|
|
52
89
|
class PostsController < ActionController::Base
|
53
90
|
include ContextExposer::BaseController
|
54
91
|
|
55
|
-
|
92
|
+
view_ctx_class :posts_view_context
|
56
93
|
|
57
|
-
|
58
|
-
exposed(:
|
94
|
+
# One model instance
|
95
|
+
exposed(:post) { Post.find params[:id] }
|
96
|
+
|
97
|
+
# Relation (for further scoping or lazy load)
|
98
|
+
exposed(:posts) { Post.all }
|
99
|
+
|
100
|
+
# Array of model instances
|
101
|
+
exposed(:posts_list) { Post.all.to_a }
|
59
102
|
end
|
60
103
|
```
|
61
104
|
|
@@ -90,7 +133,7 @@ HAML view example
|
|
90
133
|
|
91
134
|
```haml
|
92
135
|
%h1 Admin Posts
|
93
|
-
=
|
136
|
+
= ctx.admin_posts.each do |post|
|
94
137
|
%h2 = post.name
|
95
138
|
```
|
96
139
|
|
@@ -101,17 +144,26 @@ This approach opens up many new exciting ways to slice and dice your logic in a
|
|
101
144
|
|
102
145
|
### ResourceController
|
103
146
|
|
104
|
-
The `ResourceController` automatically sets up the typical singular and plural-form resource helpers.
|
147
|
+
The `ResourceController` automatically sets up the typical singular and plural-form resource helpers. For example for PostsController:
|
148
|
+
|
149
|
+
* `post` - one Post instance
|
150
|
+
* `posts` - Search Relatation (for lazy load or further scoping)
|
151
|
+
* `posts_list` - Array of Post instances
|
105
152
|
|
106
153
|
This simplifies the above `PostsController` example to this:
|
107
154
|
|
108
155
|
```ruby
|
109
156
|
class PostsController < ActionController::Base
|
157
|
+
# alternatively: context_exposer :resource
|
110
158
|
include ContextExposer::ResourceController
|
159
|
+
|
160
|
+
expose_resources :all
|
111
161
|
end
|
112
162
|
```
|
113
163
|
|
114
|
-
`
|
164
|
+
The macro `expose_resources` optionally takes a list of the types of resource you want to expose. Valid types are `:one`, `:many` and `:list` respectively (for fx: `post`, `posts` and `posts_list`).
|
165
|
+
|
166
|
+
`ContextExposer::ResourceController` uses the following internal logic for its default functionality. You can override these methods to customize your behavior as needed.
|
115
167
|
|
116
168
|
```ruby
|
117
169
|
module ContextExposer::ResourceController
|
@@ -132,22 +184,75 @@ module ContextExposer::ResourceController
|
|
132
184
|
end
|
133
185
|
```
|
134
186
|
|
135
|
-
|
187
|
+
Tip: You can create reusable module and then include your custom ResourceController.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
module NamedResourceController
|
191
|
+
extend ActiveSupport::Concern
|
192
|
+
include ContextExposer::ResourceController
|
193
|
+
|
194
|
+
protected
|
195
|
+
|
196
|
+
def resource_id
|
197
|
+
params[:name]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
class PostsController < ActionController::Base
|
204
|
+
include NamedResourceController
|
205
|
+
end
|
206
|
+
|
207
|
+
Tip: If you put your module inside the `ContextExposer` namespace, you can even use the `context_exposer` macro ;)
|
208
|
+
|
209
|
+
## Integrations with other exposure gems and patterns
|
210
|
+
|
211
|
+
You can use the class macro `integrate_with(name)` to integrate with either:
|
212
|
+
|
213
|
+
* decent_exposure - `integrate_with :decent_exposure`
|
214
|
+
* decorates_before_rendering - `integrate_with :decorates_before`
|
215
|
+
* instance vars - `integrate_with :instance_vars`
|
216
|
+
|
217
|
+
Note: You can even integrate with multiple strategies
|
136
218
|
|
137
|
-
|
219
|
+
`integrate_with :decent_exposure, :instance_vars`
|
220
|
+
|
221
|
+
You can also specify your integrations directly as part of your `context_exposer` call (recommended)
|
222
|
+
|
223
|
+
`context_exposer :base, with: :decent_exposure`
|
224
|
+
|
225
|
+
In case you use the usual (default) Rails pattern of passing instance variables, you can slowly migrate to exposing via `ctx` object, by adding a simple macro `context_expose :instance_vars` to your controller.
|
226
|
+
|
227
|
+
For decorated instance variables (see `decorates_before_rendering` gem), similarly use `context_expose :decorated_instance_vars`.
|
228
|
+
|
229
|
+
All of these `context_expose :xxxx` methods can optionally take an `:except` or `:only` option with a list of keys, similar to a `before_filter`.
|
230
|
+
|
231
|
+
The method `context_expose :decorated_instance_vars` can additionally take a `:for`option of either `:collection` or `:non_collection` to limit the type of instance vars exposed.
|
232
|
+
|
233
|
+
`context_expose` integration
|
234
|
+
|
235
|
+
* :instance_vars
|
236
|
+
* :decorated_instance_vars
|
237
|
+
* :decently
|
238
|
+
|
239
|
+
Here is a full example demonstrating integration with `decent_exposure`.
|
138
240
|
|
139
241
|
```ruby
|
140
242
|
# using gem 'decent_exposure'
|
141
243
|
# auto-included in ActionController::Base
|
142
244
|
|
143
245
|
class PostsController < ActionController::Base
|
144
|
-
|
246
|
+
# make context_expose_decently method available
|
247
|
+
context_exposer :base, with :decent_exposure
|
145
248
|
|
146
|
-
expose(:posts)
|
147
|
-
expose(:post)
|
148
|
-
expose(:postal)
|
249
|
+
expose(:posts) { Post.all.order(:created_at, :asc) }
|
250
|
+
expose(:post) { Post.first}
|
251
|
+
expose(:postal) { '1234' }
|
149
252
|
|
150
|
-
|
253
|
+
# mirror all methods exposed via #expose on #ctx object
|
254
|
+
# except for 'postal' method
|
255
|
+
context_expose :decently except: 'postal'
|
151
256
|
end
|
152
257
|
```
|
153
258
|
|
@@ -155,10 +260,75 @@ HAML view example
|
|
155
260
|
|
156
261
|
```haml
|
157
262
|
%h1 Posts
|
158
|
-
=
|
263
|
+
= ctx.posts.each do |post|
|
159
264
|
%h2 = post.name
|
160
265
|
```
|
161
266
|
|
267
|
+
## Decorates before rendering
|
268
|
+
|
269
|
+
A patch for the `decorates_before_render` gem is currently made available.
|
270
|
+
|
271
|
+
`ContextExposer.patch :decorates_before_rendering`
|
272
|
+
|
273
|
+
You typically use this in a Rails initializer. This way, `decorates_before_rendering` should try to decorate all your exposed variables before rendering, whether your view context is exposed as instance vars, methods or on the `ctx` object of the view ;)
|
274
|
+
|
275
|
+
Note: You can now also use the macro `decorates_before_render` to include the `DecoratesBeforeRendering` module.
|
276
|
+
|
277
|
+
### Auto-finding a decorator
|
278
|
+
|
279
|
+
For the patched version of `decorates_before_render` to work, your exposed and cached object must either have a `model_name` method that returns the name of the model name to be used to calculate the decorator name to use, or alternatively (and with higher precedence if present), a `decorator` method that takes the controller (self) as an argument and returns the full name of the decorator to use ;)
|
280
|
+
|
281
|
+
Example:
|
282
|
+
|
283
|
+
```ruby
|
284
|
+
class PostsController < ActionController::Base
|
285
|
+
decorates_before_render
|
286
|
+
context_exposer :base, with :decent_exposure
|
287
|
+
|
288
|
+
expose_cached(:first_post) { Post.first }
|
289
|
+
|
290
|
+
protected
|
291
|
+
|
292
|
+
def admin?
|
293
|
+
@admin ||= current_user.admin?
|
294
|
+
end
|
295
|
+
end
|
296
|
+
```
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
class Post < ActiveRecord::Base
|
300
|
+
def decorator contrl
|
301
|
+
contrl.send(:admin?) ? 'Admin::PostDecorator' : model_name
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
### Auto-detection Error handling
|
306
|
+
|
307
|
+
If the auto-decoration can't find a decorator for an exposed variable (or method), it will either ignore it (not decorate it) or call `__handle_decorate_error_(error)` which by default will log a Rails warning. Override this error handler as it suits you.
|
308
|
+
|
309
|
+
## Testing
|
310
|
+
|
311
|
+
The tests have been written in rspec 2 and capybara.
|
312
|
+
The test suite consists of:
|
313
|
+
|
314
|
+
* Full app tests
|
315
|
+
* Units tests
|
316
|
+
|
317
|
+
### Dummy app feature tests
|
318
|
+
|
319
|
+
A Dummy app has been set up for use with Capybara feature testing.
|
320
|
+
Please see: http://alindeman.github.com/2012/11/11/rspec-rails-and-capybara-2.0-what-you-need-to-know.html
|
321
|
+
|
322
|
+
The feature tests can be found in `spec/app`
|
323
|
+
|
324
|
+
`$ bundle exec rspec spec/context_exposer`
|
325
|
+
|
326
|
+
### Unit tests (specs)
|
327
|
+
|
328
|
+
The unit tests can be found in `spec/context_exposer`
|
329
|
+
|
330
|
+
`$ bundle exec rspec spec/context_exposer`
|
331
|
+
|
162
332
|
## Contributing
|
163
333
|
|
164
334
|
1. Fork it
|
data/lib/context_exposer.rb
CHANGED
@@ -1,9 +1,24 @@
|
|
1
1
|
require "context_exposer/version"
|
2
2
|
|
3
3
|
module ContextExposer
|
4
|
+
def self.patch name
|
5
|
+
case name.to_sym
|
6
|
+
when :decorates_before_rendering
|
7
|
+
require "context_exposer/patch/#{name}"
|
8
|
+
else
|
9
|
+
raise ArgumentError, "No patch defined for: #{name}. Try one of #{patches}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.patches
|
14
|
+
[:decorates_before_rendering]
|
15
|
+
end
|
4
16
|
end
|
5
17
|
|
6
18
|
require "active_support"
|
7
19
|
require "context_exposer/base_controller"
|
8
20
|
require "context_exposer/resource_controller"
|
21
|
+
require "context_exposer/cached_resource_controller"
|
9
22
|
require "context_exposer/view_context"
|
23
|
+
require "context_exposer/macros"
|
24
|
+
require "context_exposer/rails_config"
|
@@ -1,51 +1,51 @@
|
|
1
|
+
require "context_exposer/integrations"
|
2
|
+
|
1
3
|
module ContextExposer::BaseController
|
2
4
|
extend ActiveSupport::Concern
|
5
|
+
include ContextExposer::Integrations::Base
|
3
6
|
|
4
7
|
included do
|
5
|
-
before_filter :configure_exposed_context
|
6
|
-
|
7
|
-
expose_context :context
|
8
|
+
# before_filter :configure_exposed_context
|
9
|
+
set_callback :process_action, :before, :configure_exposed_context
|
8
10
|
|
9
|
-
|
11
|
+
expose_context :ctx
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
@
|
14
|
+
def view_ctx
|
15
|
+
@view_ctx ||= build_view_ctx
|
14
16
|
end
|
15
|
-
alias_method :
|
17
|
+
alias_method :ctx, :view_ctx
|
16
18
|
|
17
19
|
module ClassMethods
|
18
|
-
def exposed name, &block
|
19
|
-
|
20
|
-
exposure_storage[name.to_sym] = block
|
20
|
+
def exposed name, options = {}, &block
|
21
|
+
_exposure_storage[name.to_sym] = {options: options, proc: block}
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
except = (options[:except] || {}).map(&:to_sym)
|
27
|
-
only = (options[:only] || {}).map(&:to_sym)
|
28
|
-
|
29
|
-
transfer_keys = transfer_keys - except
|
24
|
+
def expose_cached name, options = {}, &block
|
25
|
+
exposed name, options.merge(cached: true), &block
|
26
|
+
end
|
30
27
|
|
31
|
-
|
32
|
-
|
28
|
+
def view_ctx_class name
|
29
|
+
define_method :view_ctx_class do
|
30
|
+
@view_ctx_class ||= name.kind_of?(Class) ? name : name.to_s.camelize.constantize
|
33
31
|
end
|
32
|
+
end
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
34
|
+
def integrate_with *names
|
35
|
+
names.flatten.compact.each do |name|
|
36
|
+
self.send :include, "ContextExposer::Integrations::With#{name.to_s.camelize}".constantize
|
39
37
|
end
|
40
38
|
end
|
41
|
-
alias_method :
|
39
|
+
alias_method :integrates_with, :integrate_with
|
42
40
|
|
43
|
-
def
|
44
|
-
|
45
|
-
@view_context_class ||= name.kind_of?(Class) ? name : name.to_s.camelize.constantize
|
46
|
-
end
|
41
|
+
def context_expose name, options = {}
|
42
|
+
send "context_expose_#{name}", options
|
47
43
|
end
|
48
44
|
|
45
|
+
def _exposure_storage
|
46
|
+
_exposure_hash[self.to_s] ||= {}
|
47
|
+
end
|
48
|
+
|
49
49
|
protected
|
50
50
|
|
51
51
|
def expose_context name
|
@@ -59,32 +59,26 @@ module ContextExposer::BaseController
|
|
59
59
|
end
|
60
60
|
helper_method name
|
61
61
|
hide_action name
|
62
|
-
@
|
62
|
+
@_exposed_view_context = true
|
63
63
|
end
|
64
64
|
|
65
65
|
def exposed_view_context?
|
66
|
-
@
|
66
|
+
@_exposed_view_context == true
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
def exposure_hash
|
74
|
-
@exposure_hash ||= {}
|
75
|
-
end
|
69
|
+
def _exposure_hash
|
70
|
+
@_exposure_hash ||= {}
|
71
|
+
end
|
76
72
|
end
|
77
73
|
|
78
74
|
# must be called after Controller is instantiated
|
79
75
|
def configure_exposed_context
|
80
76
|
return if configured_exposed_context?
|
81
77
|
clazz = self.class
|
82
|
-
exposed_methods = clazz.send(:
|
83
|
-
exposed_methods.each do |name,
|
84
|
-
|
85
|
-
|
86
|
-
this.instance_eval(&procedure)
|
87
|
-
end
|
78
|
+
exposed_methods = clazz.send(:_exposure_hash)[clazz.to_s] || []
|
79
|
+
exposed_methods.each do |name, obj|
|
80
|
+
options = obj[:options] || {}
|
81
|
+
options[:cached] ? _add_cached_ctx_method(obj, name) : _add_ctx_method(obj, name)
|
88
82
|
end
|
89
83
|
@configured_exposed_context = true
|
90
84
|
end
|
@@ -95,13 +89,39 @@ module ContextExposer::BaseController
|
|
95
89
|
|
96
90
|
protected
|
97
91
|
|
92
|
+
def _add_ctx_method obj, name
|
93
|
+
this = self
|
94
|
+
proc = obj[:proc]
|
95
|
+
inst_var_name = "@#{name}"
|
96
|
+
|
97
|
+
view_ctx.send :define_singleton_method, name do
|
98
|
+
this.instance_eval(&proc)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _add_cached_ctx_method obj, name
|
103
|
+
this = self
|
104
|
+
options = obj[:options]
|
105
|
+
proc = obj[:proc]
|
106
|
+
inst_var_name = "@#{name}"
|
107
|
+
|
108
|
+
view_ctx.send :define_singleton_method, name do
|
109
|
+
old_val = instance_variable_get inst_var_name
|
110
|
+
return old_val if old_val
|
111
|
+
|
112
|
+
val = this.instance_eval(&proc)
|
113
|
+
instance_variable_set inst_var_name, val
|
114
|
+
val
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
98
118
|
# returns a ViewContext object
|
99
119
|
# view helpers can be exposed as singleton methods, dynamically be attached (see below)
|
100
|
-
def
|
101
|
-
|
120
|
+
def build_view_ctx
|
121
|
+
view_ctx_class.new self
|
102
122
|
end
|
103
123
|
|
104
|
-
def
|
105
|
-
@
|
124
|
+
def view_ctx_class
|
125
|
+
@view_ctx_class ||= ContextExposer::ViewContext
|
106
126
|
end
|
107
127
|
end
|