cells 3.3.10 → 3.4.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/CHANGES +0 -8
  2. data/Gemfile +4 -1
  3. data/README.rdoc +91 -107
  4. data/Rakefile +0 -4
  5. data/lib/cell.rb +5 -6
  6. data/lib/{cells/cell → cell}/active_helper.rb +1 -1
  7. data/lib/cell/base.rb +134 -0
  8. data/lib/cell/base_methods.rb +100 -0
  9. data/lib/cell/caching.rb +153 -0
  10. data/lib/cell/rails.rb +239 -0
  11. data/lib/cells.rb +25 -3
  12. data/lib/cells/assertions_helper.rb +1 -1
  13. data/lib/cells/helpers/capture_helper.rb +3 -3
  14. data/lib/cells/rails.rb +65 -4
  15. data/lib/cells/version.rb +3 -1
  16. data/rails_generators/cell/cell_generator.rb +47 -35
  17. data/rails_generators/cell/templates/cell.rb +1 -1
  18. data/rails_generators/cells_install/cells_install_generator.rb +5 -3
  19. data/rails_generators/erb/cell_generator.rb +20 -0
  20. data/rails_generators/{cell → erb}/templates/view.html.erb +0 -0
  21. data/test/active_helper_test.rb +1 -0
  22. data/test/app/cells/bad_guitarist_cell.rb +2 -0
  23. data/test/app/cells/bassist_cell.rb +1 -1
  24. data/test/app/controllers/musician_controller.rb +16 -0
  25. data/test/assertions_helper_test.rb +8 -18
  26. data/test/base_methods_test.rb +40 -0
  27. data/test/cell_generator_test.rb +33 -21
  28. data/test/helper_test.rb +31 -123
  29. data/test/rails/caching_test.rb +215 -0
  30. data/test/rails/capture_test.rb +52 -0
  31. data/test/rails/cells_test.rb +88 -0
  32. data/test/rails/integration_test.rb +37 -0
  33. data/test/rails/render_test.rb +140 -0
  34. data/test/rails/router_test.rb +74 -0
  35. data/test/rails/view_test.rb +24 -0
  36. data/test/test_helper.rb +30 -29
  37. metadata +68 -133
  38. data/.gitignore +0 -3
  39. data/about.yml +0 -7
  40. data/cells.gemspec +0 -26
  41. data/lib/cells/cell.rb +0 -16
  42. data/lib/cells/cell/base.rb +0 -470
  43. data/lib/cells/cell/caching.rb +0 -163
  44. data/lib/cells/cell/test_case.rb +0 -158
  45. data/lib/cells/cell/view.rb +0 -55
  46. data/lib/cells/rails/action_controller.rb +0 -37
  47. data/lib/cells/rails/action_view.rb +0 -37
  48. data/rails/init.rb +0 -44
  49. data/rails_generators/cells_install/templates/tasks.rake +0 -6
  50. data/test/app/cells/a/another_state.html.erb +0 -1
  51. data/test/app/cells/a/existing_view.html.erb +0 -1
  52. data/test/app/cells/a/inherited_view.html.erb +0 -1
  53. data/test/app/cells/a/inherited_view.js.erb +0 -1
  54. data/test/app/cells/a/view_with_locals.html.erb +0 -1
  55. data/test/app/cells/a/view_with_render_call.html.erb +0 -1
  56. data/test/app/cells/b/existing_view.html.erb +0 -1
  57. data/test/app/cells/b/existing_view.js.erb +0 -1
  58. data/test/app/cells/b/layouts/metal.html.erb +0 -1
  59. data/test/app/cells/b/view_with_render_call.html.erb +0 -1
  60. data/test/app/cells/bassist/jam.html.erb +0 -3
  61. data/test/app/cells/bassist/play.html.erb +0 -1
  62. data/test/app/cells/cells_test_one/renamed_instance_view.html.erb +0 -1
  63. data/test/app/cells/cells_test_one/super_state.html.erb +0 -1
  64. data/test/app/cells/cells_test_one_cell.rb +0 -20
  65. data/test/app/cells/cells_test_two_cell.rb +0 -4
  66. data/test/app/cells/helper_using/state_using_application_helper.html.erb +0 -3
  67. data/test/app/cells/helper_using/state_with_automatic_helper_invocation.html.erb +0 -3
  68. data/test/app/cells/helper_using/state_with_helper_invocation.html.erb +0 -3
  69. data/test/app/cells/helper_using/state_with_helper_method_invocation.html.erb +0 -3
  70. data/test/app/cells/layouts/metal.html.erb +0 -1
  71. data/test/app/cells/my_child/hello.html.erb +0 -1
  72. data/test/app/cells/my_mother/bye.html.erb +0 -1
  73. data/test/app/cells/my_mother/hello.html.erb +0 -1
  74. data/test/app/cells/my_test/_broken_partial.html.erb +0 -1
  75. data/test/app/cells/my_test/_partial.html.erb +0 -1
  76. data/test/app/cells/my_test/state_with_instance_var.html.erb +0 -1
  77. data/test/app/cells/my_test/state_with_link_to.html.erb +0 -3
  78. data/test/app/cells/my_test/state_with_not_included_helper_method.html.erb +0 -8
  79. data/test/app/cells/my_test/view_containing_broken_partial.html.erb +0 -3
  80. data/test/app/cells/my_test/view_containing_nonexistant_partial.html.erb +0 -3
  81. data/test/app/cells/my_test/view_containing_partial.html.erb +0 -3
  82. data/test/app/cells/my_test/view_containing_partial_without_cell_name.html.erb +0 -3
  83. data/test/app/cells/my_test/view_in_local_test_views_dir.html.erb +0 -1
  84. data/test/app/cells/my_test/view_with_explicit_english_translation.en.html.erb +0 -1
  85. data/test/app/cells/my_test/view_with_explicit_english_translation.html.erb +0 -1
  86. data/test/app/cells/my_test/view_with_instance_var.html.erb +0 -4
  87. data/test/app/cells/really_module/nested/happy_state.html.erb +0 -1
  88. data/test/app/cells/really_module/nested_cell.rb +0 -11
  89. data/test/app/cells/simple/two_templates_state.html.mytpl +0 -1
  90. data/test/app/cells/simple_cell.rb +0 -7
  91. data/test/app/cells/test/beep.html.erb +0 -1
  92. data/test/app/cells/test/state_invoking_capture.html.erb +0 -7
  93. data/test/app/cells/test/state_invoking_content_for.html.erb +0 -7
  94. data/test/app/cells/test/state_invoking_content_for_twice.html.erb +0 -9
  95. data/test/app/cells/test/state_with_not_included_helper_method.html.erb +0 -8
  96. data/test/app/cells/two_helpers_including/state_using_another_helper.html.erb +0 -3
  97. data/test/bugs_test.rb +0 -23
  98. data/test/caching_test.rb +0 -270
  99. data/test/capture_helper_test.rb +0 -59
  100. data/test/cells_test.rb +0 -352
  101. data/test/rails_test.rb +0 -35
  102. data/test/render_test.rb +0 -305
  103. data/test/test_case_test.rb +0 -106
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- .DS_Store
2
- pkg
3
- .*~
data/about.yml DELETED
@@ -1,7 +0,0 @@
1
- author: Nick Sutterer, Peter Bex, Bob Leers
2
- summary: Cells are lightweight controllers for Rails and can be rendered in controllers and views, providing an elegant and fast way for encapsulation and component-orientation.
3
- homepage: http://cells.rubyforge.org
4
- plugin:
5
- license: MIT
6
- version: 1.1
7
- rails_version: 2.1
@@ -1,26 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib/', __FILE__)
3
- $:.unshift lib unless $:.include?(lib)
4
-
5
- require 'cells/version'
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "cells"
9
- s.version = Cells::VERSION
10
- s.platform = Gem::Platform::RUBY
11
- s.authors = ["Nick Sutterer"]
12
- s.email = ["apotonick@gmail.com"]
13
- s.homepage = "http://cells.rubyforge.org"
14
- s.summary = %q{View Components for Rails.}
15
- s.description = %q{Cells are view components for Rails. They are lightweight controllers, can be rendered in views and thus provide an elegant and fast way for encapsulation and component-orientation.}
16
-
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ["lib"]
21
-
22
- s.add_dependency "rails", "~> 2.3"
23
-
24
- s.add_development_dependency "shoulda"
25
- s.add_development_dependency "active_helper"
26
- end
@@ -1,16 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Cells
4
- module Cell
5
- autoload :Base, 'cells/cell/base'
6
- autoload :View, 'cells/cell/view'
7
- autoload :Caching, 'cells/cell/caching'
8
- autoload :ActiveHelper, 'cells/cell/active_helper'
9
- end
10
- end
11
-
12
- # Mixin caching behaviour into +::Cell::Base+.
13
- # Note: Must be done using class_eval.
14
- Cells::Cell::Base.class_eval do
15
- include ::Cells::Cell::Caching
16
- end
@@ -1,470 +0,0 @@
1
- # encoding: utf-8
2
- require 'action_controller/base'
3
-
4
- module Cells
5
- module Cell
6
- # == Basic overview
7
- #
8
- # A Cell is the central notion of the cells plugin. A cell acts as a
9
- # lightweight controller in the sense that it will assign variables and
10
- # render a view. Cells can be rendered from other cells as well as from
11
- # regular controllers and views (see ActionView::Base#render_cell and
12
- # ControllerMethods#render_cell)
13
- #
14
- # == A render_cell() cycle
15
- #
16
- # A typical <tt>render_cell</tt> state rendering cycle looks like this:
17
- # render_cell :blog, :newest_article, {...}
18
- # - an instance of the class <tt>BlogCell</tt> is created, and a hash containing
19
- # arbitrary parameters is passed
20
- # - the <em>state method</em> <tt>newest_article</tt> is executed and assigns instance
21
- # variables to be used in the view
22
- # - Usually the state method will call #render and return
23
- # - #render will retrieve the corresponding view
24
- # (e.g. <tt>app/cells/blog/newest_article.html. [erb|haml|...]</tt>),
25
- # renders this template and returns the markup.
26
- #
27
- # == Design Principles
28
- # A cell is a completely autonomous object and it should not know or have to know
29
- # from what controller it is being rendered. For this reason, the controller's
30
- # instance variables and params hash are not directly available from the cell or
31
- # its views. This is not a bug, this is a feature! It means cells are truly
32
- # reusable components which can be plugged in at any point in your application
33
- # without having to think about what information is available at that point.
34
- # When rendering a cell, you can explicitly pass variables to the cell in the
35
- # extra opts argument hash, just like you would pass locals in partials.
36
- # This hash is then available inside the cell as the @opts instance variable.
37
- #
38
- # == Directory hierarchy
39
- #
40
- # To get started creating your own cells, you can simply create a new directory
41
- # structure under your <tt>app</tt> directory called <tt>cells</tt>. Cells are
42
- # ruby classes which end in the name Cell. So for example, if you have a
43
- # cell which manages all user information, it would be called <tt>UserCell</tt>.
44
- # A cell which manages a shopping cart could be called <tt>ShoppingCartCell</tt>.
45
- #
46
- # The directory structure of this example would look like this:
47
- # app/
48
- # models/
49
- # ..
50
- # views/
51
- # ..
52
- # helpers/
53
- # application_helper.rb
54
- # product_helper.rb
55
- # ..
56
- # controllers/
57
- # ..
58
- # cells/
59
- # shopping_cart_cell.rb
60
- # shopping_cart/
61
- # status.html.erb
62
- # product_list.html.erb
63
- # empty_prompt.html.erb
64
- # user_cell.rb
65
- # user/
66
- # login.html.erb
67
- # layouts/
68
- # box.html.erb
69
- # ..
70
- #
71
- # The directory with the same name as the cell contains views for the
72
- # cell's <em>states</em>. A state is an executed method along with a
73
- # rendered view, resulting in content. This means that states are to
74
- # cells as actions are to controllers, so each state has its own view.
75
- # The use of partials is deprecated with cells, it is better to just
76
- # render a different state on the same cell (which also works recursively).
77
- #
78
- # Anyway, <tt>render :partial </tt> in a cell view will work, if the
79
- # partial is contained in the cell's view directory.
80
- #
81
- # As can be seen above, Cells also can make use of helpers. All Cells
82
- # include ApplicationHelper by default, but you can add additional helpers
83
- # as well with the ::Cell::Base.helper class method:
84
- # class ShoppingCartCell < ::Cell::Base
85
- # helper :product
86
- # ...
87
- # end
88
- #
89
- # This will make the <tt>ProductHelper</tt> from <tt>app/helpers/product_helper.rb</tt>
90
- # available from all state views from our <tt>ShoppingCartCell</tt>.
91
- #
92
- # == Cell inheritance
93
- #
94
- # Unlike controllers, Cells can form a class hierarchy. When a cell class
95
- # is inherited by another cell class, its states are inherited as regular
96
- # methods are, but also its views are inherited. Whenever a view is looked up,
97
- # the view finder first looks for a file in the directory belonging to the
98
- # current cell class, but if this is not found in the application or any
99
- # engine, the superclass' directory is checked. This continues all the
100
- # way up until it stops at ::Cell::Base.
101
- #
102
- # For instance, when you have two cells:
103
- # class MenuCell < ::Cell::Base
104
- # def show
105
- # end
106
- #
107
- # def edit
108
- # end
109
- # end
110
- #
111
- # class MainMenuCell < MenuCell
112
- # .. # no need to redefine show/edit if they do the same!
113
- # end
114
- # and the following directory structure in <tt>app/cells</tt>:
115
- # app/cells/
116
- # menu/
117
- # show.html.erb
118
- # edit.html.erb
119
- # main_menu/
120
- # show.html.erb
121
- # then when you call
122
- # render_cell :main_menu, :show
123
- # the main menu specific show.html.erb (<tt>app/cells/main_menu/show.html.erb</tt>)
124
- # is rendered, but when you call
125
- # render_cell :main_menu, :edit
126
- # cells notices that the main menu does not have a specific view for the
127
- # <tt>edit</tt> state, so it will render the view for the parent class,
128
- # <tt>app/cells/menu/edit.html.erb</tt>
129
- #
130
- #
131
- # == Gettext support
132
- #
133
- # Cells support gettext, just name your views accordingly. It works exactly equivalent
134
- # to controller views.
135
- #
136
- # cells/user/user_form.html.erb
137
- # cells/user/user_form_de.html.erb
138
- #
139
- # If gettext is set to DE_de, the latter view will be chosen.
140
- class Base
141
- include ::ActionController::Helpers
142
- include ::ActionController::RequestForgeryProtection
143
- include ActiveHelper
144
-
145
- class_inheritable_array :view_paths, :instance_writer => false
146
- write_inheritable_attribute(:view_paths, ActionView::PathSet.new) # Force use of a PathSet in this attribute, self.view_paths = ActionView::PathSet.new would still yield in an array
147
-
148
- class << self
149
- attr_accessor :request_forgery_protection_token
150
-
151
- # Use this if you want Cells to look up view templates
152
- # in directories other than the default.
153
- def view_paths=(paths)
154
- self.view_paths.clear.concat(paths) # don't let 'em overwrite the PathSet.
155
- end
156
-
157
- # A template file will be looked for in each view path. This is typically
158
- # just RAILS_ROOT/app/cells, but you might want to add e.g.
159
- # RAILS_ROOT/app/views.
160
- def add_view_path(path)
161
- path = File.join(::Rails.root, path) if defined?(::Rails) and ::Rails.respond_to?(:root)
162
- self.view_paths << path unless self.view_paths.include?(path)
163
- end
164
-
165
- # Creates a cell instance of the class <tt>name</tt>Cell, passing through
166
- # <tt>opts</tt>.
167
- def create_cell_for(controller, name, opts={})
168
- class_from_cell_name(name).new(controller, opts)
169
- end
170
-
171
- # Declare a controller method as a helper. For example,
172
- # helper_method :link_to
173
- # def link_to(name, options) ... end
174
- # makes the link_to controller method available in the view.
175
- def helper_method(*methods)
176
- methods.flatten.each do |method|
177
- master_helper_module.module_eval <<-end_eval
178
- def #{method}(*args, &block)
179
- @cell.send(:#{method}, *args, &block)
180
- end
181
- end_eval
182
- end
183
- end
184
-
185
- # Return the default view for the given state on this cell subclass.
186
- # This is a file with the name of the state under a directory with the
187
- # name of the cell followed by a template extension.
188
- def view_for_state(state)
189
- "#{cell_name}/#{state}"
190
- end
191
-
192
- # Find a possible template for a cell's current state. It tries to find a
193
- # template file with the name of the state under a subdirectory
194
- # with the name of the cell under the <tt>app/cells</tt> directory.
195
- # If this file cannot be found, it will try to call this method on
196
- # the superclass. This way you only have to write a state template
197
- # once when a more specific cell does not need to change anything in
198
- # that view.
199
- def find_class_view_for_state(state)
200
- return [view_for_state(state)] if superclass == ::Cell::Base
201
-
202
- superclass.find_class_view_for_state(state) << view_for_state(state)
203
- end
204
-
205
- # Get the name of this cell's class as an underscored string,
206
- # with _cell removed.
207
- #
208
- # Example:
209
- # UserCell.cell_name
210
- # => "user"
211
- def cell_name
212
- name.underscore.sub(/_cell/, '')
213
- end
214
-
215
- # Given a cell name, finds the class that belongs to it.
216
- #
217
- # Example:
218
- # ::Cell::Base.class_from_cell_name(:user)
219
- # => UserCell
220
- def class_from_cell_name(cell_name)
221
- "#{cell_name}_cell".classify.constantize
222
- end
223
-
224
- def state2view_cache
225
- @state2view_cache ||= {}
226
- end
227
-
228
- def cache_configured?
229
- ::ActionController::Base.cache_configured?
230
- end
231
- end
232
-
233
- class MissingTemplate < ActionView::ActionViewError
234
- def initialize(message, possible_paths)
235
- super(message + " and possible paths #{possible_paths}")
236
- end
237
- end
238
-
239
- class_inheritable_accessor :allow_forgery_protection
240
- self.allow_forgery_protection = true
241
-
242
- class_inheritable_accessor :default_template_format
243
- self.default_template_format = :html
244
-
245
- delegate :params, :session, :request, :logger, :to => :controller
246
-
247
- attr_accessor :controller
248
- attr_reader :state_name
249
-
250
- def initialize(controller, options={})
251
- @controller = controller
252
- @opts = options
253
- end
254
-
255
- def cell_name
256
- self.class.cell_name
257
- end
258
-
259
- # Render the given state. You can pass the name as either a symbol or
260
- # a string.
261
- def render_state(state)
262
- @cell = self
263
- @state_name = state
264
-
265
- content = dispatch_state(state)
266
-
267
- return content if content.kind_of? String
268
-
269
- render_view_for_backward_compat(content, state)
270
- end
271
-
272
- # Call the state method.
273
- def dispatch_state(state)
274
- send(state)
275
- end
276
-
277
- # We will soon remove the implicit call to render_view_for, but here it is for your convenience.
278
- def render_view_for_backward_compat(opts, state)
279
- ::ActiveSupport::Deprecation.warn "You either didn't call #render or forgot to return a string in the state method '#{state}'. However, returning nil is deprecated for the sake of explicitness"
280
-
281
- render_view_for(opts, state)
282
- end
283
-
284
- # Renders the view for the current state and returns the markup for the component.
285
- # Usually called and returned at the end of a state method.
286
- #
287
- # ==== Options
288
- # * <tt>:view</tt> - Specifies the name of the view file to render. Defaults to the current state name.
289
- # * <tt>:template_format</tt> - Allows using a format different to <tt>:html</tt>.
290
- # * <tt>:layout</tt> - If set to a valid filename inside your cell's view_paths, the current state view will be rendered inside the layout (as known from controller actions). Layouts should reside in <tt>app/cells/layouts</tt>.
291
- # * <tt>:locals</tt> - Makes the named parameters available as variables in the view.
292
- # * <tt>:text</tt> - Just renders plain text.
293
- # * <tt>:inline</tt> - Renders an inline template as state view. See ActionView::Base#render for details.
294
- # * <tt>:file</tt> - Specifies the name of the file template to render.
295
- # * <tt>:nothing</tt> - Will make the component kinda invisible and doesn't invoke the rendering cycle.
296
- # * <tt>:state</tt> - Instantly invokes another rendering cycle for the passed state and returns.
297
- # Example:
298
- # class MyCell < ::Cell::Base
299
- # def my_first_state
300
- # # ... do something
301
- # render
302
- # end
303
- #
304
- # will just render the view <tt>my_first_state.html</tt>.
305
- #
306
- # def my_first_state
307
- # # ... do something
308
- # render :view => :my_first_state, :layout => 'metal'
309
- # end
310
- #
311
- # will also use the view <tt>my_first_state.html</tt> as template and even put it in the layout
312
- # <tt>metal</tt> that's located at <tt>$RAILS_ROOT/app/cells/layouts/metal.html.erb</tt>.
313
- #
314
- # def say_your_name
315
- # render :locals => {:name => "Nick"}
316
- # end
317
- #
318
- # will make the variable +name+ available in the view <tt>say_your_name.html</tt>.
319
- #
320
- # def say_your_name
321
- # render :nothing => true
322
- # end
323
- #
324
- # will render an empty string thus keeping your name a secret.
325
- #
326
- #
327
- # ==== Where have all the partials gone?
328
- # In Cells we abandoned the term 'partial' in favor of plain 'views' - we don't need to distinguish
329
- # between both terms. A cell view is both, a view and a kind of partial as it represents only a small
330
- # part of the page.
331
- # Just use <tt>:view</tt> and enjoy.
332
- def render(opts={})
333
- render_view_for(opts, @state_name) ### FIXME: i don't like the magic access to @state_name here. ugly!
334
- end
335
-
336
- # Render the view belonging to the given state. Will raise ActionView::MissingTemplate
337
- # if it can not find one of the requested view template. Note that this behaviour was
338
- # introduced in cells 2.3 and replaces the former warning message.
339
- def render_view_for(opts, state)
340
- return '' if opts[:nothing]
341
-
342
- action_view = setup_action_view
343
-
344
- ### TODO: dispatch dynamically:
345
- if opts[:text]
346
- elsif opts[:inline]
347
- elsif opts[:file]
348
- elsif opts[:state]
349
- opts[:text] = render_state(opts[:state])
350
- else
351
- # handle :layout, :template_format, :view
352
- opts = defaultize_render_options_for(opts, state)
353
-
354
- # set instance vars, include helpers:
355
- prepare_action_view_for(action_view, opts)
356
-
357
- template = find_family_view_for_state_with_caching(opts[:view], action_view)
358
- opts[:file] = template
359
- end
360
-
361
- opts = sanitize_render_options(opts)
362
-
363
- action_view.render_for(opts)
364
- end
365
-
366
- # Defaultize the passed options from #render.
367
- def defaultize_render_options_for(opts, state)
368
- opts[:template_format] ||= self.class.default_template_format
369
- opts[:view] ||= state
370
- opts
371
- end
372
-
373
- def prepare_action_view_for(action_view, opts)
374
- # make helpers available:
375
- include_helpers_in_class(action_view.class)
376
-
377
- import_active_helpers_into(action_view) # in Cells::Cell::ActiveHelper.
378
-
379
- action_view.assigns = assigns_for_view # make instance vars available.
380
- action_view.template_format = opts[:template_format]
381
- end
382
-
383
- def setup_action_view
384
- view_class = Class.new(::Cells::Cell::View)
385
- action_view = view_class.new(self.class.view_paths, {}, @controller)
386
- action_view.cell = self
387
- action_view
388
- end
389
-
390
- # Prepares <tt>opts</tt> to be passed to ActionView::Base#render by removing
391
- # unknown parameters.
392
- def sanitize_render_options(opts)
393
- opts.except!(:view, :state)
394
- end
395
-
396
- # Climbs up the inheritance hierarchy of the Cell, looking for a view
397
- # for the current <tt>state</tt> in each level.
398
- # As soon as a view file is found it is returned as an ActionView::Template
399
- # instance.
400
- ### DISCUSS: moved to Cell::View#find_template in rainhead's fork:
401
- def find_family_view_for_state(state, action_view)
402
- missing_template_exception = nil
403
- possible_paths = possible_paths_for_state(state)
404
-
405
- possible_paths.each do |template_path|
406
- # we need to catch MissingTemplate, since we want to try for all possible
407
- # family views.
408
- begin
409
- if view = action_view.try_picking_template_for_path(template_path)
410
- return view
411
- end
412
- rescue ::ActionView::MissingTemplate => missing_template_exception
413
- end
414
- end
415
-
416
- raise MissingTemplate.new(missing_template_exception.message, possible_paths)
417
- end
418
-
419
- # In production mode, the view for a state/template_format is cached.
420
- ### DISCUSS: ActionView::Base already caches results for #pick_template, so maybe
421
- ### we should just cache the family path for a state/format?
422
- def find_family_view_for_state_with_caching(state, action_view)
423
- return find_family_view_for_state(state, action_view) unless self.class.cache_configured?
424
-
425
- # in production mode:
426
- key = "#{state}/#{action_view.template_format}"
427
- state2view = self.class.state2view_cache
428
- state2view[key] || state2view[key] = find_family_view_for_state(state, action_view)
429
- end
430
-
431
- # Find possible files that belong to the state. This first tries the cell's
432
- # <tt>#view_for_state</tt> method and if that returns a true value, it
433
- # will accept that value as a string and interpret it as a pathname for
434
- # the view file. If it returns a falsy value, it will call the Cell's class
435
- # method find_class_view_for_state to determine the file to check.
436
- #
437
- # You can override the ::Cell::Base#view_for_state method for a particular
438
- # cell if you wish to make it decide dynamically what file to render.
439
- def possible_paths_for_state(state)
440
- self.class.find_class_view_for_state(state).reverse!
441
- end
442
-
443
- # Prepares the hash {instance_var => value, ...} that should be available
444
- # in the ActionView when rendering the state view.
445
- def assigns_for_view
446
- assigns = {}
447
- (self.instance_variables - ivars_to_ignore).each do |k|
448
- assigns[k[1..-1]] = instance_variable_get(k)
449
- end
450
- assigns
451
- end
452
-
453
- # When passed a copy of the ActionView::Base class, it
454
- # will mix in all helper classes for this cell in that class.
455
- def include_helpers_in_class(view_klass)
456
- view_klass.send(:include, self.class.master_helper_module)
457
- end
458
-
459
- # Defines the instance variables that should <em>not</em> be copied to the
460
- # View instance.
461
- def ivars_to_ignore; ['@controller']; end
462
-
463
- ### TODO: allow log levels.
464
- def log(message)
465
- return unless @controller.logger
466
- @controller.logger.debug(message)
467
- end
468
- end
469
- end
470
- end