cells 3.8.8 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +5 -2
- data/CHANGES.textile +23 -15
- data/Gemfile +1 -1
- data/README.md +412 -0
- data/Rakefile +2 -2
- data/cells.gemspec +5 -6
- data/gemfiles/Gemfile.rails3-0 +2 -2
- data/gemfiles/Gemfile.rails3-1 +1 -1
- data/gemfiles/Gemfile.rails3-2 +1 -2
- data/gemfiles/Gemfile.rails4-0 +7 -0
- data/lib/cell.rb +27 -0
- data/lib/cell/base.rb +31 -18
- data/lib/cell/builder.rb +11 -10
- data/lib/cell/dsl.rb +7 -0
- data/lib/cell/rack.rb +5 -9
- data/lib/cell/rails.rb +19 -11
- data/lib/cell/rails/view_model.rb +115 -0
- data/lib/cell/rails3_0_strategy.rb +1 -1
- data/lib/cell/rails3_1_strategy.rb +1 -1
- data/lib/cell/rails4_0_strategy.rb +1 -2
- data/lib/cell/test_case.rb +11 -11
- data/lib/cells.rb +4 -3
- data/lib/cells/rails.rb +16 -3
- data/lib/cells/version.rb +1 -1
- data/test/app/cells/bassist_cell.rb +9 -1
- data/test/app/cells/rails_helper_api_test/bassist/edit.html.erb +3 -3
- data/test/app/cells/song/dashboard.haml +7 -0
- data/test/app/cells/song/details.html.haml +1 -0
- data/test/app/cells/song/info.html.haml +1 -0
- data/test/app/cells/song/lyrics.html.haml +6 -0
- data/test/app/cells/song/plays.haml +1 -0
- data/test/app/cells/song/show.html.haml +3 -0
- data/test/app/cells/song/title.html.haml +1 -0
- data/test/app/cells/view_model_test/comments/show.haml +7 -0
- data/test/cell_module_test.rb +39 -41
- data/test/cell_test.rb +28 -0
- data/test/dummy/app/views/musician/featured_with_block.html.erb +1 -1
- data/test/dummy/app/views/musician/title.erb +1 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/helper_test.rb +13 -10
- data/test/rails/caching_test.rb +75 -73
- data/test/rails/cells_test.rb +25 -23
- data/test/rails/integration_test.rb +80 -61
- data/test/rails/view_model_test.rb +119 -0
- data/test/rails_helper_api_test.rb +11 -13
- metadata +41 -61
- data/README.rdoc +0 -279
- data/about.yml +0 -7
- data/test/app/cells/producer/capture.html.erb +0 -1
- data/test/app/cells/producer/content_for.html.erb +0 -2
- data/test/rails/capture_test.rb +0 -70
data/lib/cell/test_case.rb
CHANGED
@@ -58,36 +58,36 @@ module Cell
|
|
58
58
|
super(HTML::Document.new(last_invoke).root, *args, &block)
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
module CommonTestMethods
|
63
63
|
def setup
|
64
|
-
@controller
|
65
|
-
@request
|
64
|
+
@controller ||= Class.new(ActionController::Base).new
|
65
|
+
@request ||= ::ActionController::TestRequest.new
|
66
66
|
@response = ::ActionController::TestResponse.new
|
67
67
|
@controller.request = @request
|
68
68
|
@controller.response = @response
|
69
69
|
@controller.params = {}
|
70
70
|
end
|
71
|
-
|
72
|
-
# Runs the block while computing the instance variables diff from before and after.
|
71
|
+
|
72
|
+
# Runs the block while computing the instance variables diff from before and after.
|
73
73
|
def extract_state_ivars_for(cell)
|
74
74
|
before = cell.instance_variables
|
75
|
-
yield
|
75
|
+
yield
|
76
76
|
after = cell.instance_variables
|
77
|
-
|
77
|
+
|
78
78
|
Hash[(after - before).collect do |var|
|
79
79
|
next if var =~ /^@_/
|
80
80
|
[var[1, var.length].to_sym, cell.instance_variable_get(var)]
|
81
81
|
end.compact]
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
|
86
86
|
module TestMethods
|
87
87
|
include CommonTestMethods
|
88
|
-
|
88
|
+
|
89
89
|
attr_reader :last_invoke, :subject_cell, :view_assigns
|
90
|
-
|
90
|
+
|
91
91
|
# Use this for functional tests of your application cells.
|
92
92
|
#
|
93
93
|
# Example:
|
@@ -100,7 +100,7 @@ module Cell
|
|
100
100
|
@view_assigns = extract_state_ivars_for(@subject_cell) do
|
101
101
|
@last_invoke = @subject_cell.render_state(state, *args)
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
@last_invoke
|
105
105
|
end
|
106
106
|
|
data/lib/cells.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# Cells are view components for Rails. Being lightweight controllers with actions and views, cells are the
|
4
4
|
# answer to <tt>DoubleRenderError</tt>s and the long awaited ability to render actions within actions.
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# == Directory structure
|
7
7
|
#
|
8
8
|
# Cells live in +app/cells/+ and have a similar file layout as controllers.
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# box.html.erb
|
18
18
|
#
|
19
19
|
# == Cell nesting
|
20
|
-
#
|
20
|
+
#
|
21
21
|
# Is is good practice to split up complex cell views into multiple states or views. Remember, you can always use
|
22
22
|
# <tt>render :view => ...</tt> and <tt>render :state => ...</tt> in your views.
|
23
23
|
#
|
@@ -42,7 +42,7 @@
|
|
42
42
|
# = @item.title
|
43
43
|
#
|
44
44
|
# render :state => :order_button
|
45
|
-
#
|
45
|
+
#
|
46
46
|
# which is more than just a partial, as you may execute additional code in the state method.
|
47
47
|
#
|
48
48
|
# == View inheritance
|
@@ -72,6 +72,7 @@ module Cells
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
require 'cell'
|
75
76
|
require 'cell/rails'
|
76
77
|
require 'cells/rails'
|
77
78
|
require 'cell/deprecations'
|
data/lib/cells/rails.rb
CHANGED
@@ -3,9 +3,14 @@
|
|
3
3
|
module Cells
|
4
4
|
module Rails
|
5
5
|
module ActionController
|
6
|
+
def cell_for(name, *args, &block)
|
7
|
+
::Cell::Base.cell_for(name, self, *args, &block)
|
8
|
+
end
|
9
|
+
alias_method :cell, :cell_for # DISCUSS: make this configurable?
|
10
|
+
|
6
11
|
# Renders the cell state and returns the content. You may pass options here, too. They will be
|
7
12
|
# around in @opts.
|
8
|
-
#
|
13
|
+
#
|
9
14
|
# Example:
|
10
15
|
#
|
11
16
|
# @box = render_cell(:posts, :latest, :user => current_user)
|
@@ -41,19 +46,27 @@ module Cells
|
|
41
46
|
ActiveSupport::Deprecation.warn "Please pass the cell class into #expire_cell_state, as in expire_cell_state(DirectorCell, :count, :user_id => 1)"
|
42
47
|
cell_class = Cell::Rails.class_from_cell_name(cell_class)
|
43
48
|
end
|
44
|
-
|
49
|
+
|
45
50
|
key = cell_class.state_cache_key(state, args)
|
46
51
|
cell_class.expire_cache_key(key, opts)
|
47
52
|
end
|
48
53
|
end
|
49
54
|
|
50
55
|
module ActionView
|
56
|
+
# Returns the cell instance for +name+. You may pass arbitrary options to your
|
57
|
+
# cell.
|
58
|
+
#
|
59
|
+
# = cell(:song, :title => "Creeping Out Sara").render(:show)
|
60
|
+
def cell_for(name, *args, &block)
|
61
|
+
controller.cell_for(name, *args, &block)
|
62
|
+
end
|
63
|
+
alias_method :cell, :cell_for # DISCUSS: make this configurable?
|
64
|
+
|
51
65
|
# See Cells::Rails::ActionController#render_cell.
|
52
66
|
def render_cell(name, state, *args, &block)
|
53
67
|
::Cell::Rails.render_cell_for(name, state, controller, *args, &block)
|
54
68
|
end
|
55
69
|
end
|
56
|
-
|
57
70
|
end
|
58
71
|
end
|
59
72
|
|
data/lib/cells/version.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
class BassistCell < Cell::Rails
|
2
|
-
def play
|
2
|
+
def play
|
3
|
+
render
|
4
|
+
end
|
3
5
|
|
4
6
|
def shout(args)
|
5
7
|
@words = args[:words]
|
6
8
|
render
|
7
9
|
end
|
10
|
+
|
11
|
+
def provoke
|
12
|
+
controller.config.relative_url_root = "" if Cell.rails3_0?
|
13
|
+
|
14
|
+
render
|
15
|
+
end
|
8
16
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
%h3 #{title}
|
@@ -0,0 +1 @@
|
|
1
|
+
%li #{render :title}
|
@@ -0,0 +1 @@
|
|
1
|
+
Plays: 99
|
@@ -0,0 +1 @@
|
|
1
|
+
= title
|
data/test/cell_module_test.rb
CHANGED
@@ -18,25 +18,23 @@ end
|
|
18
18
|
|
19
19
|
|
20
20
|
class CellBaseTest < MiniTest::Spec
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
{:host => "cells-project.org"}
|
28
|
-
end
|
29
|
-
|
21
|
+
it "still have a working #url_for" do
|
22
|
+
cell = Cell::Base.new
|
23
|
+
cell.instance_eval do
|
24
|
+
# You can use #default_url_options.
|
25
|
+
def default_url_options
|
26
|
+
{:host => "cells-project.org"}
|
30
27
|
end
|
31
|
-
|
32
|
-
assert_equal "http://cells-project.org/dashboard/show", cell.url_for(:action => :show, :controller => :dashboard)
|
28
|
+
|
33
29
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
# You could also use a *_url or *_path helper method here.
|
31
|
+
assert_equal "http://cells-project.org/dashboard/show", cell.url_for(:action => :show, :controller => :dashboard)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".render_cell_for" do
|
35
|
+
it "invokes controller-less cell" do
|
36
|
+
Cell::Base.view_paths= ["test/app/cells"]
|
37
|
+
assert_equal "YAAAaaargh!\n", Cell::Base.render_cell_for(:shouter, :sing, "Y")
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -50,19 +48,19 @@ class CellModuleTest < MiniTest::Spec
|
|
50
48
|
it "render the actual cell" do
|
51
49
|
assert_equal "Doo", Cell::Rails.render_cell_for(:bassist, :play, @controller)
|
52
50
|
end
|
53
|
-
|
51
|
+
|
54
52
|
it "accept a block, passing the cell instance" do
|
55
53
|
flag = false
|
56
54
|
html = Cell::Rails.render_cell_for(:bassist, :play, @controller) do |cell|
|
57
55
|
assert_equal BassistCell, cell.class
|
58
56
|
flag = true
|
59
57
|
end
|
60
|
-
|
58
|
+
|
61
59
|
assert_equal "Doo", html
|
62
60
|
assert flag
|
63
61
|
end
|
64
62
|
end
|
65
|
-
|
63
|
+
|
66
64
|
describe "create_cell_for" do
|
67
65
|
it "call the cell's builders, eventually returning a different class" do
|
68
66
|
class DrummerCell < BassistCell
|
@@ -70,22 +68,22 @@ class CellModuleTest < MiniTest::Spec
|
|
70
68
|
BassistCell
|
71
69
|
end
|
72
70
|
end
|
73
|
-
|
71
|
+
|
74
72
|
assert_instance_of BassistCell, Cell::Rails.create_cell_for("cell_module_test/drummer", :play, @controller)
|
75
73
|
end
|
76
74
|
end
|
77
|
-
|
75
|
+
|
78
76
|
describe "#create_cell_for with #build" do
|
79
77
|
before do
|
80
78
|
@controller.class_eval do
|
81
79
|
attr_accessor :bassist
|
82
80
|
end
|
83
|
-
|
81
|
+
|
84
82
|
MusicianCell.build do
|
85
83
|
BassistCell if bassist
|
86
84
|
end
|
87
85
|
end
|
88
|
-
|
86
|
+
|
89
87
|
after do
|
90
88
|
MusicianCell.class_eval do
|
91
89
|
@builders = false
|
@@ -94,40 +92,40 @@ class CellModuleTest < MiniTest::Spec
|
|
94
92
|
@builders = false
|
95
93
|
end
|
96
94
|
end
|
97
|
-
|
95
|
+
|
98
96
|
it "execute the block in controller describe" do
|
99
97
|
@controller.bassist = true
|
100
98
|
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
101
99
|
end
|
102
|
-
|
100
|
+
|
103
101
|
it "limit the builder to the receiving class" do
|
104
102
|
assert_is_a PianistCell, Cell::Rails.create_cell_for(:pianist, @controller) # don't inherit anything.
|
105
103
|
@controller.bassist = true
|
106
104
|
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
107
105
|
end
|
108
|
-
|
106
|
+
|
109
107
|
it "chain build blocks and execute them by ORing them in the same order" do
|
110
108
|
MusicianCell.build do
|
111
109
|
PianistCell unless bassist
|
112
110
|
end
|
113
|
-
|
111
|
+
|
114
112
|
MusicianCell.build do
|
115
113
|
UnknownCell # it never be executed.
|
116
114
|
end
|
117
|
-
|
115
|
+
|
118
116
|
assert_is_a PianistCell, Cell::Rails.create_cell_for(:musician, @controller) # bassist is false.
|
119
117
|
@controller.bassist = true
|
120
118
|
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
121
119
|
end
|
122
|
-
|
120
|
+
|
123
121
|
it "use the original cell if no builder matches" do
|
124
122
|
assert_is_a MusicianCell, Cell::Rails.create_cell_for(:musician, @controller) # bassist is false.
|
125
123
|
end
|
126
|
-
|
124
|
+
|
127
125
|
it "stop at the first builder returning a valid cell" do
|
128
|
-
|
126
|
+
|
129
127
|
end
|
130
|
-
|
128
|
+
|
131
129
|
it "pass options to the block" do
|
132
130
|
BassistCell.build do |opts|
|
133
131
|
SingerCell if opts[:sing_the_song]
|
@@ -135,38 +133,38 @@ class CellModuleTest < MiniTest::Spec
|
|
135
133
|
assert_kind_of BassistCell, Cell::Rails.create_cell_for(:bassist, @controller, {})
|
136
134
|
assert_kind_of SingerCell, Cell::Rails.create_cell_for(:bassist, @controller, {:sing_the_song => true})
|
137
135
|
end
|
138
|
-
|
136
|
+
|
139
137
|
it "create the original target class if no block matches" do
|
140
138
|
assert_kind_of PianistCell, Cell::Rails.create_cell_for(:pianist, @controller)
|
141
139
|
end
|
142
|
-
|
140
|
+
|
143
141
|
it "builders it return an empty array per default" do
|
144
142
|
assert_equal [], PianistCell.send(:builders)
|
145
143
|
end
|
146
144
|
end
|
147
|
-
|
145
|
+
|
148
146
|
it "provide class_from_cell_name" do
|
149
147
|
assert_equal BassistCell, ::Cell::Rails.class_from_cell_name('bassist')
|
150
148
|
end
|
151
|
-
|
149
|
+
|
152
150
|
if Cell.rails3_0?
|
153
151
|
it "provide possible_paths_for_state" do
|
154
152
|
assert_equal ["bad_guitarist/play", "bassist/play"], cell(:bad_guitarist).send(:possible_paths_for_state, :play)
|
155
153
|
end
|
156
|
-
|
154
|
+
|
157
155
|
it "provide Cell.cell_name" do
|
158
156
|
assert_equal 'bassist', cell(:bassist).class.cell_name
|
159
157
|
end
|
160
|
-
|
158
|
+
|
161
159
|
it "provide cell_name for modules, too" do
|
162
160
|
class SingerCell < Cell::Rails
|
163
161
|
end
|
164
|
-
|
162
|
+
|
165
163
|
assert_equal "cell_module_test/singer", CellModuleTest::SingerCell.cell_name
|
166
164
|
end
|
167
165
|
end
|
168
166
|
end
|
169
|
-
|
167
|
+
|
170
168
|
it "respond to #rails3_1_or_more?" do
|
171
169
|
if Rails::VERSION::MAJOR == 3
|
172
170
|
if Rails::VERSION::MINOR == 0
|
data/test/cell_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class CellTest < MiniTest::Spec
|
4
|
+
class ArtistCell < Cell::Rails
|
5
|
+
end
|
6
|
+
class SongCell < Cell::Base
|
7
|
+
include Cell::OptionsConstructor
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it { Class.new(Cell::Base) { include Cell::OptionsConstructor }.new(:song => song=Object.new).song.must_equal song }
|
12
|
+
it { Class.new(Cell::Rack) { include Cell::OptionsConstructor }.new(Object, :song => song=Object.new).song.must_equal song }
|
13
|
+
it { Class.new(Cell::Rails) { include Cell::OptionsConstructor }.new(Object, :song => song=Object.new).song.must_equal song }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "::create_cell_for" do
|
17
|
+
it { Cell::Base.create_cell_for("cell_test/song", :song => song=Object.new).song.must_equal song }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#cell" do
|
21
|
+
it { Cell::Rails.new(Object).cell("cell_test/artist").must_be_instance_of ArtistCell }
|
22
|
+
it { Cell::Base.new.cell("cell_test/song").must_be_instance_of SongCell }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class OptionsConstructorTest < MiniTest::Spec
|
27
|
+
it { Class.new(Cell::Base) { include Cell::OptionsConstructor }.new(:song => song=Object.new).song.must_equal song }
|
28
|
+
end
|