pakyow-presenter 0.11.3 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/{pakyow-presenter/CHANGELOG.md → CHANGELOG.md} +0 -5
  3. data/LICENSE +4 -0
  4. data/{pakyow-presenter/README.md → README.md} +1 -2
  5. data/lib/pakyow/generators/presenter/presenter_generator.rb +28 -0
  6. data/lib/pakyow/generators/presenter/templates/presenter.rb.tt +2 -0
  7. data/lib/pakyow/plugin/helpers/rendering.rb +19 -0
  8. data/lib/pakyow/presenter/actions/auto_render.rb +15 -0
  9. data/lib/pakyow/presenter/attributes/attribute.rb +22 -0
  10. data/lib/pakyow/presenter/attributes/boolean.rb +24 -0
  11. data/lib/pakyow/presenter/attributes/hash.rb +89 -0
  12. data/lib/pakyow/presenter/attributes/set.rb +61 -0
  13. data/lib/pakyow/presenter/attributes/string.rb +38 -0
  14. data/lib/pakyow/presenter/attributes.rb +126 -0
  15. data/lib/pakyow/presenter/behavior/config.rb +29 -0
  16. data/lib/pakyow/presenter/behavior/error_rendering.rb +124 -0
  17. data/lib/pakyow/presenter/behavior/exposures.rb +29 -0
  18. data/lib/pakyow/presenter/behavior/implicit_rendering.rb +21 -0
  19. data/lib/pakyow/presenter/behavior/initializing.rb +37 -0
  20. data/lib/pakyow/presenter/behavior/modes.rb +117 -0
  21. data/lib/pakyow/presenter/behavior/versions.rb +71 -0
  22. data/lib/pakyow/presenter/behavior/watching.rb +21 -0
  23. data/lib/pakyow/presenter/binder.rb +115 -0
  24. data/lib/pakyow/presenter/binding_parts.rb +64 -0
  25. data/lib/pakyow/presenter/component.rb +74 -0
  26. data/lib/pakyow/presenter/composers/component.rb +78 -0
  27. data/lib/pakyow/presenter/composers/view.rb +73 -0
  28. data/lib/pakyow/presenter/errors.rb +63 -0
  29. data/lib/pakyow/presenter/framework.rb +203 -0
  30. data/lib/pakyow/presenter/front_matter_parser.rb +42 -0
  31. data/lib/pakyow/presenter/helpers/rendering.rb +18 -0
  32. data/lib/pakyow/presenter/presentable.rb +28 -0
  33. data/lib/pakyow/presenter/presentable_error.rb +19 -0
  34. data/lib/pakyow/presenter/presenter.rb +766 -0
  35. data/lib/pakyow/presenter/presenters/endpoint.rb +158 -0
  36. data/lib/pakyow/presenter/presenters/form.rb +522 -0
  37. data/lib/pakyow/presenter/processor.rb +61 -0
  38. data/lib/pakyow/presenter/renderable.rb +28 -0
  39. data/lib/pakyow/presenter/renderer.rb +269 -0
  40. data/lib/pakyow/presenter/rendering/actions/cleanup_prototype_nodes.rb +21 -0
  41. data/lib/pakyow/presenter/rendering/actions/cleanup_unbound_bindings.rb +35 -0
  42. data/lib/pakyow/presenter/rendering/actions/create_template_nodes.rb +27 -0
  43. data/lib/pakyow/presenter/rendering/actions/insert_prototype_bar.rb +101 -0
  44. data/lib/pakyow/presenter/rendering/actions/install_authenticity.rb +42 -0
  45. data/lib/pakyow/presenter/rendering/actions/place_in_mode.rb +56 -0
  46. data/lib/pakyow/presenter/rendering/actions/render_components.rb +279 -0
  47. data/lib/pakyow/presenter/rendering/actions/set_page_title.rb +35 -0
  48. data/lib/pakyow/presenter/rendering/actions/setup_endpoints.rb +62 -0
  49. data/lib/pakyow/presenter/rendering/actions/setup_forms.rb +174 -0
  50. data/lib/pakyow/presenter/significant_nodes.rb +309 -0
  51. data/lib/pakyow/presenter/templates.rb +229 -0
  52. data/lib/pakyow/presenter/versioned_view.rb +209 -0
  53. data/lib/pakyow/presenter/view.rb +586 -0
  54. data/lib/pakyow/presenter/views/form.rb +58 -0
  55. data/lib/pakyow/presenter/views/layout.rb +32 -0
  56. data/lib/pakyow/presenter/views/page.rb +72 -0
  57. data/lib/pakyow/presenter/views/partial.rb +28 -0
  58. data/lib/pakyow/presenter.rb +33 -0
  59. data/lib/pakyow/views/errors/layouts/development_error.html +102 -0
  60. data/lib/pakyow/views/errors/layouts/production_error.html +27 -0
  61. data/lib/pakyow/views/errors/pages/404.html +12 -0
  62. data/lib/pakyow/views/errors/pages/500.html +12 -0
  63. data/lib/pakyow/views/errors/pages/development/500.html +39 -0
  64. data/lib/string_doc/attributes.rb +109 -0
  65. data/lib/string_doc/meta_attributes.rb +48 -0
  66. data/lib/string_doc/meta_node.rb +328 -0
  67. data/lib/string_doc/node.rb +377 -0
  68. data/lib/string_doc.rb +642 -0
  69. metadata +95 -75
  70. data/pakyow-presenter/LICENSE +0 -20
  71. data/pakyow-presenter/lib/pakyow/presenter/attributes.rb +0 -228
  72. data/pakyow-presenter/lib/pakyow/presenter/base.rb +0 -38
  73. data/pakyow-presenter/lib/pakyow/presenter/binder.rb +0 -116
  74. data/pakyow-presenter/lib/pakyow/presenter/binder_set.rb +0 -94
  75. data/pakyow-presenter/lib/pakyow/presenter/binding_eval.rb +0 -37
  76. data/pakyow-presenter/lib/pakyow/presenter/config/presenter.rb +0 -42
  77. data/pakyow-presenter/lib/pakyow/presenter/container.rb +0 -6
  78. data/pakyow-presenter/lib/pakyow/presenter/doc_helpers.rb +0 -17
  79. data/pakyow-presenter/lib/pakyow/presenter/exceptions.rb +0 -11
  80. data/pakyow-presenter/lib/pakyow/presenter/ext/app.rb +0 -33
  81. data/pakyow-presenter/lib/pakyow/presenter/ext/call_context.rb +0 -28
  82. data/pakyow-presenter/lib/pakyow/presenter/helpers.rb +0 -46
  83. data/pakyow-presenter/lib/pakyow/presenter/page.rb +0 -110
  84. data/pakyow-presenter/lib/pakyow/presenter/partial.rb +0 -6
  85. data/pakyow-presenter/lib/pakyow/presenter/presenter.rb +0 -232
  86. data/pakyow-presenter/lib/pakyow/presenter/string_doc.rb +0 -380
  87. data/pakyow-presenter/lib/pakyow/presenter/string_doc_parser.rb +0 -144
  88. data/pakyow-presenter/lib/pakyow/presenter/string_doc_renderer.rb +0 -18
  89. data/pakyow-presenter/lib/pakyow/presenter/template.rb +0 -51
  90. data/pakyow-presenter/lib/pakyow/presenter/view.rb +0 -541
  91. data/pakyow-presenter/lib/pakyow/presenter/view_collection.rb +0 -330
  92. data/pakyow-presenter/lib/pakyow/presenter/view_composer.rb +0 -237
  93. data/pakyow-presenter/lib/pakyow/presenter/view_context.rb +0 -111
  94. data/pakyow-presenter/lib/pakyow/presenter/view_store.rb +0 -262
  95. data/pakyow-presenter/lib/pakyow/presenter/view_store_loader.rb +0 -43
  96. data/pakyow-presenter/lib/pakyow/presenter/view_version.rb +0 -113
  97. data/pakyow-presenter/lib/pakyow/presenter.rb +0 -8
  98. data/pakyow-presenter/lib/pakyow/views/errors/404.erb +0 -26
  99. data/pakyow-presenter/lib/pakyow/views/errors/500.erb +0 -23
  100. data/pakyow-presenter/lib/pakyow-presenter.rb +0 -1
@@ -1,330 +0,0 @@
1
- module Pakyow
2
- module Presenter
3
- class ViewCollection
4
- include Enumerable
5
-
6
- attr_reader :views, :scoped_as
7
-
8
- def initialize(scope = nil)
9
- @views = []
10
- @scoped_as = scope
11
- end
12
-
13
- def initialize_copy(original_view)
14
- super
15
-
16
- @views = Pakyow::Utils::Dup.deep(original_view.views)
17
- @scoped_as = original_view.scoped_as
18
- end
19
-
20
- def ==(other)
21
- @views.each_with_index do |view, i|
22
- return false if view != other.views[i]
23
- end
24
-
25
- return true
26
- end
27
-
28
- def each
29
- @views.each { |v| yield(v) }
30
- end
31
-
32
- def attrs(attrs = {})
33
- inject(AttributesCollection.new) { |coll, view|
34
- coll << view.attrs(attrs)
35
- }
36
- end
37
-
38
- def remove
39
- each {|e| e.remove}
40
- end
41
-
42
- def clear
43
- each {|e| e.clear}
44
- end
45
-
46
- def text
47
- map { |v| v.text }
48
- end
49
-
50
- def text=(text)
51
- each {|e| e.text = text}
52
- end
53
-
54
- def html
55
- map { |v| v.html }
56
- end
57
-
58
- def html=(html)
59
- each {|e| e.html = html}
60
- end
61
-
62
- def to_html
63
- map { |v| v.to_html }.join('')
64
- end
65
-
66
- alias :to_s :to_html
67
-
68
- def append(content)
69
- each do |view|
70
- view.append(content)
71
- end
72
- end
73
-
74
- def prepend(content)
75
- each do |view|
76
- view.prepend(content)
77
- end
78
- end
79
-
80
- # TODO: decide if we care to check the type of
81
- # objects being added to the collection
82
- def <<(val)
83
- @views << val
84
- self
85
- end
86
-
87
- def concat(views)
88
- @views.concat(views)
89
- end
90
-
91
- def [](i)
92
- @views[i]
93
- end
94
-
95
- def length
96
- @views.length
97
- end
98
-
99
- def scope(name)
100
- collection = inject(ViewCollection.new(name)) { |coll, view|
101
- scopes = view.scope(name)
102
- next if scopes.nil?
103
-
104
- scopes.inject(coll) { |coll, scoped_view|
105
- coll << scoped_view
106
- }
107
- }
108
-
109
- if collection.versioned?
110
- ViewVersion.new(collection.views)
111
- else
112
- collection
113
- end
114
- end
115
-
116
- def prop(name)
117
- inject(ViewCollection.new(scoped_as)) { |coll, view|
118
- scopes = view.prop(name)
119
- next if scopes.nil?
120
-
121
- scopes.inject(coll) { |coll, scoped_view|
122
- coll << scoped_view
123
- }
124
- }
125
- end
126
-
127
- def versioned?
128
- each do |view|
129
- return true if view.versioned?
130
- end
131
-
132
- false
133
- end
134
-
135
- def exists?
136
- each do |view|
137
- return true if view.exists?
138
- end
139
-
140
- false
141
- end
142
-
143
- def component(name)
144
- collection = inject(ViewCollection.new(scoped_as)) { |coll, view|
145
- scopes = view.component(name)
146
- next if scopes.nil?
147
-
148
- scopes.inject(coll) { |coll, scoped_view|
149
- coll << scoped_view
150
- }
151
- }
152
-
153
- if collection.versioned?
154
- ViewVersion.new(collection.views)
155
- else
156
- collection
157
- end
158
- end
159
-
160
- def component?
161
- each do |view|
162
- return true if view.component?
163
- end
164
-
165
- false
166
- end
167
-
168
- def component_name
169
- each do |view|
170
- return view.component_name if view.component?
171
- end
172
- end
173
-
174
- # call-seq:
175
- # with {|view| block}
176
- #
177
- # Creates a context in which view manipulations can be performed.
178
- #
179
- def with(&block)
180
- if block.arity == 0
181
- instance_exec(&block)
182
- else
183
- yield(self)
184
- end
185
-
186
- self
187
- end
188
-
189
- # call-seq:
190
- # for {|view, datum| block}
191
- #
192
- # Yields a view and its matching dataum. Datums are yielded until
193
- # no more views or data is available. For the ViewCollection case, this
194
- # means the block will be yielded self.length times.
195
- #
196
- # (this is basically Bret's `map` function)
197
- #
198
- def for(data, &block)
199
- data = Array.ensure(data)
200
- each_with_index do |view, i|
201
- datum = data[i]
202
- break if datum.nil?
203
-
204
- if block.arity == 1
205
- view.instance_exec(data[i], &block)
206
- else
207
- block.call(view, data[i])
208
- end
209
- end
210
-
211
- self
212
- end
213
-
214
- # call-seq:
215
- # for_with_index {|view, datum, i| block}
216
- #
217
- # Yields a view, its matching datum, and index. Datums are yielded until
218
- # no more views or data is available. For the ViewCollection case, this
219
- # means the block will be yielded self.length times.
220
- #
221
- def for_with_index(data, &block)
222
- i = 0
223
- self.for(data) do |ctx, datum|
224
- if block.arity == 2
225
- ctx.instance_exec(datum, i, &block)
226
- else
227
- block.call(ctx, datum, i)
228
- end
229
-
230
- i += 1
231
- end
232
- end
233
-
234
- # call-seq:
235
- # match(data) => ViewCollection
236
- #
237
- # Manipulates the current collection to match the data. The final ViewCollection object
238
- # will consist n copies of self[data index] || self[-1], where n = data.length.
239
- #
240
- def match(data)
241
- return self if length == 0
242
- data = Array.ensure(data)
243
-
244
- # an empty set always means an empty view
245
- if data.empty?
246
- remove
247
- else
248
- if length > data.length
249
- self[data.length..-1].each do |view|
250
- view.remove
251
- end
252
- else
253
- working = self[-1]
254
- data[length..-1].each do
255
- duped_view = working.soft_copy
256
- working.after(duped_view)
257
- working = duped_view
258
- self << duped_view
259
- end
260
- end
261
- end
262
-
263
- self
264
- end
265
-
266
- # call-seq:
267
- # repeat(data) {|view, datum| block}
268
- #
269
- # Matches self to data and yields a view/datum pair.
270
- #
271
- def repeat(data, &block)
272
- match(data).for(data, &block)
273
- end
274
-
275
- # call-seq:
276
- # repeat_with_index(data) {|view, datum, i| block}
277
- #
278
- # Matches self with data and yields a view/datum pair with index.
279
- #
280
- def repeat_with_index(data, &block)
281
- match(data).for_with_index(data, &block)
282
- end
283
-
284
- # call-seq:
285
- # bind(data)
286
- #
287
- # Binds data across existing scopes.
288
- #
289
- def bind(data, bindings: {}, context: nil, &block)
290
- self.for(data) do |view, datum|
291
- view.bind(datum, bindings: bindings, context: context)
292
- next if block.nil?
293
-
294
- if block.arity == 1
295
- view.instance_exec(datum, &block)
296
- else
297
- block.call(view, datum)
298
- end
299
- end
300
- end
301
-
302
- # call-seq:
303
- # bind_with_index(data)
304
- #
305
- # Binds data across existing scopes, yielding a view/datum pair with index.
306
- #
307
- def bind_with_index(*a, **k, &block)
308
- i = 0
309
- bind(*a, **k) do |ctx, datum|
310
- if block.arity == 2
311
- ctx.instance_exec(datum, i, &block)
312
- else
313
- block.call(ctx, datum, i)
314
- end
315
-
316
- i += 1
317
- end
318
- end
319
-
320
- # call-seq:
321
- # apply(data)
322
- #
323
- # Matches self to data then binds data to the view.
324
- #
325
- def apply(data, bindings: {}, context: nil, &block)
326
- match(data).bind(data, bindings: bindings, context: context, &block)
327
- end
328
- end
329
- end
330
- end
@@ -1,237 +0,0 @@
1
- module Pakyow
2
- module Presenter
3
- class ViewComposer
4
- class << self
5
- def from_path(store, path, opts = {}, &block)
6
- ViewComposer.new(store, path, opts, &block)
7
- end
8
- end
9
-
10
- extend Forwardable
11
-
12
- def_delegators :template, :title, :title=
13
- def_delegators :parts, :prop, :component
14
- def_delegators :view, :to_html
15
-
16
- attr_reader :store, :path, :page, :partials
17
-
18
- def initialize(store, path = nil, opts = {}, &block)
19
- @store = store
20
- @path = path
21
-
22
- self.page = opts.fetch(:page) {
23
- path
24
- }
25
-
26
- self.template = opts.fetch(:template) {
27
- (@page.is_a?(Page) && @page.info(:template)) || path
28
- }
29
-
30
- # Setting up partials is a bit complicated, but here's how it works.
31
- #
32
- # First we set `@partials` to the ones passed or the partials from the
33
- # store for the path that we're composing at. We do this so that
34
- # partials are included in `parts` after this (important since we
35
- # want partials defined in partials to be found properly).
36
- begin
37
- @partials = {}
38
- @partials = includes(opts.fetch(:includes))
39
- rescue
40
- @partials = store.partials(path) unless path.nil?
41
- end
42
-
43
- # Now we need to build the actual set of partials used by parts of the
44
- # view that we're composing. This bit of code counts the number of each
45
- # partial present; if it's greater than one we represent them as a view
46
- # collection, otherwise it's just a partial.
47
- #
48
- # FIXME: It's possible there's a more straight-forward way to write this
49
- # code; it should be explored at some poitn in the future.
50
- partials = {}
51
- @partials.each do |name, view|
52
- count = parts.select { |part|
53
- part.doc.partials.key?(name)
54
- }.map { |part|
55
- part.doc.partials[name].count
56
- }.inject(&:+) || 0
57
-
58
- partials[name] = view; next if count < 2
59
-
60
- collection = ViewCollection.new
61
-
62
- count.times do
63
- collection << view.dup
64
- end
65
-
66
- partials[name] = collection
67
- end
68
-
69
- @partials = partials
70
-
71
- instance_exec(&block) if block_given?
72
- end
73
-
74
- def initialize_copy(original)
75
- super
76
-
77
- %w[store path page template partials view].each do |ivar|
78
- value = original.instance_variable_get("@#{ivar}")
79
- next if value.nil?
80
-
81
- if value.is_a?(Hash)
82
- dup_value = {}
83
- value.each_pair { |key, value| dup_value[key] = value.dup }
84
- else
85
- dup_value = value.dup
86
- end
87
-
88
- self.instance_variable_set("@#{ivar}", dup_value)
89
- end
90
- end
91
-
92
- def view
93
- build_view
94
- end
95
- alias_method :composed, :view
96
-
97
- def template(template = nil)
98
- if template.nil?
99
- return @template
100
- end
101
-
102
- self.template = template
103
- return self
104
- end
105
-
106
- def template=(template)
107
- unless template.is_a?(Template)
108
- # get template by name
109
- template = @store.template(template.to_sym)
110
- end
111
-
112
- @template = template
113
-
114
- return self
115
- end
116
-
117
- def page=(page)
118
- unless page.is_a?(Page)
119
- # get page by name
120
- page = @store.page(page)
121
- end
122
-
123
- @page = page
124
-
125
- return self
126
- end
127
-
128
- def includes(partial_map)
129
- @partials.merge!(remap_partials(partial_map))
130
- end
131
-
132
- def partials=(partial_map)
133
- @partials.merge!(remap_partials(partial_map))
134
- end
135
-
136
- def partial(name)
137
- partial = @partials[name]
138
- partial.includes(partials)
139
- return partial
140
- end
141
-
142
- def container(name)
143
- container = @page.container(name)
144
- return container
145
- end
146
-
147
- def parts
148
- # create an array to hold the parts
149
- parts = ViewCollection.new
150
-
151
- # add the current template
152
- parts << @template
153
-
154
- # add each page container
155
- @page.each_container do |_, container|
156
- parts << container
157
- end
158
-
159
- parts.concat(partials_for_parts(parts))
160
-
161
- return parts
162
- end
163
-
164
- def scope(name)
165
- collection = parts.scope(name)
166
-
167
- if collection.is_a?(ViewVersion)
168
- collection = collection.versions.inject(ViewCollection.new(name)) { |c, v| c << v; c }
169
- end
170
-
171
- # include partials so nested scopes/props can be bound to
172
- collection.each do |view|
173
- view.includes(partials)
174
- end
175
-
176
- #TODO make sure anytime we return a collection it tries to version
177
- # make this a class level helper method on ViewVersion
178
- if !collection.is_a?(ViewVersion) && collection.versioned?
179
- ViewVersion.new(collection.views)
180
- else
181
- collection
182
- end
183
- end
184
-
185
- private
186
-
187
- def build_view
188
- raise MissingTemplate, "No template provided to view composer" if @template.nil?
189
- raise MissingPage, "No page provided to view composer" if @page.nil?
190
-
191
- view = @template.dup.build(@page).includes(@partials)
192
-
193
- # set title
194
- title = @page.info(:title)
195
- view.title = title unless title.nil?
196
-
197
- return view
198
- end
199
-
200
- def remap_partials(partials)
201
- Hash[partials.map { |name, partial_or_path|
202
- if partial_or_path.is_a?(Partial)
203
- partial = partial_or_path
204
- else
205
- partial = Partial.load(@store.expand_partial_path(partial_or_path))
206
- end
207
-
208
- [name, partial]
209
- }]
210
- end
211
-
212
- def partials_for_parts(parts, acc = [])
213
- # determine the partials to be included
214
- available_partials = parts.inject([]) { |sum, part|
215
- if part.is_a?(ViewCollection)
216
- part.each do |view|
217
- sum.concat(view.doc.partials.keys)
218
- end
219
- else
220
- sum.concat(part.doc.partials.keys)
221
- end
222
- }
223
-
224
- # add available partials as parts
225
- partials.select { |name|
226
- available_partials.include?(name)
227
- }.each_pair { |_, partial|
228
- acc << partial
229
- partials_for_parts([partial], acc)
230
- }
231
-
232
- return acc
233
- end
234
-
235
- end
236
- end
237
- end
@@ -1,111 +0,0 @@
1
- module Pakyow
2
- module Presenter
3
- # This is a wrapper for View / ViewCollection that passes the current
4
- # AppContext to all binding methods. This object is expected to only
5
- # be used from the app, not internally.
6
- #
7
- class ViewContext
8
- include Helpers
9
- VIEW_CLASSES = [View, ViewCollection, Partial, Template, Container, ViewVersion]
10
-
11
- # The arities of misc view methods that switch the behavior from
12
- # instance_exec to yield.
13
- #
14
- EXEC_ARITIES = { with: 0, for: 1, for_with_index: 2, repeat: 1,
15
- repeat_with_index: 2, bind: 1, bind_with_index: 2, apply: 1 }
16
-
17
- attr_reader :context
18
-
19
- def initialize(view, context)
20
- @view = view
21
- @context = context
22
- end
23
-
24
- def subject
25
- @view
26
- end
27
-
28
- # View methods that expect context, so it can be mixed in.
29
- #
30
- %i[bind bind_with_index apply].each do |method|
31
- define_method(method) do |data, **kargs, &block|
32
- kargs[:context] ||= @context
33
- ret = @view.send(method, data, **kargs, &wrap(method, &block))
34
- handle_return_value(ret)
35
- end
36
- end
37
-
38
- # View methods that return views, but don't expect context.
39
- #
40
- %i[with for for_with_index repeat repeat_with_index].each do |method|
41
- define_method(method) do |*args, &block|
42
- ret = @view.send(method, *args, &wrap(method, &block))
43
- handle_return_value(ret)
44
- end
45
- end
46
-
47
- # View methods that support versioning.
48
- #
49
- %i[scope prop].each do |method|
50
- define_method(method) do |*args|
51
- collection = @view.send(method, *args)
52
-
53
- if collection.views && collection.versioned?
54
- ret = ViewVersion.new(collection.views)
55
- else
56
- ret = collection
57
- end
58
-
59
- handle_return_value(ret)
60
- end
61
- end
62
-
63
- # Pass these through, handling the return value.
64
- #
65
- def method_missing(method, *args, &block)
66
- ret = @view.send(method, *args, &block)
67
- handle_return_value(ret)
68
- end
69
-
70
- private
71
-
72
- def view?(obj)
73
- VIEW_CLASSES.include?(obj.class)
74
- end
75
-
76
- # Returns a new context for returned views, or the return value.
77
- #
78
- def handle_return_value(value)
79
- if view?(value)
80
- return ViewContext.new(value, @context)
81
- end
82
-
83
- value
84
- end
85
-
86
- # Wrap the block, substituting the view with the current view context.
87
- #
88
- def wrap(method, &block)
89
- return if block.nil?
90
-
91
- Proc.new do |*args|
92
- ctx = args.map! { |arg|
93
- view?(arg) ? ViewContext.new(arg, @context) : arg
94
- }.find { |arg| arg.is_a?(ViewContext) }
95
-
96
- case block.arity
97
- when EXEC_ARITIES[method]
98
- # Rejecting ViewContext handles the edge cases around the order of
99
- # arguments from view methods (since view is not present in some
100
- # situations and when it is present, is always the first arg).
101
- ctx.instance_exec(*args.reject { |arg|
102
- arg.is_a?(ViewContext)
103
- }, &block)
104
- else
105
- block.call(*args)
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end