cells 3.10.1 → 3.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.travis.yml +7 -0
  2. data/CHANGES.md +18 -0
  3. data/Gemfile +1 -1
  4. data/README.md +182 -57
  5. data/TODO.md +9 -0
  6. data/cells.gemspec +3 -1
  7. data/gemfiles/Gemfile.rails4-0 +2 -1
  8. data/gemfiles/Gemfile.rails4-1 +5 -3
  9. data/lib/cell/base.rb +33 -64
  10. data/lib/cell/base/prefixes.rb +27 -0
  11. data/lib/cell/base/self_contained.rb +13 -0
  12. data/lib/cell/base/view.rb +15 -0
  13. data/lib/cell/builder.rb +52 -53
  14. data/lib/cell/caching.rb +21 -4
  15. data/lib/cell/concept.rb +85 -0
  16. data/lib/cell/rails.rb +13 -6
  17. data/lib/cell/rails/view_model.rb +47 -6
  18. data/lib/cell/rendering.rb +13 -13
  19. data/lib/cell/test_case.rb +3 -3
  20. data/lib/cell/view_model.rb +151 -0
  21. data/lib/cells.rb +0 -60
  22. data/lib/cells/rails.rb +10 -5
  23. data/lib/cells/railtie.rb +2 -5
  24. data/lib/cells/version.rb +1 -1
  25. data/lib/generators/erb/concept_generator.rb +17 -0
  26. data/lib/generators/haml/concept_generator.rb +17 -0
  27. data/lib/generators/rails/concept_generator.rb +16 -0
  28. data/lib/generators/templates/concept/cell.rb +9 -0
  29. data/lib/generators/templates/concept/view.erb +7 -0
  30. data/lib/generators/templates/concept/view.haml +4 -0
  31. data/lib/generators/trailblazer/base.rb +21 -0
  32. data/lib/generators/trailblazer/view_generator.rb +18 -0
  33. data/test/app/cells/bassist_cell.rb +1 -1
  34. data/test/app/cells/record/views/layout.haml +2 -0
  35. data/test/app/cells/record/views/show.erb +1 -0
  36. data/test/app/cells/record/views/song.erb +1 -0
  37. data/test/app/cells/song/scale.haml +1 -0
  38. data/test/cell_module_test.rb +18 -37
  39. data/test/cells_module_test.rb +1 -1
  40. data/test/concept_generator_test.rb +26 -0
  41. data/test/concept_test.rb +78 -0
  42. data/test/dummy/Rakefile +1 -1
  43. data/test/dummy/app/assets/javascripts/application.js +2 -0
  44. data/test/dummy/app/cells/album/assets/album.js +1 -0
  45. data/test/dummy/app/concepts/song/assets/songs.js +1 -0
  46. data/test/dummy/config/application.rb +11 -6
  47. data/test/dummy/label/label.gemspec +2 -2
  48. data/test/helper_test.rb +2 -2
  49. data/test/prefixes_test.rb +75 -0
  50. data/test/rails/asset_pipeline_test.rb +20 -0
  51. data/test/rails/caching_test.rb +1 -9
  52. data/test/rails/cells_test.rb +2 -17
  53. data/test/rails/forms_test.rb +2 -1
  54. data/test/rails/integration_test.rb +199 -8
  55. data/test/rails/render_test.rb +2 -10
  56. data/test/rails/view_model_test.rb +135 -60
  57. data/test/rails_helper_api_test.rb +2 -1
  58. data/test/self_contained_test.rb +9 -2
  59. data/test/test_case_test.rb +2 -2
  60. data/test/test_helper.rb +2 -3
  61. metadata +117 -33
  62. checksums.yaml +0 -7
  63. data/test/dummy/app/controllers/musician_controller.rb +0 -36
  64. data/test/rails/router_test.rb +0 -45
@@ -39,6 +39,7 @@ class FormsTest < MiniTest::Spec
39
39
  end
40
40
 
41
41
  it "renders input fields within the form tag with ERB and ViewModel" do
42
+ skip if ::Cell.rails_version.~("3.0")
42
43
 
43
44
  html = SongFormCell.new(@controller).form
44
45
  puts html.to_s
@@ -65,7 +66,7 @@ class FormsTest < MiniTest::Spec
65
66
  end
66
67
 
67
68
  it "renders input fields within the form tag with HAML and ViewModel" do
68
-
69
+ skip
69
70
  html = HamlSongFormCell.new(@controller).form
70
71
  puts html.to_s
71
72
 
@@ -1,5 +1,65 @@
1
1
  require 'test_helper'
2
2
 
3
+ class MusicianController < ActionController::Base
4
+ def index
5
+ render :text => render_cell(:bassist, :promote)
6
+ end
7
+
8
+ def promote
9
+ render :text => render_cell(:trumpeter, :promote)
10
+ end
11
+
12
+ def promotion
13
+ render :text => render_cell(:bassist, :provoke)
14
+ end
15
+
16
+ def featured
17
+ end
18
+
19
+ def featured_with_block
20
+ end
21
+
22
+ def skills
23
+ render :text => render_cell(:bassist, :listen)
24
+ end
25
+
26
+ def hamlet
27
+ end
28
+
29
+ attr_reader :flag
30
+ def promotion_with_block
31
+ html = render_cell(:bassist, :play) do |cell|
32
+ @flag = cell.class
33
+ end
34
+
35
+ render :text => html
36
+ end
37
+
38
+ def song
39
+ render :inline => %{<%= concept("view_methods_test/cell", "Up For Breakfast").call %>} # TODO: concept doesn't need .call
40
+ end
41
+
42
+ def songs
43
+ render :inline => %{<%= concept("view_methods_test/cell", :collection => %w{Alltax Ronny}) %>} # TODO: concept doesn't need .call
44
+ end
45
+
46
+ def album
47
+ render :inline => %{<%= cell("view_methods_test/album", "Dreiklang").call %>} # DISCUSS: make .call in #cell?
48
+ end
49
+
50
+ def albums
51
+ render :inline => %{<%= cell("view_methods_test/album", :collection => %w{Dreiklang Coaster}) %>}
52
+ end
53
+ end
54
+
55
+ ActionController::TestCase.class_eval do
56
+ def png_src
57
+ return "/images/me.png" if Cell.rails_version >= 4.0
58
+ return "/assets/me.png" if Cell.rails_version >= 3.1
59
+ "/images/me.png"
60
+ end
61
+ end
62
+
3
63
  class ControllerMethodsTest < ActionController::TestCase
4
64
  tests MusicianController
5
65
 
@@ -11,7 +71,7 @@ class ControllerMethodsTest < ActionController::TestCase
11
71
  fix_relative_url_root
12
72
 
13
73
  get 'promotion'
14
- assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />", @response.body
74
+ assert_equal "That's me, naked <img alt=\"Me\" src=\"#{png_src}\" />", @response.body
15
75
  end
16
76
 
17
77
  test "#render_cell with arbitrary options" do
@@ -36,20 +96,63 @@ class ControllerMethodsTest < ActionController::TestCase
36
96
  assert_equal BassistCell, @controller.flag
37
97
  end
38
98
 
39
- test "#cell_for" do
40
- @controller.cell_for(:bassist).must_be_instance_of BassistCell
99
+ test "#cell" do
100
+ @controller.cell(:bassist).must_be_instance_of BassistCell
41
101
  end
42
102
 
43
- test "#cell_for with options" do
44
- @controller.cell_for("controller_methods_test/song", :title => "We Called It America").
103
+ test "#cell with options" do
104
+ @controller.cell("controller_methods_test/song", :title => "We Called It America").
45
105
  title.must_equal "We Called It America"
46
106
  end
47
107
 
48
- if Cell.rails4_0? or Cell.rails4_1_or_more?
108
+ if Cell.rails_version >= "5.0" # TODO: make run.
49
109
  test "#render_cell for engine" do
50
110
  @controller.render_cell(:label, :show).must_equal "Fat Wreck"
51
111
  end
52
112
  end
113
+
114
+
115
+
116
+
117
+
118
+
119
+ test "pass url_helpers to the cell instance" do
120
+ assert_equal "/musicians", BassistCell.new(@controller).musicians_path
121
+ end
122
+
123
+ test "allow cells to use url_helpers" do
124
+ get "index"
125
+ assert_response :success
126
+ assert_equal "Find me at <a href=\"/musicians\">vd.com</a>\n", @response.body
127
+ end
128
+
129
+ test "delegate #url_options to the parent_controller" do
130
+ @controller.instance_eval do
131
+ def default_url_options
132
+ {:host => "cells.rails.org"}
133
+ end
134
+ end
135
+
136
+ assert_equal "http://cells.rails.org/musicians", BassistCell.new(@controller).musicians_url
137
+ end
138
+
139
+ test "allow cells to use *_url helpers when mixing in AC::UrlFor" do
140
+ get "promote"
141
+ assert_response :success
142
+ assert_equal "Find me at <a href=\"http://test.host/musicians\">vd.com</a>\n", @response.body
143
+ end
144
+
145
+ test "allow cells to use #config" do
146
+ BassistCell.class_eval do
147
+ def provoke; render; end
148
+ end
149
+
150
+ fix_relative_url_root
151
+
152
+ get "promotion"
153
+ assert_response :success
154
+ assert_equal "That's me, naked <img alt=\"Me\" src=\"#{png_src}\" />", @response.body
155
+ end
53
156
  end
54
157
 
55
158
 
@@ -70,7 +173,7 @@ class ViewMethodsTest < ActionController::TestCase
70
173
  fix_relative_url_root
71
174
 
72
175
  get 'featured'
73
- assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />", @response.body
176
+ assert_equal "That's me, naked <img alt=\"Me\" src=\"#{png_src}\" />", @response.body
74
177
  end
75
178
 
76
179
  test "#render_cell with a block" do
@@ -82,9 +185,97 @@ class ViewMethodsTest < ActionController::TestCase
82
185
  fix_relative_url_root
83
186
 
84
187
  get 'hamlet'
85
- assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />\n", @response.body
188
+ assert_equal "That's me, naked <img alt=\"Me\" src=\"#{png_src}\" />\n", @response.body
86
189
  end
87
190
 
191
+
192
+
193
+ unless ::Cell.rails_version.~("3.0")
194
+
195
+ # concept -------------------
196
+ class Cell < Cell::Concept
197
+ def show
198
+ render :text => "<b>#{model}</b>"
199
+ end
200
+
201
+
202
+ class Collection < ::Cell::Concept
203
+ def show
204
+ concept("view_methods_test/cell", "Dreiklang").call
205
+ end
206
+
207
+ def collection
208
+ concept("view_methods_test/cell", :collection => %w{Dreiklang Coaster})
209
+ end
210
+ end
211
+ end
212
+
213
+ # Concept#concept(:album, "Dreiklang").call
214
+ test "Concept#cell" do # FIXME: move to HelperTest.
215
+ Cell::Collection.new(@controller).call.must_equal "<b>Dreiklang</b>"
216
+ end
217
+
218
+ # Concept#concept(:album, collection: [])
219
+ test "Concept#cell collection: []" do # FIXME: move to HelperTest.
220
+ Cell::Collection.new(@controller).call(:collection).must_equal "<b>Dreiklang</b>\n<b>Coaster</b>"
221
+ end
222
+
223
+
224
+ # concept(:song, "Alltax").call
225
+ test "#concept" do
226
+ get :song
227
+ @response.body.must_equal "<b>Up For Breakfast</b>"
228
+ end
229
+
230
+ # concept(:song, collection: [..])
231
+ test "#concept with collection" do
232
+ get :songs
233
+ @response.body.must_equal "<b>Alltax</b>\n<b>Ronny</b>"
234
+ end
235
+
236
+
237
+
238
+ # view model ------------------
239
+ class AlbumCell < ::Cell::ViewModel
240
+ def show
241
+ "<b>#{model}</b>"
242
+ end
243
+ end
244
+
245
+ class AlbumsCell < ::Cell::ViewModel
246
+ def show
247
+ cell("view_methods_test/album", "Dreiklang").call
248
+ end
249
+
250
+ def collection
251
+ cell("view_methods_test/album", :collection => %w{Dreiklang Coaster})
252
+ end
253
+ end
254
+
255
+ # ViewModel#cell(:album, "Dreiklang").call
256
+ test "ViewModel#cell" do # FIXME: move to HelperTest.
257
+ AlbumsCell.new(@controller).call.must_equal "<b>Dreiklang</b>"
258
+ end
259
+
260
+ test "ViewModel#cell collection: []" do # FIXME: move to HelperTest.
261
+ AlbumsCell.new(@controller).call(:collection).must_equal "<b>Dreiklang</b>\n<b>Coaster</b>"
262
+ end
263
+
264
+
265
+ # cell(:album, "Dreiklang").call
266
+ test "#cell for view model" do
267
+ get :album
268
+ @response.body.must_equal "<b>Dreiklang</b>"
269
+ end
270
+
271
+ # cell(:album, collection: [..])
272
+ test "#cell with collection for view model" do
273
+ get :albums
274
+ @response.body.must_equal "<b>Dreiklang</b>\n<b>Coaster</b>"
275
+ end
276
+ end
277
+
278
+
88
279
  test "make params (and friends) available in a cell" do
89
280
  BassistCell.class_eval do
90
281
  def listen
@@ -122,7 +122,7 @@ class RailsRenderTest < MiniTest::Spec
122
122
  end
123
123
 
124
124
  exception = ActionView::MissingTemplate
125
- exception = Cell::VersionStrategy::MissingTemplate if Cell.rails3_0?
125
+ exception = Cell::VersionStrategy::MissingTemplate if Cell.rails_version.~("3.0")
126
126
 
127
127
  assert_raises exception do
128
128
  render_cell(:bassist, :groove)
@@ -134,7 +134,7 @@ class RailsRenderTest < MiniTest::Spec
134
134
  def groove; render; end
135
135
  end
136
136
 
137
- if Cell.rails3_0?
137
+ if Cell.rails_version.~("3.0")
138
138
  e = assert_raises Cell::Rails::MissingTemplate do
139
139
  render_cell(:bad_guitarist, :groove)
140
140
  end
@@ -167,14 +167,6 @@ class RailsRenderTest < MiniTest::Spec
167
167
  end
168
168
  assert_equal "<h1>Laaa</h1>\n<h1>Laaa</h1>\n<h1>Laaa</h1>\n", render_cell(:bassist, :sing)
169
169
  end
170
-
171
- # inheriting
172
- it "inherit play.html.erb from BassistCell" do
173
- BassistCell.class_eval do
174
- def play; render; end
175
- end
176
- assert_equal "Doo", render_cell(:bad_guitarist, :play)
177
- end
178
170
  end
179
171
 
180
172
  describe "A cell view" do
@@ -1,24 +1,22 @@
1
1
  require 'test_helper'
2
2
 
3
- # TODO: test if nested state renders are html_safe.
3
+ if Cell.rails_version >= 3.1
4
4
 
5
- class Song < OpenStruct
6
- extend ActiveModel::Naming
5
+ class Song < OpenStruct
6
+ extend ActiveModel::Naming
7
7
 
8
- def persisted?
9
- true
10
- end
8
+ def persisted?
9
+ true
10
+ end
11
11
 
12
- def to_param
13
- id
12
+ def to_param
13
+ id
14
+ end
14
15
  end
15
- end
16
16
 
17
17
 
18
18
 
19
- class SongCell < Cell::Rails
20
- include Cell::Rails::ViewModel
21
-
19
+ class SongCell < Cell::ViewModel
22
20
  def show
23
21
  render
24
22
  end
@@ -47,6 +45,10 @@ class SongCell < Cell::Rails
47
45
  render :dashboard
48
46
  end
49
47
 
48
+ def scale
49
+ render :layout => 'b'
50
+ end
51
+
50
52
  class Lyrics < self
51
53
  def show
52
54
  render :lyrics
@@ -54,81 +56,154 @@ class SongCell < Cell::Rails
54
56
  end
55
57
 
56
58
  class PlaysCell < self
59
+ def show
60
+ render :plays
61
+ end
57
62
  end
58
63
  end
59
64
 
60
- class ViewModelTest < MiniTest::Spec
61
- # class PianoSongCell < Cell::Rails
62
- # include ViewModel
65
+ class ViewModelTest < MiniTest::Spec
66
+ # views :show, :create #=> wrap in render_state(:show, *)
67
+ let (:cell) { SongCell.new(nil, :title => "Shades Of Truth") }
63
68
 
64
- # property :title
65
- # end
69
+ it { cell.title.must_equal "Shades Of Truth" }
66
70
 
67
- # views :show, :create #=> wrap in render_state(:show, *)
68
- let (:cell) { SongCell.build_for(nil, :title => "Shades Of Truth") }
71
+ class HitCell < Cell::ViewModel
72
+ property :title, :artist
69
73
 
70
- it { cell.title.must_equal "Shades Of Truth" }
74
+ def show
75
+ "Great!"
76
+ end
71
77
 
72
- class HitCell < Cell::Base
73
- include Cell::Rails::ViewModel
74
- property :title, :artist
75
- end
78
+ def rate
79
+ "Fantastic!"
80
+ end
81
+
82
+ attr_accessor :count
83
+ cache :count
84
+ end
85
+
86
+ let (:song) { Song.new(:title => "65", artist: "Boss") }
87
+ it { HitCell.new(nil, song).title.must_equal "65" }
88
+ it { HitCell.new(nil, song).artist.must_equal "Boss" }
76
89
 
77
- let (:song) { Song.new(:title => "65", artist: "Boss") }
78
- it { HitCell.new(song).title.must_equal "65" }
79
- it { HitCell.new(song).artist.must_equal "Boss" }
80
- end
81
90
 
82
- if Cell.rails3_2_or_more?
83
- class ViewModelIntegrationTest < ActionController::TestCase
84
- tests MusicianController
91
+ describe "#call" do
92
+ let (:cell) { HitCell.new(nil, song) }
85
93
 
86
- #let (:song) { Song.new(:title => "Blindfold", :id => 1) }
87
- #let (:html) { %{<h1>Shades Of Truth</h1>\n} }
88
- #let (:cell) { }
94
+ it { cell.call.must_equal "Great!" }
95
+ it { cell.call(:rate).must_equal "Fantastic!" }
96
+
97
+ it "no caching" do
98
+ cell.instance_eval do
99
+ def cache_configured?
100
+ false
101
+ end
102
+ end
103
+
104
+ cell.count = 1
105
+ cell.call(:count).must_equal "1"
106
+ cell.count = 2
107
+ cell.call(:count).must_equal "2"
108
+ end
89
109
 
90
- setup do
91
- @cell = SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => "1"))
110
+ it "with caching" do
111
+ cell.instance_eval do
112
+ self.cache_store = ActiveSupport::Cache::MemoryStore.new
113
+ self.cache_configured = true
114
+ end
92
115
 
93
- @url = "/songs/1"
94
- @url = "http://test.host/songs/1" if Cell.rails4_0?
116
+ cell.count = 1
117
+ cell.call(:count).must_equal "1"
118
+ cell.count = 2
119
+ cell.call(:count).must_equal "1"
120
+ end
95
121
  end
96
122
 
97
123
 
98
- # test "instantiating without model, but call to ::property" do
99
- # assert_raises do
100
- # @controller.cell("view_model_test/piano_song")
101
- # end
124
+ # describe "::helper" do
125
+ # it { assert_raises { HitCell.helper Module.new } }
102
126
  # end
127
+ end
128
+
103
129
 
130
+ if Cell.rails_version >= "3.2"
131
+ class ViewModelIntegrationTest < ActionController::TestCase
132
+ tests MusicianController
104
133
 
105
- test "URL helpers in view" do
106
- @cell.show.must_equal %{<h1>BLINDFOLD</h1>
134
+ #let (:song) { Song.new(:title => "Blindfold", :id => 1) }
135
+ #let (:html) { %{<h1>Shades Of Truth</h1>\n} }
136
+ #let (:cell) { }
137
+
138
+ setup do
139
+ @cell = SongCell.new(@controller, :song => Song.new(:title => "Blindfold", :id => "1"))
140
+
141
+ @url = "/songs/1"
142
+ @url = "http://test.host/songs/1" if Cell.rails_version.>=("4.0")
143
+ end
144
+
145
+
146
+ # test "instantiating without model, but call to ::property" do
147
+ # assert_raises do
148
+ # @controller.cell("view_model_test/piano_song")
149
+ # end
150
+ # end
151
+
152
+
153
+ test "URL helpers in view" do
154
+ @cell.show.must_equal %{<h1>BLINDFOLD</h1>
107
155
  <a href=\"#{@url}\">Permalink</a>
108
- } end
156
+ } end
109
157
 
110
- test "URL helper in instance" do
111
- @cell.self_url.must_equal @url
112
- end
158
+ test "URL helper in instance" do
159
+ @cell.self_url.must_equal @url
160
+ end
113
161
 
114
- test "implicit #render" do
115
- @cell.details.must_equal "<h3>BLINDFOLD</h3>\n"
116
- SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => 1)).details
117
- end
162
+ test "implicit #render" do
163
+ @cell.details.must_equal "<h3>BLINDFOLD</h3>\n"
164
+ SongCell.new(@controller, :song => Song.new(:title => "Blindfold", :id => 1)).details
165
+ end
166
+
167
+ test "explicit #render with one arg" do
168
+ @cell = SongCell.new(@controller, :song => Song.new(:title => "Blindfold", :id => 1))
169
+ @cell.stats.must_equal "<h3>BLINDFOLD</h3>\n"
170
+ end
171
+
172
+ test "nested render" do
173
+ @cell.info.must_equal "<li>BLINDFOLD\n</li>\n"
174
+ end
118
175
 
119
- test "explicit #render with one arg" do
120
- @cell = SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => 1))
121
- @cell.stats.must_equal "<h3>BLINDFOLD</h3>\n"
176
+ test "nested rendering method" do
177
+ @cell.dashboard.must_equal "<h1>Dashboard</h1>\n<h3>Lyrics for BLINDFOLD</h3>\n<li>\nIn the Mirror\n</li>\n<li>\nI can see\n</li>\n\nPlays: 99\n\nPlays: 99\n\n"
178
+ end
179
+
180
+ test( "layout") { @cell.scale.must_equal "<b>A Minor!\n</b>" }
181
+
182
+ # TODO: when we don't pass :song into Lyrics
122
183
  end
184
+ end
123
185
 
124
- test "nested render" do
125
- @cell.info.must_equal "<li>BLINDFOLD\n</li>\n"
186
+ class CollectionTest < MiniTest::Spec
187
+ class ReleasePartyCell < Cell::ViewModel
188
+ def show
189
+ "Party on, #{model}!"
190
+ end
191
+
192
+ def show_more
193
+ "Go nuts, #{model}!"
194
+ end
126
195
  end
127
196
 
128
- test "nested rendering method" do
129
- @cell.dashboard.must_equal "<h1>Dashboard</h1>\n<h3>Lyrics for BLINDFOLD</h3>\n<li>\nIn the Mirror\n</li>\n<li>\nI can see\n</li>\n\nPlays: 99\n\nPlays: 99\n\n"
197
+
198
+ describe "::collection" do
199
+ it { Cell::ViewModel.collection("collection_test/release_party", @controller, %w{Garth Wayne}).must_equal "Party on, Garth!\nParty on, Wayne!" }
200
+ it { Cell::ViewModel.collection("collection_test/release_party", @controller, %w{Garth Wayne}, :show_more).must_equal "Go nuts, Garth!\nGo nuts, Wayne!" }
130
201
  end
202
+ # TODO: test with builders ("polymorphic collections") and document that.
131
203
 
132
- # TODO: when we don't pass :song into Lyrics
204
+ describe "::cell" do
205
+ it { Cell::ViewModel.cell("collection_test/release_party", @controller, "Garth").call.must_equal "Party on, Garth!" }
206
+ end
133
207
  end
208
+
134
209
  end