cells 3.11.3 → 4.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +15 -13
- data/Appraisals +23 -0
- data/CHANGES.md +20 -3
- data/Gemfile +5 -7
- data/README.md +317 -236
- data/Rakefile +1 -1
- data/TODO.md +3 -0
- data/cells.gemspec +19 -28
- data/gemfiles/rails3.2.gemfile +14 -0
- data/gemfiles/rails4.0.gemfile +14 -0
- data/gemfiles/rails4.1.gemfile +15 -0
- data/gemfiles/rails4.2.gemfile +14 -0
- data/lib/cell.rb +28 -21
- data/lib/cell/caching.rb +10 -22
- data/lib/cell/caching/notification.rb +15 -0
- data/lib/cell/concept.rb +4 -69
- data/lib/cell/development.rb +11 -0
- data/lib/{cells → cell}/engines.rb +1 -1
- data/lib/cell/layout.rb +20 -0
- data/lib/cell/partial.rb +17 -0
- data/lib/cell/{base/prefixes.rb → prefixes.rb} +1 -1
- data/lib/cell/rails.rb +58 -50
- data/lib/cell/railtie.rb +60 -0
- data/lib/cell/{base/self_contained.rb → self_contained.rb} +1 -1
- data/lib/cell/templates.rb +60 -0
- data/lib/cell/test_case.rb +4 -162
- data/lib/cell/testing.rb +15 -0
- data/lib/cell/twin.rb +11 -29
- data/lib/cell/version.rb +10 -0
- data/lib/cell/view_model.rb +196 -88
- data/lib/cells.rb +1 -20
- data/lib/rails/generators/cell/cell_generator.rb +43 -0
- data/lib/rails/generators/cell/templates/cell.rb.erb +8 -0
- data/lib/{generators/templates/concept → rails/generators/cell/templates}/view.erb +0 -0
- data/lib/{generators/templates/concept → rails/generators/cell/templates}/view.haml +0 -0
- data/lib/rails/generators/cell/templates/view.slim +2 -0
- data/lib/rails/generators/concept/concept_generator.rb +38 -0
- data/lib/{generators/templates/concept/cell.rb → rails/generators/concept/templates/concept.rb.erb} +2 -2
- data/lib/{generators → rails/generators/concept}/templates/view.erb +0 -0
- data/lib/{generators → rails/generators/concept}/templates/view.haml +0 -0
- data/lib/rails/generators/concept/templates/view.slim +2 -0
- data/lib/rails/generators/test_unit/cell/cell_generator.rb +21 -0
- data/lib/{generators/templates/cell_test.rb → rails/generators/test_unit/cell/templates/unit_test.rb.erb} +3 -3
- data/lib/rails/generators/test_unit/concept/concept_generator.rb +21 -0
- data/lib/rails/generators/test_unit/concept/templates/unit_test.rb.erb +11 -0
- data/lib/{cells → tasks}/cells.rake +0 -0
- data/test/builder_test.rb +58 -0
- data/test/caching_test.rb +298 -0
- data/test/cell_benchmark.rb +32 -0
- data/test/cell_generator_test.rb +51 -82
- data/test/cell_test.rb +8 -23
- data/test/concept_generator_test.rb +22 -13
- data/test/concept_test.rb +41 -75
- data/test/dummy/app/views/musician/hamlet.html.erb +1 -0
- data/test/dummy/config/application.rb +21 -8
- data/test/{app/cells/bassist/play.html.erb → fixtures/bassist/play.erb} +0 -0
- data/test/fixtures/concepts/record/views/layout.erb +1 -0
- data/test/{app → fixtures}/concepts/record/views/show.erb +0 -0
- data/test/{app → fixtures}/concepts/record/views/song.erb +0 -0
- data/test/fixtures/inherit_views_test/popper/tap.erb +1 -0
- data/test/fixtures/inherit_views_test/tapper/play.erb +1 -0
- data/test/fixtures/inherit_views_test/tapper/tap.erb +1 -0
- data/test/fixtures/partial_test/with_partial/show.erb +1 -0
- data/test/fixtures/partials/_show.html.erb +1 -0
- data/test/fixtures/partials/_show.xml.erb +1 -0
- data/test/fixtures/song/ivar.erb +1 -0
- data/test/fixtures/song/show.erb +1 -0
- data/test/fixtures/song/with_erb.erb +4 -0
- data/test/fixtures/song/with_html.erb +1 -0
- data/test/fixtures/song/with_locals.erb +2 -0
- data/test/fixtures/song_with_layout/happy.erb +1 -0
- data/test/fixtures/song_with_layout/merry.erb +1 -0
- data/test/fixtures/song_with_layout/show.erb +1 -0
- data/test/fixtures/song_with_layout/show_with_layout.erb +1 -0
- data/test/fixtures/templates_caching_test/song/show.erb +1 -0
- data/test/fixtures/url_helper_test/song/edit.erb +8 -0
- data/test/fixtures/url_helper_test/song/with_block.erb +2 -0
- data/test/fixtures/url_helper_test/song/with_capture.erb +4 -0
- data/test/fixtures/url_helper_test/song/with_content_tag.erb +6 -0
- data/test/fixtures/url_helper_test/song/with_form_for_block.erb +3 -0
- data/test/fixtures/url_helper_test/song/with_link_to.erb +3 -0
- data/test/layout_test.rb +57 -0
- data/test/partial_test.rb +27 -0
- data/test/prefixes_test.rb +36 -10
- data/test/public_test.rb +42 -0
- data/test/rails_extensions_test.rb +51 -0
- data/test/render_test.rb +103 -0
- data/test/templates_test.rb +45 -0
- data/test/test_case_test.rb +21 -122
- data/test/test_helper.rb +37 -33
- data/test/twin_test.rb +3 -7
- data/test/url_helper_test.rb +89 -0
- metadata +92 -357
- data/gemfiles/Gemfile.rails3-0 +0 -7
- data/gemfiles/Gemfile.rails3-1 +0 -7
- data/gemfiles/Gemfile.rails3-2 +0 -7
- data/gemfiles/Gemfile.rails4-0 +0 -12
- data/gemfiles/Gemfile.rails4-1 +0 -12
- data/lib/cell/base.rb +0 -82
- data/lib/cell/base/view.rb +0 -15
- data/lib/cell/builder.rb +0 -71
- data/lib/cell/deprecations.rb +0 -41
- data/lib/cell/dsl.rb +0 -7
- data/lib/cell/rack.rb +0 -32
- data/lib/cell/rails/helper_api.rb +0 -37
- data/lib/cell/rails/view_model.rb +0 -159
- data/lib/cell/rails3_0_strategy.rb +0 -82
- data/lib/cell/rails3_1_strategy.rb +0 -40
- data/lib/cell/rails4_0_strategy.rb +0 -39
- data/lib/cell/rails4_1_strategy.rb +0 -40
- data/lib/cell/rendering.rb +0 -109
- data/lib/cells/rails.rb +0 -86
- data/lib/cells/railtie.rb +0 -38
- data/lib/cells/version.rb +0 -3
- data/lib/generators/USAGE +0 -30
- data/lib/generators/cells/base.rb +0 -22
- data/lib/generators/cells/cell_generator.rb +0 -15
- data/lib/generators/cells/view_generator.rb +0 -18
- data/lib/generators/erb/cell_generator.rb +0 -15
- data/lib/generators/erb/concept_generator.rb +0 -17
- data/lib/generators/haml/cell_generator.rb +0 -17
- data/lib/generators/haml/concept_generator.rb +0 -17
- data/lib/generators/rails/cell_generator.rb +0 -16
- data/lib/generators/rails/concept_generator.rb +0 -16
- data/lib/generators/slim/cell_generator.rb +0 -17
- data/lib/generators/templates/cell.rb +0 -9
- data/lib/generators/templates/view.slim +0 -4
- data/lib/generators/test_unit/cell_generator.rb +0 -14
- data/lib/generators/trailblazer/base.rb +0 -21
- data/lib/generators/trailblazer/view_generator.rb +0 -18
- data/test/app/cells/album/views/cover.haml +0 -1
- data/test/app/cells/bad_guitarist/_dii.html.erb +0 -1
- data/test/app/cells/bad_guitarist_cell.rb +0 -2
- data/test/app/cells/bassist/_dii.html.erb +0 -1
- data/test/app/cells/bassist/ahem.html.erb +0 -1
- data/test/app/cells/bassist/compose.html.erb +0 -1
- data/test/app/cells/bassist/contact_form.html.erb +0 -1
- data/test/app/cells/bassist/form_for.erb +0 -3
- data/test/app/cells/bassist/form_for_in_haml.haml +0 -2
- data/test/app/cells/bassist/jam.html.erb +0 -3
- data/test/app/cells/bassist/play.js.erb +0 -1
- data/test/app/cells/bassist/pose.html.erb +0 -1
- data/test/app/cells/bassist/promote.html.erb +0 -1
- data/test/app/cells/bassist/provoke.html.erb +0 -1
- data/test/app/cells/bassist/shout.html.erb +0 -1
- data/test/app/cells/bassist/sing.html.haml +0 -1
- data/test/app/cells/bassist/slap.html.erb +0 -1
- data/test/app/cells/bassist/yell.en.html.erb +0 -1
- data/test/app/cells/bassist_cell.rb +0 -25
- data/test/app/cells/club_security.rb +0 -2
- data/test/app/cells/club_security/guard/help.html.erb +0 -1
- data/test/app/cells/club_security/guard_cell.rb +0 -6
- data/test/app/cells/club_security/medic/help.html.erb +0 -1
- data/test/app/cells/club_security/medic_cell.rb +0 -8
- data/test/app/cells/layouts/b.erb +0 -1
- data/test/app/cells/layouts/metal.html.erb +0 -1
- data/test/app/cells/rails_helper_api_test/bassist/edit.html.erb +0 -5
- data/test/app/cells/shouter/sing.html.erb +0 -1
- data/test/app/cells/song/dashboard.haml +0 -7
- data/test/app/cells/song/details.html.haml +0 -1
- data/test/app/cells/song/info.html.haml +0 -1
- data/test/app/cells/song/lyrics.html.haml +0 -6
- data/test/app/cells/song/plays.haml +0 -1
- data/test/app/cells/song/scale.haml +0 -1
- data/test/app/cells/song/show.html.haml +0 -3
- data/test/app/cells/song/title.html.haml +0 -1
- data/test/app/cells/trumpeter/promote.html.erb +0 -1
- data/test/app/cells/trumpeter_cell.rb +0 -8
- data/test/app/cells/view_model_test/comments/show.haml +0 -7
- data/test/app/concepts/record/views/layout.haml +0 -2
- data/test/app/views/shared/_dong.html.erb +0 -1
- data/test/cell_module_test.rb +0 -170
- data/test/cells_module_test.rb +0 -27
- data/test/deprecations_test.rb +0 -101
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/musician/hamlet.html.haml +0 -1
- data/test/dummy/config/environments/development.rb +0 -16
- data/test/dummy/config/environments/production.rb +0 -46
- data/test/dummy/config/environments/test.rb +0 -33
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/label/app/cells/label/show.erb +0 -1
- data/test/dummy/label/app/cells/label_cell.rb +0 -5
- data/test/dummy/label/label.gemspec +0 -20
- data/test/dummy/label/lib/label.rb +0 -4
- data/test/dummy/label/lib/label/version.rb +0 -3
- data/test/dummy/public/404.html +0 -26
- data/test/dummy/public/422.html +0 -26
- data/test/dummy/public/500.html +0 -26
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/stylesheets/.gitkeep +0 -0
- data/test/helper_test.rb +0 -81
- data/test/rack_test.rb +0 -32
- data/test/rails/asset_pipeline_test.rb +0 -20
- data/test/rails/caching_test.rb +0 -456
- data/test/rails/cells_test.rb +0 -119
- data/test/rails/forms_test.rb +0 -75
- data/test/rails/integration_test.rb +0 -299
- data/test/rails/render_test.rb +0 -189
- data/test/rails/view_model_test.rb +0 -226
- data/test/rails/view_test.rb +0 -49
- data/test/rails_helper_api_test.rb +0 -58
- data/test/self_contained_test.rb +0 -31
data/lib/cells.rb
CHANGED
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
-
<%
|
|
4
|
+
<% states.each do |state| -%>
|
|
5
5
|
test "<%= state %>" do
|
|
6
6
|
invoke :<%= state %>
|
|
7
|
-
assert_select
|
|
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
|
|
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
|