cells 3.11.3 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +15 -13
  4. data/Appraisals +23 -0
  5. data/CHANGES.md +20 -3
  6. data/Gemfile +5 -7
  7. data/README.md +317 -236
  8. data/Rakefile +1 -1
  9. data/TODO.md +3 -0
  10. data/cells.gemspec +19 -28
  11. data/gemfiles/rails3.2.gemfile +14 -0
  12. data/gemfiles/rails4.0.gemfile +14 -0
  13. data/gemfiles/rails4.1.gemfile +15 -0
  14. data/gemfiles/rails4.2.gemfile +14 -0
  15. data/lib/cell.rb +28 -21
  16. data/lib/cell/caching.rb +10 -22
  17. data/lib/cell/caching/notification.rb +15 -0
  18. data/lib/cell/concept.rb +4 -69
  19. data/lib/cell/development.rb +11 -0
  20. data/lib/{cells → cell}/engines.rb +1 -1
  21. data/lib/cell/layout.rb +20 -0
  22. data/lib/cell/partial.rb +17 -0
  23. data/lib/cell/{base/prefixes.rb → prefixes.rb} +1 -1
  24. data/lib/cell/rails.rb +58 -50
  25. data/lib/cell/railtie.rb +60 -0
  26. data/lib/cell/{base/self_contained.rb → self_contained.rb} +1 -1
  27. data/lib/cell/templates.rb +60 -0
  28. data/lib/cell/test_case.rb +4 -162
  29. data/lib/cell/testing.rb +15 -0
  30. data/lib/cell/twin.rb +11 -29
  31. data/lib/cell/version.rb +10 -0
  32. data/lib/cell/view_model.rb +196 -88
  33. data/lib/cells.rb +1 -20
  34. data/lib/rails/generators/cell/cell_generator.rb +43 -0
  35. data/lib/rails/generators/cell/templates/cell.rb.erb +8 -0
  36. data/lib/{generators/templates/concept → rails/generators/cell/templates}/view.erb +0 -0
  37. data/lib/{generators/templates/concept → rails/generators/cell/templates}/view.haml +0 -0
  38. data/lib/rails/generators/cell/templates/view.slim +2 -0
  39. data/lib/rails/generators/concept/concept_generator.rb +38 -0
  40. data/lib/{generators/templates/concept/cell.rb → rails/generators/concept/templates/concept.rb.erb} +2 -2
  41. data/lib/{generators → rails/generators/concept}/templates/view.erb +0 -0
  42. data/lib/{generators → rails/generators/concept}/templates/view.haml +0 -0
  43. data/lib/rails/generators/concept/templates/view.slim +2 -0
  44. data/lib/rails/generators/test_unit/cell/cell_generator.rb +21 -0
  45. data/lib/{generators/templates/cell_test.rb → rails/generators/test_unit/cell/templates/unit_test.rb.erb} +3 -3
  46. data/lib/rails/generators/test_unit/concept/concept_generator.rb +21 -0
  47. data/lib/rails/generators/test_unit/concept/templates/unit_test.rb.erb +11 -0
  48. data/lib/{cells → tasks}/cells.rake +0 -0
  49. data/test/builder_test.rb +58 -0
  50. data/test/caching_test.rb +298 -0
  51. data/test/cell_benchmark.rb +32 -0
  52. data/test/cell_generator_test.rb +51 -82
  53. data/test/cell_test.rb +8 -23
  54. data/test/concept_generator_test.rb +22 -13
  55. data/test/concept_test.rb +41 -75
  56. data/test/dummy/app/views/musician/hamlet.html.erb +1 -0
  57. data/test/dummy/config/application.rb +21 -8
  58. data/test/{app/cells/bassist/play.html.erb → fixtures/bassist/play.erb} +0 -0
  59. data/test/fixtures/concepts/record/views/layout.erb +1 -0
  60. data/test/{app → fixtures}/concepts/record/views/show.erb +0 -0
  61. data/test/{app → fixtures}/concepts/record/views/song.erb +0 -0
  62. data/test/fixtures/inherit_views_test/popper/tap.erb +1 -0
  63. data/test/fixtures/inherit_views_test/tapper/play.erb +1 -0
  64. data/test/fixtures/inherit_views_test/tapper/tap.erb +1 -0
  65. data/test/fixtures/partial_test/with_partial/show.erb +1 -0
  66. data/test/fixtures/partials/_show.html.erb +1 -0
  67. data/test/fixtures/partials/_show.xml.erb +1 -0
  68. data/test/fixtures/song/ivar.erb +1 -0
  69. data/test/fixtures/song/show.erb +1 -0
  70. data/test/fixtures/song/with_erb.erb +4 -0
  71. data/test/fixtures/song/with_html.erb +1 -0
  72. data/test/fixtures/song/with_locals.erb +2 -0
  73. data/test/fixtures/song_with_layout/happy.erb +1 -0
  74. data/test/fixtures/song_with_layout/merry.erb +1 -0
  75. data/test/fixtures/song_with_layout/show.erb +1 -0
  76. data/test/fixtures/song_with_layout/show_with_layout.erb +1 -0
  77. data/test/fixtures/templates_caching_test/song/show.erb +1 -0
  78. data/test/fixtures/url_helper_test/song/edit.erb +8 -0
  79. data/test/fixtures/url_helper_test/song/with_block.erb +2 -0
  80. data/test/fixtures/url_helper_test/song/with_capture.erb +4 -0
  81. data/test/fixtures/url_helper_test/song/with_content_tag.erb +6 -0
  82. data/test/fixtures/url_helper_test/song/with_form_for_block.erb +3 -0
  83. data/test/fixtures/url_helper_test/song/with_link_to.erb +3 -0
  84. data/test/layout_test.rb +57 -0
  85. data/test/partial_test.rb +27 -0
  86. data/test/prefixes_test.rb +36 -10
  87. data/test/public_test.rb +42 -0
  88. data/test/rails_extensions_test.rb +51 -0
  89. data/test/render_test.rb +103 -0
  90. data/test/templates_test.rb +45 -0
  91. data/test/test_case_test.rb +21 -122
  92. data/test/test_helper.rb +37 -33
  93. data/test/twin_test.rb +3 -7
  94. data/test/url_helper_test.rb +89 -0
  95. metadata +92 -357
  96. data/gemfiles/Gemfile.rails3-0 +0 -7
  97. data/gemfiles/Gemfile.rails3-1 +0 -7
  98. data/gemfiles/Gemfile.rails3-2 +0 -7
  99. data/gemfiles/Gemfile.rails4-0 +0 -12
  100. data/gemfiles/Gemfile.rails4-1 +0 -12
  101. data/lib/cell/base.rb +0 -82
  102. data/lib/cell/base/view.rb +0 -15
  103. data/lib/cell/builder.rb +0 -71
  104. data/lib/cell/deprecations.rb +0 -41
  105. data/lib/cell/dsl.rb +0 -7
  106. data/lib/cell/rack.rb +0 -32
  107. data/lib/cell/rails/helper_api.rb +0 -37
  108. data/lib/cell/rails/view_model.rb +0 -159
  109. data/lib/cell/rails3_0_strategy.rb +0 -82
  110. data/lib/cell/rails3_1_strategy.rb +0 -40
  111. data/lib/cell/rails4_0_strategy.rb +0 -39
  112. data/lib/cell/rails4_1_strategy.rb +0 -40
  113. data/lib/cell/rendering.rb +0 -109
  114. data/lib/cells/rails.rb +0 -86
  115. data/lib/cells/railtie.rb +0 -38
  116. data/lib/cells/version.rb +0 -3
  117. data/lib/generators/USAGE +0 -30
  118. data/lib/generators/cells/base.rb +0 -22
  119. data/lib/generators/cells/cell_generator.rb +0 -15
  120. data/lib/generators/cells/view_generator.rb +0 -18
  121. data/lib/generators/erb/cell_generator.rb +0 -15
  122. data/lib/generators/erb/concept_generator.rb +0 -17
  123. data/lib/generators/haml/cell_generator.rb +0 -17
  124. data/lib/generators/haml/concept_generator.rb +0 -17
  125. data/lib/generators/rails/cell_generator.rb +0 -16
  126. data/lib/generators/rails/concept_generator.rb +0 -16
  127. data/lib/generators/slim/cell_generator.rb +0 -17
  128. data/lib/generators/templates/cell.rb +0 -9
  129. data/lib/generators/templates/view.slim +0 -4
  130. data/lib/generators/test_unit/cell_generator.rb +0 -14
  131. data/lib/generators/trailblazer/base.rb +0 -21
  132. data/lib/generators/trailblazer/view_generator.rb +0 -18
  133. data/test/app/cells/album/views/cover.haml +0 -1
  134. data/test/app/cells/bad_guitarist/_dii.html.erb +0 -1
  135. data/test/app/cells/bad_guitarist_cell.rb +0 -2
  136. data/test/app/cells/bassist/_dii.html.erb +0 -1
  137. data/test/app/cells/bassist/ahem.html.erb +0 -1
  138. data/test/app/cells/bassist/compose.html.erb +0 -1
  139. data/test/app/cells/bassist/contact_form.html.erb +0 -1
  140. data/test/app/cells/bassist/form_for.erb +0 -3
  141. data/test/app/cells/bassist/form_for_in_haml.haml +0 -2
  142. data/test/app/cells/bassist/jam.html.erb +0 -3
  143. data/test/app/cells/bassist/play.js.erb +0 -1
  144. data/test/app/cells/bassist/pose.html.erb +0 -1
  145. data/test/app/cells/bassist/promote.html.erb +0 -1
  146. data/test/app/cells/bassist/provoke.html.erb +0 -1
  147. data/test/app/cells/bassist/shout.html.erb +0 -1
  148. data/test/app/cells/bassist/sing.html.haml +0 -1
  149. data/test/app/cells/bassist/slap.html.erb +0 -1
  150. data/test/app/cells/bassist/yell.en.html.erb +0 -1
  151. data/test/app/cells/bassist_cell.rb +0 -25
  152. data/test/app/cells/club_security.rb +0 -2
  153. data/test/app/cells/club_security/guard/help.html.erb +0 -1
  154. data/test/app/cells/club_security/guard_cell.rb +0 -6
  155. data/test/app/cells/club_security/medic/help.html.erb +0 -1
  156. data/test/app/cells/club_security/medic_cell.rb +0 -8
  157. data/test/app/cells/layouts/b.erb +0 -1
  158. data/test/app/cells/layouts/metal.html.erb +0 -1
  159. data/test/app/cells/rails_helper_api_test/bassist/edit.html.erb +0 -5
  160. data/test/app/cells/shouter/sing.html.erb +0 -1
  161. data/test/app/cells/song/dashboard.haml +0 -7
  162. data/test/app/cells/song/details.html.haml +0 -1
  163. data/test/app/cells/song/info.html.haml +0 -1
  164. data/test/app/cells/song/lyrics.html.haml +0 -6
  165. data/test/app/cells/song/plays.haml +0 -1
  166. data/test/app/cells/song/scale.haml +0 -1
  167. data/test/app/cells/song/show.html.haml +0 -3
  168. data/test/app/cells/song/title.html.haml +0 -1
  169. data/test/app/cells/trumpeter/promote.html.erb +0 -1
  170. data/test/app/cells/trumpeter_cell.rb +0 -8
  171. data/test/app/cells/view_model_test/comments/show.haml +0 -7
  172. data/test/app/concepts/record/views/layout.haml +0 -2
  173. data/test/app/views/shared/_dong.html.erb +0 -1
  174. data/test/cell_module_test.rb +0 -170
  175. data/test/cells_module_test.rb +0 -27
  176. data/test/deprecations_test.rb +0 -101
  177. data/test/dummy/app/helpers/application_helper.rb +0 -2
  178. data/test/dummy/app/views/musician/hamlet.html.haml +0 -1
  179. data/test/dummy/config/environments/development.rb +0 -16
  180. data/test/dummy/config/environments/production.rb +0 -46
  181. data/test/dummy/config/environments/test.rb +0 -33
  182. data/test/dummy/db/test.sqlite3 +0 -0
  183. data/test/dummy/label/app/cells/label/show.erb +0 -1
  184. data/test/dummy/label/app/cells/label_cell.rb +0 -5
  185. data/test/dummy/label/label.gemspec +0 -20
  186. data/test/dummy/label/lib/label.rb +0 -4
  187. data/test/dummy/label/lib/label/version.rb +0 -3
  188. data/test/dummy/public/404.html +0 -26
  189. data/test/dummy/public/422.html +0 -26
  190. data/test/dummy/public/500.html +0 -26
  191. data/test/dummy/public/favicon.ico +0 -0
  192. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  193. data/test/helper_test.rb +0 -81
  194. data/test/rack_test.rb +0 -32
  195. data/test/rails/asset_pipeline_test.rb +0 -20
  196. data/test/rails/caching_test.rb +0 -456
  197. data/test/rails/cells_test.rb +0 -119
  198. data/test/rails/forms_test.rb +0 -75
  199. data/test/rails/integration_test.rb +0 -299
  200. data/test/rails/render_test.rb +0 -189
  201. data/test/rails/view_model_test.rb +0 -226
  202. data/test/rails/view_test.rb +0 -49
  203. data/test/rails_helper_api_test.rb +0 -58
  204. data/test/self_contained_test.rb +0 -31
@@ -1,20 +1 @@
1
- module Cells
2
- # Setup your special needs for Cells here. Use this to add new view paths.
3
- #
4
- # Example:
5
- #
6
- # Cells.setup do |config|
7
- # config.append_view_path "app/view_models"
8
- # end
9
- #
10
- def self.setup
11
- yield(Cell::Rails)
12
- end
13
- end
14
-
15
- require 'cell'
16
- require 'cell/rails'
17
- require 'cells/rails'
18
- require 'cell/deprecations'
19
- require 'cells/engines'
20
- require 'cells/railtie'
1
+ require 'cell'
@@ -0,0 +1,43 @@
1
+ module Rails
2
+ module Generators
3
+ class CellGenerator < NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ class_option :parent, type: :string, desc: 'The parent class for the generated cell'
7
+ class_option :e, type: :string, desc: 'The template engine'
8
+
9
+ check_class_collision suffix: 'Cell'
10
+
11
+ argument :actions, type: :array, default: [], banner: 'action action2'
12
+
13
+ def create_cell_file
14
+ template 'cell.rb.erb', File.join('app/cells', class_path, "#{file_name}_cell.rb")
15
+ end
16
+
17
+ def create_view_files
18
+ states.each do |state|
19
+ @state = state
20
+ @path = File.join('app/cells', class_path, file_name, "#{state}.#{template_engine}")
21
+ template "view.#{template_engine}", @path
22
+ end
23
+ end
24
+
25
+ hook_for :test_framework
26
+
27
+ private
28
+
29
+ def parent_class_name
30
+ options[:parent] || 'Cell::ViewModel'
31
+ end
32
+
33
+ # The show state is included by default
34
+ def states
35
+ (['show'] + actions).uniq
36
+ end
37
+
38
+ def template_engine
39
+ (options[:e] || Rails.application.config.app_generators.rails[:template_engine] || 'erb').to_s
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+ class <%= class_name %>Cell < <%= parent_class_name %>
2
+ <% states.each do |state| -%>
3
+ def <%= state %>
4
+ render
5
+ end
6
+
7
+ <% end -%>
8
+ end
@@ -0,0 +1,2 @@
1
+ h1 <%= class_name %>#<%= @state %>
2
+ p Find me in <%= @path %>
@@ -0,0 +1,38 @@
1
+ module Rails
2
+ module Generators
3
+ class ConceptGenerator < NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ class_option :e, type: :string, desc: 'The template engine'
7
+ argument :actions, type: :array, default: [], banner: 'action action2'
8
+
9
+ check_class_collision suffix: 'Concept'
10
+
11
+
12
+ def create_concept
13
+ template 'concept.rb.erb', File.join('app/concepts', class_path, file_name, 'cell.rb')
14
+ end
15
+
16
+ def create_views
17
+ states.each do |state|
18
+ @state = state
19
+ @path = File.join('app/concepts', class_path, file_name, 'views', "#{state}.#{template_engine}")
20
+ template "view.#{template_engine}", @path
21
+ end
22
+ end
23
+
24
+ hook_for :test_framework
25
+
26
+ private
27
+
28
+ def template_engine
29
+ (options[:e] || Rails.application.config.app_generators.rails[:template_engine] || 'erb').to_s
30
+ end
31
+
32
+ # The show state is included by default
33
+ def states
34
+ (['show'] + actions).uniq
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,6 @@
1
1
  class <%= class_name %>::Cell < Cell::Concept
2
- <% for action in actions -%>
3
- def <%= action %>
2
+ <% states.each do |state| -%>
3
+ def <%= state %>
4
4
  render
5
5
  end
6
6
  <% end -%>
@@ -0,0 +1,2 @@
1
+ h1 <%= class_name %>#<%= @state %>
2
+ p Find me in <%= @path %>
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/test_unit'
2
+
3
+ module TestUnit # :nodoc:
4
+ module Generators # :nodoc:
5
+ class CellGenerator < Base # :nodoc:
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :actions, type: :array, default: []
8
+ check_class_collision suffix: 'CellTest'
9
+
10
+ def create_test_file
11
+ template 'unit_test.rb.erb', File.join('test/cells', class_path, "#{file_name}_cell_test.rb")
12
+ end
13
+
14
+ private
15
+
16
+ def states
17
+ (['show'] + actions).uniq
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,11 +1,11 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class <%= class_name %>CellTest < Cell::TestCase
4
- <% for state in @states -%>
4
+ <% states.each do |state| -%>
5
5
  test "<%= state %>" do
6
6
  invoke :<%= state %>
7
- assert_select "p"
7
+ assert_select 'p'
8
8
  end
9
-
9
+
10
10
  <% end %>
11
11
  end
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/test_unit'
2
+
3
+ module TestUnit # :nodoc:
4
+ module Generators # :nodoc:
5
+ class ConceptGenerator < Base # :nodoc:
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :actions, type: :array, default: []
8
+ check_class_collision suffix: 'ConceptTest'
9
+
10
+ def create_test_file
11
+ template 'unit_test.rb.erb', File.join('test/concepts', class_path, file_name, 'cell_test.rb')
12
+ end
13
+
14
+ private
15
+
16
+ def states
17
+ (['show'] + actions).uniq
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ class <%= class_name %>ConceptTest < Cell::TestCase
4
+ <% states.each do |state| -%>
5
+ test "<%= state %>" do
6
+ invoke :<%= state %>
7
+ assert_select 'p'
8
+ end
9
+
10
+ <% end %>
11
+ end
File without changes
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ class BuilderTest < MiniTest::Spec
4
+ Song = Struct.new(:title)
5
+ Hit = Struct.new(:title)
6
+
7
+ class SongCell < Cell::ViewModel
8
+ builds do |model, options|
9
+ if model.is_a? Hit
10
+ HitCell
11
+ elsif options[:evergreen]
12
+ EvergreenCell
13
+ end
14
+ end
15
+
16
+ def options
17
+ @options
18
+ end
19
+
20
+ def show
21
+ "* #{title}"
22
+ end
23
+
24
+ property :title
25
+ end
26
+
27
+ class HitCell < SongCell
28
+ def show
29
+ "* **#{title}**"
30
+ end
31
+ end
32
+
33
+ class EvergreenCell < SongCell
34
+ end
35
+
36
+ # the original class is used when no builder matches.
37
+ it { Cell::ViewModel.cell("builder_test/song", nil, Song.new("Nation States"), {}).must_be_instance_of BuilderTest::SongCell }
38
+
39
+ it do
40
+ cell = Cell::ViewModel.cell("builder_test/song", nil, Hit.new("New York"), {})
41
+ cell.must_be_instance_of BuilderTest::HitCell
42
+ cell.options.must_equal({})
43
+ end
44
+
45
+ it do
46
+ cell = Cell::ViewModel.cell("builder_test/song", nil, Song.new("San Francisco"), evergreen: true)
47
+ cell.must_be_instance_of BuilderTest::EvergreenCell
48
+ cell.options.must_equal({:evergreen=>true})
49
+ end
50
+
51
+ # with collection.
52
+ it { Cell::ViewModel.cell("builder_test/song", nil, collection: [Song.new("Nation States"), Hit.new("New York")]).must_equal "* Nation States* **New York**" }
53
+
54
+ # with Concept
55
+ class Track < Cell::Concept
56
+ end
57
+ it { Cell::Concept.cell("builder_test/track", nil).must_be_instance_of Track }
58
+ end
@@ -0,0 +1,298 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ class DirectorCell < Cell::ViewModel
5
+ attr_reader :count
6
+
7
+ def initialize(*)
8
+ super
9
+ @count = 0
10
+ end
11
+
12
+ cache :tock
13
+
14
+ def tock
15
+ @count += 1
16
+ end
17
+ end
18
+
19
+
20
+ class CachingUnitTest < MiniTest::Spec
21
+ before :each do
22
+ ActionController::Base.cache_store.clear
23
+ ActionController::Base.perform_caching = true
24
+ end
25
+
26
+ let (:director) { DirectorCell }
27
+ let (:cellule) { DirectorCell.new(nil) }
28
+
29
+
30
+ describe "::state_cache_key" do
31
+ # accepts state name, only.
32
+ it { director.state_cache_key(:count).must_equal "cells/director/count/" }
33
+
34
+ # accepts hash as key parts
35
+ if Cell.rails_version >= Gem::Version.new('4.0')
36
+ it { director.state_cache_key(:count, b: 2, a: 1).must_equal "cells/director/count/b/2/a/1" }
37
+ else
38
+ it { director.state_cache_key(:count, b: 2, a: 1).must_equal "cells/director/count/a=1&b=2" }
39
+ end
40
+
41
+ # accepts array as key parts
42
+ it { director.state_cache_key(:count, [1, 2, 3]).must_equal "cells/director/count/1/2/3" }
43
+
44
+ # accepts string as key parts
45
+ it { director.state_cache_key(:count, "1/2").must_equal "cells/director/count/1/2" }
46
+
47
+ # accepts nil as key parts
48
+ it { director.state_cache_key(:count, nil).must_equal "cells/director/count/" }
49
+ end
50
+
51
+
52
+ describe "#state_cached?" do
53
+ # true for cached
54
+ it { cellule.send(:state_cached?, :tock).must_equal true }
55
+
56
+ # false otherwise
57
+ it { cellule.send(:state_cached?, :sing).must_equal false }
58
+ end
59
+
60
+
61
+ describe "#cache?" do
62
+ # true for cached
63
+ it { cellule.cache?(:tock).must_equal true }
64
+
65
+ # false otherwise
66
+ it { cellule.cache?(:sing).must_equal false }
67
+
68
+ describe "perform_caching turned off" do
69
+ after do
70
+ ::ActionController::Base.perform_caching = true
71
+ end
72
+
73
+ # always false
74
+ it do
75
+ ::ActionController::Base.perform_caching = false
76
+ cellule.cache?(:sing).must_equal false
77
+ cellule.cache?(:sing).must_equal false
78
+ end
79
+ end
80
+
81
+ describe "#cache_store" do
82
+ # rails cache store per default.
83
+ it { cellule.cache_store.must_equal ActionController::Base.cache_store }
84
+ end
85
+ end
86
+
87
+
88
+ # describe ".expire_cache_key" do
89
+ # before :each do
90
+ # @key = @class.state_cache_key(:tock)
91
+ # puts "====== key is #{@key}"
92
+ # assert_equal "1", render_cell(:director, :tock)
93
+ # assert_equal "1", @class.cache_store.read(@key)
94
+ # end
95
+
96
+ # it "delete the state from cache" do
97
+ # @class.expire_cache_key(@key)
98
+ # assert_not @class.cache_store.read(@key)
99
+ # end
100
+
101
+ # it "be available in controllers for sweepers" do
102
+ # MusicianController.new.expire_cell_state(DirectorCell, :tock)
103
+ # assert_not @class.cache_store.read(@key)
104
+ # end
105
+
106
+ # it "accept cache options" do
107
+ # key = @class.state_cache_key(:tock, :volume => 9)
108
+ # assert Cell::Rails.cache_store.write(key, 'ONE!')
109
+
110
+ # MusicianController.new.expire_cell_state(DirectorCell, :tock, :volume => 9)
111
+ # assert_equal "1", @class.cache_store.read(@key)
112
+ # assert_not ::Cell::Rails.cache_store.read(key)
113
+ # end
114
+ # end
115
+ end
116
+
117
+
118
+ class CachingTest < MiniTest::Spec
119
+ class DirectorCell < Cell::ViewModel
120
+ def initialize(controller, counter=0)
121
+ super
122
+ @counter = counter
123
+ end
124
+
125
+ def show # public method.
126
+ @counter
127
+ end
128
+
129
+
130
+ cache :utf8
131
+
132
+ def utf8
133
+ "æøå" # or any other UTF-8 string
134
+ end
135
+ end
136
+
137
+ before :each do
138
+ ActionController::Base.cache_store.clear
139
+ ActionController::Base.perform_caching = true
140
+ end
141
+
142
+ # let (:cell) { DirectorCell.new(nil) }
143
+ def cellule(*args)
144
+ DirectorCell.new(nil, *args)
145
+ end
146
+
147
+ # no caching when turned off.
148
+ it do
149
+ cellule.class.cache :show
150
+ ActionController::Base.perform_caching = false
151
+
152
+ cellule(1).call.must_equal "1"
153
+ cellule(2).call.must_equal "2"
154
+ end
155
+
156
+ # cache forever when no options.
157
+ it do
158
+ cellule.class.cache :show
159
+ cellule(1).call.must_equal "1"
160
+ cellule(2).call.must_equal "1"
161
+ end
162
+
163
+
164
+ # no caching when state not configured.
165
+ it do
166
+ cellule.class.class_eval do
167
+ def dictate
168
+ @counter
169
+ end
170
+ end
171
+
172
+ cellule(1).call(:dictate).must_equal "1"
173
+ cellule(2).call(:dictate).must_equal "2"
174
+ end
175
+
176
+ # compute key with cell properties from #initialize.
177
+ it do
178
+ cellule.class.cache :show do
179
+ @counter < 3 ? {:count => "<"} : {:count => ">"}
180
+ end
181
+
182
+ cellule(1).call.must_equal "1"
183
+ cellule(2).call.must_equal "1"
184
+ cellule(3).call.must_equal "3"
185
+ cellule(4).call.must_equal "3"
186
+ end
187
+
188
+ # compute key with instance method
189
+ it do
190
+ cellule.class.cache :show, :version
191
+ cellule.class.class_eval do
192
+ def version
193
+ @counter < 3 ? {:count => "<"} : {:count => ">"}
194
+ end
195
+ end
196
+
197
+ cellule(1).call.must_equal "1"
198
+ cellule(2).call.must_equal "1"
199
+ cellule(3).call.must_equal "3"
200
+ cellule(4).call.must_equal "3"
201
+ end
202
+
203
+ # allow returning strings for key
204
+ it do
205
+ cellule.class.cache :show do
206
+ @counter < 3 ? "<" : ">"
207
+ end
208
+
209
+ cellule(1).call.must_equal "1"
210
+ cellule(2).call.must_equal "1"
211
+ cellule(3).call.must_equal "3"
212
+ cellule(4).call.must_equal "3"
213
+ end
214
+
215
+ # allows conditional ifs.
216
+ it do
217
+ cellule.class.cache :show, if: lambda { @counter < 3 }
218
+
219
+ cellule(1).call.must_equal "1"
220
+ cellule(2).call.must_equal "1"
221
+ cellule(3).call.must_equal "3"
222
+ cellule(4).call.must_equal "4"
223
+ end
224
+
225
+ # allows conditional ifs with instance method.
226
+ it do
227
+ cellule.class.class_eval do
228
+ cache :show, if: :smaller?
229
+
230
+ def smaller?
231
+ @counter < 3
232
+ end
233
+ end
234
+
235
+ cellule(1).call.must_equal "1"
236
+ cellule(2).call.must_equal "1"
237
+ cellule(3).call.must_equal "3"
238
+ cellule(4).call.must_equal "4"
239
+ end
240
+
241
+
242
+ unless ::ActionPack::VERSION::MAJOR == 3 and ::ActionPack::VERSION::MINOR >= 2 # bug in 3.2.
243
+ describe "utf-8" do
244
+ before do
245
+ @key = cellule.class.state_cache_key(:utf8)
246
+ end
247
+
248
+ it "has the correct encoding when reading from cache" do
249
+ assert_equal "UTF-8", cellule.call(:utf8).encoding.to_s
250
+ assert_equal "UTF-8", cellule.cache_store.read(@key).encoding.to_s
251
+ end
252
+ end
253
+ end
254
+
255
+ # options are passed through to cache store.
256
+ # :expires_in.
257
+ # :tags => lambda { |one, two, three| "#{one},#{two},#{three}" }
258
+ class CacheStore
259
+ attr_reader :fetch_args
260
+
261
+ def fetch(*args)
262
+ @fetch_args = args
263
+ end
264
+ end
265
+
266
+ it do
267
+ cellule = self.cellule
268
+
269
+ cellule.instance_eval do
270
+ def cache_store;
271
+ @cache_store ||= CacheStore.new;
272
+ end
273
+ end
274
+
275
+ cellule.class.cache :show, expires_in: 1.minutes, tags: lambda { self.class.to_s }
276
+ cellule.call
277
+ cellule.cache_store.fetch_args.must_equal ["cells/caching_test/director/show/", {expires_in: 60, tags: "CachingTest::DirectorCell"}]
278
+ end
279
+ end
280
+
281
+
282
+ class CachingInheritanceTest < CachingTest
283
+ class DirectorCell < ::DirectorCell
284
+ cache :show, :expires_in => 10.minutes do
285
+ "v1"
286
+ end
287
+ end
288
+
289
+ class DirectorsSonCell < DirectorCell
290
+ end
291
+
292
+ class DirectorsDaughterCell < ::DirectorCell
293
+ cache :show, :expires_in => 9.minutes do
294
+ "v2"
295
+ end
296
+ end
297
+
298
+ end