cells 3.8.8 → 3.9.0

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -1
  3. data/.travis.yml +5 -2
  4. data/CHANGES.textile +23 -15
  5. data/Gemfile +1 -1
  6. data/README.md +412 -0
  7. data/Rakefile +2 -2
  8. data/cells.gemspec +5 -6
  9. data/gemfiles/Gemfile.rails3-0 +2 -2
  10. data/gemfiles/Gemfile.rails3-1 +1 -1
  11. data/gemfiles/Gemfile.rails3-2 +1 -2
  12. data/gemfiles/Gemfile.rails4-0 +7 -0
  13. data/lib/cell.rb +27 -0
  14. data/lib/cell/base.rb +31 -18
  15. data/lib/cell/builder.rb +11 -10
  16. data/lib/cell/dsl.rb +7 -0
  17. data/lib/cell/rack.rb +5 -9
  18. data/lib/cell/rails.rb +19 -11
  19. data/lib/cell/rails/view_model.rb +115 -0
  20. data/lib/cell/rails3_0_strategy.rb +1 -1
  21. data/lib/cell/rails3_1_strategy.rb +1 -1
  22. data/lib/cell/rails4_0_strategy.rb +1 -2
  23. data/lib/cell/test_case.rb +11 -11
  24. data/lib/cells.rb +4 -3
  25. data/lib/cells/rails.rb +16 -3
  26. data/lib/cells/version.rb +1 -1
  27. data/test/app/cells/bassist_cell.rb +9 -1
  28. data/test/app/cells/rails_helper_api_test/bassist/edit.html.erb +3 -3
  29. data/test/app/cells/song/dashboard.haml +7 -0
  30. data/test/app/cells/song/details.html.haml +1 -0
  31. data/test/app/cells/song/info.html.haml +1 -0
  32. data/test/app/cells/song/lyrics.html.haml +6 -0
  33. data/test/app/cells/song/plays.haml +1 -0
  34. data/test/app/cells/song/show.html.haml +3 -0
  35. data/test/app/cells/song/title.html.haml +1 -0
  36. data/test/app/cells/view_model_test/comments/show.haml +7 -0
  37. data/test/cell_module_test.rb +39 -41
  38. data/test/cell_test.rb +28 -0
  39. data/test/dummy/app/views/musician/featured_with_block.html.erb +1 -1
  40. data/test/dummy/app/views/musician/title.erb +1 -0
  41. data/test/dummy/config/routes.rb +1 -0
  42. data/test/helper_test.rb +13 -10
  43. data/test/rails/caching_test.rb +75 -73
  44. data/test/rails/cells_test.rb +25 -23
  45. data/test/rails/integration_test.rb +80 -61
  46. data/test/rails/view_model_test.rb +119 -0
  47. data/test/rails_helper_api_test.rb +11 -13
  48. metadata +41 -61
  49. data/README.rdoc +0 -279
  50. data/about.yml +0 -7
  51. data/test/app/cells/producer/capture.html.erb +0 -1
  52. data/test/app/cells/producer/content_for.html.erb +0 -2
  53. data/test/rails/capture_test.rb +0 -70
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f0e0a0f0e9e01a740baa8dcabe12f82876ca1ef
4
+ data.tar.gz: a0a66d1ecd8e09265efc3a8c5fe7e293bc8df5d1
5
+ SHA512:
6
+ metadata.gz: 33577d3b2e94dde50fb8f68ff2695fbaa1dbc73a04fb839fbb14e4ca215f83d01b854ec57454cf75488210a2ef8060312cdfc9ae865ece439af2fd84ab4df111
7
+ data.tar.gz: 7c03b94c1a6dee95e672a0411025e9fa7afb6414d4a3c43a4038b70e45f381f4bde3d9cf66a2364f953ef381b27220af690da67685f5aaddb8be8e09d4f3a4c0
data/.gitignore CHANGED
@@ -1,8 +1,9 @@
1
1
  .DS_Store
2
2
  pkg
3
+ *.gem
3
4
  .*~
4
5
  .bundle
5
6
  Gemfile*.lock
6
- test/dummy/log/*.log
7
+ test/dummy/log/
7
8
  test/dummy/tmp/
8
9
  /.rvmrc
data/.travis.yml CHANGED
@@ -1,8 +1,11 @@
1
- rvm: 1.9.2
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - jruby-19mode
2
5
  notifications:
3
6
  irc: "irc.freenode.org#cells"
4
7
  gemfile:
5
- - Gemfile
6
8
  - gemfiles/Gemfile.rails3-0
7
9
  - gemfiles/Gemfile.rails3-1
8
10
  - gemfiles/Gemfile.rails3-2
11
+ - gemfiles/Gemfile.rails4-0
data/CHANGES.textile CHANGED
@@ -1,3 +1,11 @@
1
+ h2. 3.9.0
2
+
3
+ * Cells in engines are now recognized under Rails 4.0.
4
+ * Introducing @#cell@ and @#cell_for@ to instantiate cells in ActionController and ActionView.
5
+ * Adding @Cell::Rails::ViewModel@ as a new "dialect" of working with cells.
6
+ * Add @Cell::Base#process_args@ which is called in the initializer to handle arguments passed into the constructor.
7
+ * Setting @controller in your @Cell::TestCase@ no longer get overridden by us.
8
+
1
9
  h2. 3.8.8
2
10
 
3
11
  * Maintenance release.
@@ -24,7 +32,7 @@ h2. 3.8.4
24
32
 
25
33
  h2. 3.8.3
26
34
 
27
- * Added @Engines.existent_directories_for@ to prevent Rails 3.0 from crashing when it detects engines.
35
+ * Added @Engines.existent_directories_for@ to prevent Rails 3.0 from crashing when it detects engines.
28
36
 
29
37
  h2. 3.8.2
30
38
 
@@ -40,7 +48,7 @@ h2. 3.8.0
40
48
  * New API (note that @controller@ isn't the first argument anymore):
41
49
  ** @Rails.create_cell_for(name, controller)@
42
50
  ** @Rails.render_cell_for(name, state, controller, *args)@
43
- * Moved builder methods to @Cell::Builder@ module.
51
+ * Moved builder methods to @Cell::Builder@ module.
44
52
  * @DEFAULT_VIEW_PATHS@ is now in @Cell::Base@.
45
53
  * Removed the monkey-patch that made state-args work in Rails <= 3.0.3. Upgrade to +3.0.4.
46
54
 
@@ -60,18 +68,18 @@ h2. 3.6.8
60
68
 
61
69
  h3. Changes
62
70
  * Removed <code>@opts</code>.
63
- * Deprecated @#options@ in favour of state-args.
71
+ * Deprecated @#options@ in favour of state-args.
64
72
 
65
73
  h2. 3.6.7
66
74
 
67
75
  h3. Changes
68
- * Added @view_assigns@ to TestCase.
69
-
76
+ * Added @view_assigns@ to TestCase.
77
+
70
78
  h2. 3.6.6
71
79
 
72
80
  h3. Changes
73
81
  * Added the @:format@ option for @#render@ which should be used with caution. Sorry for that.
74
- * Removed the useless @layouts/@ view path from Cell::Base.
82
+ * Removed the useless @layouts/@ view path from Cell::Base.
75
83
 
76
84
  h2. 3.6.5
77
85
 
@@ -79,7 +87,7 @@ h3. Bugfixes
79
87
  * `Cell::TestCase#invoke` now properly accepts state-args.
80
88
 
81
89
  h3. Changes
82
- * Added the `:if` option to `Base.cache` which allows adding a conditional proc or instance method to the cache definition. If it doesn't return true, caching for that state is skipped.
90
+ * Added the `:if` option to `Base.cache` which allows adding a conditional proc or instance method to the cache definition. If it doesn't return true, caching for that state is skipped.
83
91
 
84
92
 
85
93
  h2. 3.6.4
@@ -122,7 +130,7 @@ h3. Changes
122
130
 
123
131
 
124
132
  h2. 3.5.5
125
-
133
+
126
134
  h3. Bugfixes
127
135
  * The generator now places views of namespaced cells into the correct directory. E.g. `rails g Blog::Post display` puts views to `app/cells/blog/post/display.html.erb`.
128
136
 
@@ -131,7 +139,7 @@ h3. Changes
131
139
 
132
140
 
133
141
  h2. 3.5.4
134
-
142
+
135
143
  h3. Bugfixes
136
144
  * state-args work even if your state method receives optional arguments or default values, like @def show(user, age=18)@.
137
145
 
@@ -142,7 +150,7 @@ h3. Changes
142
150
 
143
151
 
144
152
  h2. 3.5.2
145
-
153
+
146
154
  h3. Bugfixes
147
155
  * Controller#render_cell now accepts multiple args as options.
148
156
 
@@ -155,7 +163,7 @@ h2. 3.5.1
155
163
  * No longer pass an explicit Proc but a versioner block to @Cell.Base.cache@. Example: @cache :show do "v1" end@
156
164
  * Caching.cache_key_for now uses @ActiveSupport::Cache.expand_cache_key@. Consequently, a key which used to be like @"cells/director/count/a=1/b=2"@ now is @cells/director/count/a=1&b=2@ and so on. Be warned that this might break your home-made cache expiry.
157
165
  * Controller#expire_cell_state now expects the cell class as first arg. Example: @expire_cell_state(DirectorCell, :count)@
158
-
166
+
159
167
  h3. Bugfixes
160
168
  * Passing options to @render :state@ in views finally works: @render({:state => :list_item}, item, i)@
161
169
 
@@ -165,26 +173,26 @@ h2. 3.5.0
165
173
  h3. Changes
166
174
  * Deprecated @opts, use #options now.
167
175
  * Added state-args. State methods can now receive the options as method arguments. This should be the prefered way of parameter exchange with the outer world.
168
- * #params, #request, and #config is now delegated to @parent_controller.
176
+ * #params, #request, and #config is now delegated to @parent_controller.
169
177
  * The generator now is invoked as @rails g cell ...@
170
178
  * The `--haml` option is no longer available.
171
179
  * The `-t` option now is compatible with the rest of rails generators, now it is used as alias for `--test-framework`. Use the `-e` option as an alias of `--template-engine`
172
180
  Thanks to Jorge Calás Lozano <calas@qvitta.net> for patching this in the most reasonable manner i could imagine.
173
181
  * Privatized @#find_family_view_for_state@, @#render_view_for@, and all *ize methods in Cell::Rails.
174
182
  * New signature: @#render_view_for(state, *args)@
175
-
183
+
176
184
  h2. 3.4.4
177
185
 
178
186
  h3. Changes
179
187
  * Cells.setup now yields Cell::Base, so you can really call append_view_path and friends here.
180
188
  * added Cell::Base.build for streamlining the process of deciders around #render_cell, "see here":http://nicksda.apotomo.de/2010/12/pragmatic-rails-thoughts-on-views-inheritance-view-inheritance-and-rails-304
181
189
  * added TestCase#in_view to test helpers in a real cell view.
182
-
190
+
183
191
 
184
192
  h2. 3.4.3
185
193
 
186
194
  h3. Changes
187
195
  * #render_cell now accepts a block which yields the cell instance before rendering.
188
-
196
+
189
197
  h3. Bugfixes
190
198
  * We no longer use TestTaskWithoutDescription in our rake tasks.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :gemcutter
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
data/README.md ADDED
@@ -0,0 +1,412 @@
1
+ # Cells
2
+
3
+ **View Components for Rails.**
4
+
5
+ ## Overview
6
+
7
+ Say you're writing a Rails online shop - the shopping cart is reappearing again and again in every view. You're thinking about a clean solution for that part. A mixture of controller code, before-filters, partials and helpers?
8
+
9
+ No. That sucks. Take Cells.
10
+
11
+ Cells are View Components for Rails. They look and feel like controllers. They don't have no `DoubleRenderError`. They can be rendered everywhere in your controllers or views. They are cacheable, testable, fast and wonderful. They bring back OOP to your view and improve your software design.
12
+
13
+ And the best: You can have as many cells in your page as you need!
14
+
15
+
16
+ Note: Since version 3.9 cells comes with two "dialects": You can still use a cell like a controller. However, the new [view model](https://github.com/apotonick/cells#view-models) "dialect" allows you to treat a cell more object-oriented while providing an alternative approach to helpers.
17
+
18
+ ## Installation
19
+
20
+ It's a gem!
21
+
22
+ Rails >= 3.0:
23
+
24
+ ```shell
25
+ gem install cells
26
+ ```
27
+
28
+ Rails 2.3:
29
+
30
+ ```shell
31
+ gem install cells -v 3.3.9
32
+ ```
33
+
34
+ ## Generate
35
+
36
+ Creating a cell is nothing more than
37
+
38
+ ```shell
39
+ rails generate cell cart show -e haml
40
+ ```
41
+
42
+ ```
43
+ create app/cells/
44
+ create app/cells/cart
45
+ create app/cells/cart_cell.rb
46
+ create app/cells/cart/show.html.haml
47
+ create test/cells/cart_test.rb
48
+ ```
49
+
50
+ That looks very familiar.
51
+
52
+ ## Render the cell
53
+
54
+ Now, render your cart. Why not put it in `layouts/application.html.erb` for now?
55
+
56
+ ```erb
57
+ <div id="header">
58
+ <%= render_cell :cart, :show, :user => @current_user %>
59
+ ```
60
+
61
+ Feels like rendering a controller action. For good encapsulation we pass the current `user` from outside into the cell - a dependency injection.
62
+
63
+ ## Code
64
+
65
+ Time to improve our cell code. Let's start with `app/cells/cart_cell.rb`:
66
+
67
+ ```ruby
68
+ class CartCell < Cell::Rails
69
+ def show(args)
70
+ user = args[:user]
71
+ @items = user.items_in_cart
72
+
73
+ render # renders show.html.haml
74
+ end
75
+ end
76
+ ```
77
+
78
+ Is that a controller? Hell, yeah. We even got a `#render` method as we know it from the good ol' `ActionController`.
79
+
80
+
81
+ ## Views
82
+
83
+ Since a plain call to `#render` will start rendering `app/cells/cart/show.html.haml` we should put some meaningful markup there.
84
+
85
+ ```haml
86
+ #cart
87
+ You have #{@items.size} items in your shopping cart.
88
+ ```
89
+
90
+ ### ERB? Haml? Builder?
91
+
92
+ Yes, Cells support all template types that are supported by Rails itself. Remember- it's a controller!
93
+
94
+ ### Helpers
95
+
96
+ Yes, Cells have helpers just like controllers. If you need some specific helper, do
97
+
98
+ ```ruby
99
+ class CartCell < Cell::Rails
100
+ helper MyExtraHelper
101
+ ```
102
+
103
+ and it will be around in your cart views.
104
+
105
+ ### Partials?
106
+
107
+ Yeah, we do support rendering partials in views. Nevertheless, we discourage _partials_ at all.
108
+
109
+ The distinction between partials and views is making things more complex, so why should we have two kinds of view types? Use ordinary views instead, they're fine.
110
+
111
+ ```haml
112
+ %p
113
+ = render :view => 'items'
114
+ ```
115
+
116
+ ### Rendering Global Partials
117
+
118
+ Sometimes you need to render a global partial from `app/views` within a cell. For instance, the `gmaps4rails` helper depends on a global partial. While this breaks encapsulation it's still possible in cells - just add the global view path.
119
+
120
+ ```ruby
121
+ class MapCell < Cell::Rails
122
+ append_view_path "app/views"
123
+ ```
124
+
125
+
126
+ ## View Inheritance
127
+
128
+ This is where OOP comes back to your view.
129
+
130
+ * __Inherit code__ into your cells by deriving more abstract cells.
131
+ * __Inherit views__ from parent cells.
132
+
133
+ ### Builders
134
+
135
+ Let `render_cell` take care of creating the right cell. Just configure your super-cell properly.
136
+
137
+ ```ruby
138
+ class LoginCell < Cell::Rails
139
+ build do
140
+ UnauthorizedUserCell unless logged_in?
141
+ end
142
+ ```
143
+
144
+ A call to
145
+
146
+ ```ruby
147
+ render_cell(:login, :box)
148
+ ```
149
+
150
+ will render the configured `UnauthorizedUserCell` instead of the original `LoginCell` if the login test fails.
151
+
152
+
153
+ ## Caching
154
+
155
+ Cells do strict view caching. No cluttered fragment caching. Add
156
+
157
+ ```ruby
158
+ class CartCell < Cell::Rails
159
+ cache :show, :expires_in => 10.minutes
160
+ ```
161
+
162
+ and your cart will be re-rendered after 10 minutes.
163
+
164
+ You can expand the state's cache key - why not use a versioner block to do just this?
165
+
166
+ ```ruby
167
+ class CartCell < Cell::Rails
168
+ cache :show do |cell, options|
169
+ options[:items].md5
170
+ end
171
+ ```
172
+
173
+ The block's return value is appended to the state key: `"cells/cart/show/0ecb1360644ce665a4ef"`.
174
+
175
+ Check the [API to learn more](http://rdoc.info/gems/cells/Cell/Caching/ClassMethods#cache-instance_method).
176
+
177
+ *Reminder*: If you want to test it in `development`, you need to put `config.action_controller.perform_caching = true` in `development.rb` to see the effect
178
+
179
+ ## Testing
180
+
181
+ Another big advantage compared to monolithic controller/helper/partial piles is the ability to test your cells isolated.
182
+
183
+ ### Test::Unit
184
+
185
+ So what if you wanna test the cart cell? Use the generated `test/cells/cart_cell_test.rb` test.
186
+
187
+ ```ruby
188
+ class CartCellTest < Cell::TestCase
189
+ test "show" do
190
+ invoke :show, :user => @user_fixture
191
+ assert_select "#cart", "You have 3 items in your shopping cart."
192
+ end
193
+ ```
194
+
195
+ Don't forget to put `require 'cell/test_case'` in your project's `test/test_helper.rb` file.
196
+
197
+ Then, run your tests with
198
+
199
+ ```shell
200
+ rake test:cells
201
+ ```
202
+
203
+ That's easy, clean and strongly improves your component-driven software quality. How'd you do that with partials?
204
+
205
+
206
+ ### RSpec
207
+
208
+ If you prefer RSpec examples, use the [rspec-cells](http://github.com/apotonick/rspec-cells) gem for specing.
209
+
210
+ ```ruby
211
+ it "should render the posts count" do
212
+ render_cell(:posts, :count).should have_selector("p", :content => "4 posts!")
213
+ end
214
+ ```
215
+
216
+ To run your specs we got a rake task, too!
217
+
218
+ ```shell
219
+ rake spec:cells
220
+ ```
221
+
222
+ # View Models
223
+
224
+ Cells 3.9 brings a new dialect to cells: view models (still experimental!).
225
+
226
+ Think of a view model as a cell decorating a model or a collection. In this mode, helpers are nothing more than instance methods of your cell class, making helpers predictable and scoped.
227
+
228
+ ```ruby
229
+ class SongCell < Cell::Rails
230
+ include Cell::Rails::ViewModel
231
+
232
+ property :title
233
+
234
+
235
+ def show
236
+ render
237
+ end
238
+
239
+ def self_link
240
+ link_to(title, song_url(model))
241
+ end
242
+ end
243
+ ```
244
+
245
+ ### Creation
246
+
247
+ Creating the view model should usually happen in the controller.
248
+
249
+ ```ruby
250
+ class DashboardController < ApplicationController
251
+
252
+ def index
253
+ @song = Song.find(1)
254
+
255
+ @cell = cell(:song, @song)
256
+ end
257
+ ```
258
+
259
+ You can now grab an instance of your cell using the `#cell` method. The 2nd argument will be the cell's decorated model.
260
+
261
+ Have a look at how to use this cell in your controller view.
262
+
263
+ ```haml
264
+ = @cell.show # renders its show view.
265
+ ```
266
+
267
+ You no longer use the `#render_cell` helper but call any method on that cell. Usually, this is a state (or "action") like `show`.
268
+
269
+ ### Helpers
270
+
271
+ Note that this doesn't have to be a rendering state, it could be any instance method (aka "helper").
272
+
273
+ ```haml
274
+ = @cell.self_link
275
+ ```
276
+
277
+ As all helpers are now instance methods, the `#self_link` example can use any existing helper (as the URL helpers) on the instance level.
278
+
279
+ Attributes declared using ``::property` are automatically delegated to the decorated model.
280
+
281
+ ```ruby
282
+ @cell.title # delegated to @song.title
283
+ ```
284
+
285
+ ### Views
286
+
287
+ This greatly reduces wiring in the cell view (which is still in `app/cells/song/show.haml`).
288
+
289
+ ```haml
290
+ %h1
291
+ = title
292
+
293
+ Bookmark! #{self_link}
294
+ ```
295
+
296
+ Making the cell instance itself the view context should be an interesting alternative for many views.
297
+
298
+
299
+ ## Mountable Cells
300
+
301
+ Cells 3.8 got rid of the ActionController dependency. This essentially means you can mount Cells to routes or use them like a Rack middleware. All you need to do is derive from Cell::Base.
302
+
303
+ ```ruby
304
+ class PostCell < Cell::Base
305
+ ...
306
+ end
307
+ ```
308
+
309
+ In your `routes.rb` file, mount the cell like a Rack app.
310
+
311
+ ```ruby
312
+ match "/posts" => proc { |env|
313
+ [ 200, {}, [ Cell::Base.render_cell_for(:post, :show) ]]
314
+ }
315
+ ```
316
+
317
+ ### Cells in ActionMailer
318
+
319
+ ActionMailer doesn't have request object, so if you inherit from Cell::Rails you will receive an error. Cell::Base will fix that problem, but you will not be able to use any of routes inside your cells.
320
+
321
+ You can fix that with [actionmailer_with_request](https://github.com/weppos/actionmailer_with_request) which (suprise!) brings request object to the ActionMailer.
322
+
323
+ ## Using Rails Gems Like simple_form Outside Of Rails
324
+
325
+ Cells can be used outside of Rails. A new module brought in 3.8.5 provides the Rails view "API" making it possible to use gems like the popular [simple_form](https://github.com/plataformatec/simple_form) outside Rails!
326
+
327
+ All you need to do is providing the cell with some helpers, usually it's the polymorphic routing paths required by the gems.
328
+
329
+ ```ruby
330
+ module RoutingHelpers
331
+ def musician_path(model)
332
+ "/musicians/#{model.id}"
333
+ end
334
+ end
335
+ ```
336
+
337
+ Then, use the Cell::Rails::HelperAPI module and it should work fine (depending on the quality of the gem you're desiring to use).
338
+
339
+ ```ruby
340
+ require 'cell/base'
341
+ require "cell/rails/helper_api"
342
+ require "simple_form"
343
+
344
+ class BassistCell < Cell::Base
345
+ include Cell::Rails::HelperAPI
346
+
347
+ self._helpers = RoutingHelpers
348
+
349
+ def show
350
+ @musician = Musician.find(:first)
351
+ end
352
+ end
353
+ ```
354
+
355
+ Your views can now use the gem's helpers.
356
+
357
+ ```erb
358
+ <%= simple_form_for @musician do |f| %>
359
+ <%= f.input :name %>
360
+ <%= f.button :submit %>
361
+ <% end %>
362
+ ```
363
+
364
+ Note that this currently "only" works with Rails 3.2-4.0.
365
+
366
+ ## Cells is Rails::Engine aware!
367
+
368
+ Now `Rails::Engine`s can contribute to Cells view paths. By default, any 'app/cells' found inside any Engine is automatically included into Cells view paths. If you need to, you can customize the view paths changing/appending to the `'app/cell_views'` path configuration. See the `Cell::EngineIntegration` for more details.
369
+
370
+ ## Generators
371
+
372
+ By default, generated cells inherit from `Cell::Rails`. If you want to change this, specify your new class name in `config/application.rb`:
373
+
374
+ ```ruby
375
+ module MyApp
376
+ class Application < Rails::Application
377
+ config.generators do |g|
378
+ g.base_cell_class "ApplicationCell"
379
+ end
380
+ end
381
+ end
382
+ ```
383
+
384
+ ## Rails 2.3 note
385
+
386
+ In order to copy the cells rake tasks to your app, run
387
+
388
+ ```shell
389
+ script/generate cells_install
390
+ ```
391
+
392
+ ## Capture Support
393
+
394
+ If you need a global `#content_for` use the [cells-capture](https://github.com/apotonick/cells-capture) gem.
395
+
396
+ ## More features
397
+
398
+ Cells can do more.
399
+
400
+ * __No Limits__. Have as many cells in your page as you need - no limitation to your `render_cell` calls.
401
+ * __Cell Nesting__. Have complex cell hierarchies as you can call `render_cell` within cells, too.
402
+
403
+ Go for it, you'll love it!
404
+
405
+
406
+ ## LICENSE
407
+
408
+ Copyright (c) 2007-2013, Nick Sutterer
409
+
410
+ Copyright (c) 2007-2008, Solide ICT by Peter Bex and Bob Leers
411
+
412
+ Released under the MIT License.