cells 3.3.10 → 3.4.0.beta1

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.
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