cells 3.10.1 → 3.11.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.
- data/.travis.yml +7 -0
- data/CHANGES.md +18 -0
- data/Gemfile +1 -1
- data/README.md +182 -57
- data/TODO.md +9 -0
- data/cells.gemspec +3 -1
- data/gemfiles/Gemfile.rails4-0 +2 -1
- data/gemfiles/Gemfile.rails4-1 +5 -3
- data/lib/cell/base.rb +33 -64
- data/lib/cell/base/prefixes.rb +27 -0
- data/lib/cell/base/self_contained.rb +13 -0
- data/lib/cell/base/view.rb +15 -0
- data/lib/cell/builder.rb +52 -53
- data/lib/cell/caching.rb +21 -4
- data/lib/cell/concept.rb +85 -0
- data/lib/cell/rails.rb +13 -6
- data/lib/cell/rails/view_model.rb +47 -6
- data/lib/cell/rendering.rb +13 -13
- data/lib/cell/test_case.rb +3 -3
- data/lib/cell/view_model.rb +151 -0
- data/lib/cells.rb +0 -60
- data/lib/cells/rails.rb +10 -5
- data/lib/cells/railtie.rb +2 -5
- data/lib/cells/version.rb +1 -1
- data/lib/generators/erb/concept_generator.rb +17 -0
- data/lib/generators/haml/concept_generator.rb +17 -0
- data/lib/generators/rails/concept_generator.rb +16 -0
- data/lib/generators/templates/concept/cell.rb +9 -0
- data/lib/generators/templates/concept/view.erb +7 -0
- data/lib/generators/templates/concept/view.haml +4 -0
- data/lib/generators/trailblazer/base.rb +21 -0
- data/lib/generators/trailblazer/view_generator.rb +18 -0
- data/test/app/cells/bassist_cell.rb +1 -1
- data/test/app/cells/record/views/layout.haml +2 -0
- data/test/app/cells/record/views/show.erb +1 -0
- data/test/app/cells/record/views/song.erb +1 -0
- data/test/app/cells/song/scale.haml +1 -0
- data/test/cell_module_test.rb +18 -37
- data/test/cells_module_test.rb +1 -1
- data/test/concept_generator_test.rb +26 -0
- data/test/concept_test.rb +78 -0
- data/test/dummy/Rakefile +1 -1
- data/test/dummy/app/assets/javascripts/application.js +2 -0
- data/test/dummy/app/cells/album/assets/album.js +1 -0
- data/test/dummy/app/concepts/song/assets/songs.js +1 -0
- data/test/dummy/config/application.rb +11 -6
- data/test/dummy/label/label.gemspec +2 -2
- data/test/helper_test.rb +2 -2
- data/test/prefixes_test.rb +75 -0
- data/test/rails/asset_pipeline_test.rb +20 -0
- data/test/rails/caching_test.rb +1 -9
- data/test/rails/cells_test.rb +2 -17
- data/test/rails/forms_test.rb +2 -1
- data/test/rails/integration_test.rb +199 -8
- data/test/rails/render_test.rb +2 -10
- data/test/rails/view_model_test.rb +135 -60
- data/test/rails_helper_api_test.rb +2 -1
- data/test/self_contained_test.rb +9 -2
- data/test/test_case_test.rb +2 -2
- data/test/test_helper.rb +2 -3
- metadata +117 -33
- checksums.yaml +0 -7
- data/test/dummy/app/controllers/musician_controller.rb +0 -36
- data/test/rails/router_test.rb +0 -45
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 3.11.0
|
2
|
+
|
3
|
+
* Deprecated `Cell::Rails::ViewModel`, please inherit: `class SongCell < Cell::ViewModel`.
|
4
|
+
* `ViewModel#call` is now the prefered way to invoke the rendering flow. Without any argument, `call` will run `render_state(:show)`. Pass in any method name you want.
|
5
|
+
* Added `Caching::Notifications`.
|
6
|
+
* Added `cell(:song, collection: [song1, song2])` to render collections. This only works with ViewModel (and, of course, Concept, too).
|
7
|
+
* Added `::inherit_views` to only inherit views whereas real class inheritance would inherit all the dark past of the class.
|
8
|
+
* `::build_for` removed/privatized/changed. Use `Cell::Base::cell_for` instead.
|
9
|
+
* `Base::_parent_prefixes` is no longer used, if you override that somewhere in your cells it will break. We have our own implementation for computing the controller's prefixes in `Cell::Base::Prefixes` (simpler).
|
10
|
+
* `#expire_cell_state` doesn't take symbols anymore, only the real cell class name.
|
11
|
+
* Remove `Cell::Base.setup_view_paths!` and `Cell::Base::DEFAULT_VIEW_PATHS` and the associated Railtie. I don't know why this code survived 3 major versions, if you wanna set you own view paths just use `Cell::Base.view_paths=`.
|
12
|
+
* Add `Base::self_contained!`.
|
13
|
+
* Add `Base::inherit_views`.
|
14
|
+
|
15
|
+
### Concept
|
16
|
+
* `#concept` helper is mixed into all views as an alternative to `#cell` and `#render_cell`. Let us know if we should do that conditionally, only.
|
17
|
+
* Concept cells look for layouts in their self-contained views directory.
|
18
|
+
|
1
19
|
## 3.10.1
|
2
20
|
|
3
21
|
Allow packaging assets for Rails' asset pipeline into cells. This is still experimental but works great. I love it.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,35 +1,43 @@
|
|
1
1
|
# Cells
|
2
2
|
|
3
|
-
|
3
|
+
*View Components for Rails.*
|
4
|
+
|
4
5
|
|
5
6
|
## Overview
|
6
7
|
|
7
|
-
|
8
|
+
Cells allow you to encapsulate parts of your page into a separate MVC component. They look and feel like controllers, can run arbitrary code in an action and render views.
|
8
9
|
|
9
|
-
|
10
|
+
While they improve your overall software architecture by abstracting logic into an encapsulated OOP instance, cells also maximise reuseability within or across projects.
|
10
11
|
|
11
|
-
|
12
|
+
Basically, cells can be rendered anywhere in your code. Most people use them in views to replace a helper/partial/filter mess, as a mailer renderer substitute or hook them to routes and completely bypass `ActionController`.
|
12
13
|
|
13
|
-
And the best: You can have as many cells in your page as you need!
|
14
14
|
|
15
|
+
## View Models
|
15
16
|
|
16
|
-
|
17
|
+
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-explained) "dialect" allows you to treat a cell more object-oriented while providing an alternative approach to helpers.
|
17
18
|
|
18
|
-
|
19
|
+
While the old dialect still works, we strongly recommend using a cell as a view model.
|
19
20
|
|
20
|
-
It's a gem!
|
21
21
|
|
22
|
-
|
22
|
+
## Installation
|
23
23
|
|
24
|
-
```
|
25
|
-
gem
|
24
|
+
```ruby
|
25
|
+
gem 'cells'
|
26
26
|
```
|
27
27
|
|
28
|
-
|
28
|
+
## File Layout
|
29
|
+
|
30
|
+
Cells are placed in `app/cells`.
|
29
31
|
|
30
|
-
```shell
|
31
|
-
gem install cells -v 3.3.9
|
32
32
|
```
|
33
|
+
app
|
34
|
+
├── cells
|
35
|
+
│ ├── comment_cell.rb
|
36
|
+
│ ├── comment
|
37
|
+
│ │ ├── show.haml
|
38
|
+
│ │ ├── list.haml
|
39
|
+
```
|
40
|
+
|
33
41
|
|
34
42
|
## Generate
|
35
43
|
|
@@ -104,18 +112,22 @@ and it will be around in your cart views.
|
|
104
112
|
|
105
113
|
### Partials?
|
106
114
|
|
107
|
-
|
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.
|
115
|
+
In Cells, everything template file is a _view_. You're still free to render views within views (aka "partial") but we just call it "_view_". There's no need to have two different types of views. Whenever you're tempted to render a partial, use the cells term `view`.
|
110
116
|
|
111
117
|
```haml
|
118
|
+
/ app/cells/comment/show.haml
|
119
|
+
|
120
|
+
%h1 All comments
|
121
|
+
|
112
122
|
%p
|
113
123
|
= render :view => 'items'
|
114
124
|
```
|
115
125
|
|
116
126
|
## File Structure
|
117
127
|
|
118
|
-
|
128
|
+
TODO: rails g concept Song => show.haml,
|
129
|
+
|
130
|
+
In Cells 3.10 we introduce a new _optional_ file structure integrating with [Trailblazer](https://github.com/apotonick/trailblazer)'s "concept-oriented" layout.
|
119
131
|
|
120
132
|
This new file layout makes a cell fully **self-contained** so it can be moved around just by grabbing one single directory.
|
121
133
|
|
@@ -213,6 +225,25 @@ This is where OOP comes back to your view.
|
|
213
225
|
* __Inherit views__ from parent cells.
|
214
226
|
|
215
227
|
|
228
|
+
### Sharing Views
|
229
|
+
|
230
|
+
Sometimes it is handy to reuse an existing view directory from another cell, to avoid a growing number of directories. You could derive the new cell and thus inherit the view paths.
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
class Comment::FormCell < CommentCell
|
234
|
+
```
|
235
|
+
|
236
|
+
This does not only allow view inheritance, but will also inherit all the code from `CommentCell`. This might not be what you want.
|
237
|
+
|
238
|
+
If you're just after inheriting the _views_, use `::inherit_views`.
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
class Comment::FormCell < Cell::Rails
|
242
|
+
inherit_views CommentCell
|
243
|
+
```
|
244
|
+
|
245
|
+
When rendering views in `FormCell`, the view directories to look for templates will be inherited.
|
246
|
+
|
216
247
|
### Builders
|
217
248
|
|
218
249
|
Let `render_cell` take care of creating the right cell. Just configure your super-cell properly.
|
@@ -291,12 +322,37 @@ You can expand the state's cache key by appending a versioner block to the `::ca
|
|
291
322
|
```ruby
|
292
323
|
class CartCell < Cell::Rails
|
293
324
|
cache :show do |options|
|
294
|
-
|
325
|
+
order.id
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
The versioner block is executed in the cell instance context, allowing you to access all stakeholder objects you need to compute a cache key. The return value is appended to the state key: `"cells/cart/show/1"`.
|
330
|
+
|
331
|
+
As everywhere in Rails, you can also return an array.
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
class CartCell < Cell::Rails
|
335
|
+
cache :show do |options|
|
336
|
+
[id, options[:items].md5]
|
295
337
|
end
|
296
338
|
```
|
297
339
|
|
298
|
-
|
340
|
+
Resulting in: `"cells/cart/show/1/0ecb1360644ce665a4ef"`.
|
341
|
+
|
342
|
+
|
343
|
+
### Debugging Cache
|
299
344
|
|
345
|
+
When caching is turned on, you might wanna see notifications. Just like a controller, Cells gives you the following notifications.
|
346
|
+
|
347
|
+
* `write_fragment.action_controller` for cache miss.
|
348
|
+
* `read_fragment.action_controller` for cache hits.
|
349
|
+
|
350
|
+
To activate notifications, include the `Notifications` module in your cell.
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
class Comment::Cell < Cell::Rails
|
354
|
+
include Cell::Caching::Notifications
|
355
|
+
```
|
300
356
|
|
301
357
|
### Inheritance
|
302
358
|
|
@@ -359,81 +415,144 @@ To run your specs we got a rake task, too!
|
|
359
415
|
rake spec:cells
|
360
416
|
```
|
361
417
|
|
362
|
-
# View Models
|
418
|
+
# View Models, Explained
|
363
419
|
|
364
|
-
|
420
|
+
View models supersede the old controller-like cells. View models feel more natural as they wrap domain models and then add decorating methods for the view.
|
421
|
+
|
422
|
+
They are also significantly faster since they don't need to copy helpers and instance variables to the view: The view model itself is the view context. That means, methods called in the view are invoked on your cell instance.
|
365
423
|
|
366
|
-
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.
|
367
424
|
|
368
425
|
```ruby
|
369
|
-
|
370
|
-
|
426
|
+
# app/cells/song_cell.rb
|
427
|
+
class SongCell < Cell::ViewModel
|
428
|
+
end
|
429
|
+
```
|
371
430
|
|
372
|
-
|
431
|
+
### Creation
|
432
|
+
|
433
|
+
Instantiating the view model should happen in controllers and views, but you can virtually use them anywhere.
|
434
|
+
|
435
|
+
A default workflow for creating and rendering a view model looks as the following.
|
436
|
+
|
437
|
+
```ruby
|
438
|
+
song = Song.find(1)
|
439
|
+
|
440
|
+
@cell = cell(:song, song).call
|
441
|
+
```
|
373
442
|
|
443
|
+
The `#cell` helper gives you an instance of the `SongCell` cell and wraps the `song` object.
|
374
444
|
|
445
|
+
### Rendering
|
446
|
+
|
447
|
+
The `call` invocation instructs the cell to render. Internally, that runs `render_state(:show)` per default.
|
448
|
+
|
449
|
+
You can basically invoke any method you want on that cell. Nevertheless, a view model should only expose the `#show` method per convention, which is reflected by the `#call` alias.
|
450
|
+
|
451
|
+
It is important to understand this convention: Internally, you may render multiple views, combine them, use instance methods to render and format values, and so on. Externally, exposing only one "public", rendering method defines a strong interface for your view model.
|
452
|
+
|
453
|
+
```ruby
|
454
|
+
class SongCell < Cell::ViewModel
|
375
455
|
def show
|
376
456
|
render
|
377
457
|
end
|
378
|
-
|
379
|
-
def self_link
|
380
|
-
link_to(title, song_url(model))
|
381
|
-
end
|
382
458
|
end
|
383
459
|
```
|
384
460
|
|
385
|
-
|
461
|
+
The `render` call will render the cell's `show` view.
|
462
|
+
|
463
|
+
### Views
|
386
464
|
|
387
|
-
|
465
|
+
```haml
|
466
|
+
- # app/cells/song/show.haml
|
467
|
+
|
468
|
+
%h1 #{title}
|
469
|
+
|
470
|
+
%p Written at #{composed_at}
|
471
|
+
|
472
|
+
= author_box
|
473
|
+
```
|
474
|
+
|
475
|
+
We strongly recommend to invoke methods, only, in views and not to use instance variables and locals. In a view model template (or, view), methods are called on the view model instance itself, meaning you can easily expose "helpers" by defining instance methods.
|
476
|
+
|
477
|
+
### Helpers
|
388
478
|
|
389
479
|
```ruby
|
390
|
-
class
|
480
|
+
class SongCell < Cell::ViewModel
|
481
|
+
include TimeagoHelper
|
391
482
|
|
392
|
-
def
|
393
|
-
|
483
|
+
def show
|
484
|
+
render
|
485
|
+
end
|
394
486
|
|
395
|
-
|
487
|
+
def composed_at
|
488
|
+
timeago(model.created_at)
|
396
489
|
end
|
490
|
+
end
|
397
491
|
```
|
398
492
|
|
399
|
-
|
493
|
+
In other words, using `composed_at` in the view will call `SongCell#composed_at`. Note that you have to `include` additional helpers into the class.
|
400
494
|
|
401
|
-
|
495
|
+
The `#model` methods lets you access the wrapped `Song` instance we passed into the cell when creating it.
|
402
496
|
|
403
|
-
|
404
|
-
= @cell.show # renders its show view.
|
405
|
-
```
|
497
|
+
### Properties
|
406
498
|
|
407
|
-
|
499
|
+
Often, it is helpful to automatically expose some reader methods to the model. You can do that with `::property`.
|
408
500
|
|
409
|
-
|
501
|
+
```ruby
|
502
|
+
class SongCell < Cell::ViewModel
|
503
|
+
include TimeagoHelper
|
410
504
|
|
411
|
-
|
505
|
+
property :title
|
412
506
|
|
413
|
-
|
414
|
-
|
507
|
+
# ...
|
508
|
+
end
|
415
509
|
```
|
416
510
|
|
417
|
-
|
511
|
+
You can now safely use `#title` in the view (and, in the cell class), it is delegated to `model.title`.
|
512
|
+
|
513
|
+
### Nested Rendering
|
418
514
|
|
419
|
-
|
515
|
+
When extracting parts of your view into a partial, as we did for the author section, you're free to render additional views using `#render`. Again, wrap render calls in instance methods, otherwise you'll end up with too much logic in your view.
|
420
516
|
|
421
517
|
```ruby
|
422
|
-
|
518
|
+
class SongCell < Cell::ViewModel
|
519
|
+
include TimeagoHelper
|
520
|
+
|
521
|
+
property :title
|
522
|
+
|
523
|
+
# ...
|
524
|
+
|
525
|
+
def author_box
|
526
|
+
render :author # same as render view: :author
|
527
|
+
end
|
528
|
+
end
|
423
529
|
```
|
424
530
|
|
425
|
-
|
531
|
+
This will simply render the `author.haml` template in the same context as the `show` view, meaning you might use helpers, again.
|
426
532
|
|
427
|
-
|
533
|
+
### Encapsulation
|
428
534
|
|
429
|
-
|
430
|
-
|
431
|
-
|
535
|
+
If in doubt, encapsulate nested parts of your view into a separate cell. You can use the `#cell` method in your cell to instantiate a nested cell.
|
536
|
+
|
537
|
+
Designing view models to create kickass UIs for your domain layer is discussed in 50+ pages in [my upcoming book](http://nicksda.apotomo.de).
|
432
538
|
|
433
|
-
|
539
|
+
### Alternative Instantiation
|
540
|
+
|
541
|
+
You don't need to pass in a model, it can also be a hash for a composition.
|
542
|
+
|
543
|
+
```ruby
|
544
|
+
cell(album, song: song, composer: album.composer)
|
434
545
|
```
|
435
546
|
|
436
|
-
|
547
|
+
This will create two readers in the cell for you automatically: `#song` and `#composer`.
|
548
|
+
|
549
|
+
|
550
|
+
Note that we are still working on a declarative API for compositions. It will be similar to the one found in Reform, Disposable::Twin and Representable:
|
551
|
+
|
552
|
+
```ruby
|
553
|
+
property :title, on: :song
|
554
|
+
property :last_name, on: :composer
|
555
|
+
```
|
437
556
|
|
438
557
|
|
439
558
|
## Mountable Cells
|
@@ -536,6 +655,12 @@ end
|
|
536
655
|
|
537
656
|
## Rails 2.3 note
|
538
657
|
|
658
|
+
### Installation
|
659
|
+
|
660
|
+
```shell
|
661
|
+
gem install cells -v 3.3.9
|
662
|
+
```
|
663
|
+
|
539
664
|
In order to copy the cells rake tasks to your app, run
|
540
665
|
|
541
666
|
```shell
|
@@ -558,7 +683,7 @@ Go for it, you'll love it!
|
|
558
683
|
|
559
684
|
## LICENSE
|
560
685
|
|
561
|
-
Copyright (c) 2007-
|
686
|
+
Copyright (c) 2007-2014, Nick Sutterer
|
562
687
|
|
563
688
|
Copyright (c) 2007-2008, Solide ICT by Peter Bex and Bob Leers
|
564
689
|
|
data/TODO.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# 4.0
|
2
|
+
|
3
|
+
* Get rid of the annoying `ActionController` dependency that needs to be passed into each cell. We only need it for "contextual links", when people wanna link to the same page. Make them pass in a URL generator object as a normal argument instead.
|
4
|
+
* Generated cells will be view models per default.
|
5
|
+
* Introduce Composition as in Reform, Representable, etc, when passing in a hash.
|
6
|
+
```ruby
|
7
|
+
include Composition
|
8
|
+
property :id, on: :comment
|
9
|
+
```
|
data/cells.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.add_dependency "actionpack", ">= 3.0"
|
23
23
|
s.add_dependency "railties", ">= 3.0"
|
24
|
-
s.add_dependency "uber", "~> 0.0.
|
24
|
+
s.add_dependency "uber", "~> 0.0.6"
|
25
25
|
|
26
26
|
s.add_development_dependency "rake"
|
27
27
|
s.add_development_dependency "haml"
|
@@ -29,4 +29,6 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_development_dependency "tzinfo" # FIXME: why the hell do we need this for 3.1?
|
30
30
|
s.add_development_dependency "minitest", ">= 4.7.5"
|
31
31
|
s.add_development_dependency "activemodel"
|
32
|
+
s.add_development_dependency "capybara"
|
33
|
+
s.add_development_dependency "sprockets"
|
32
34
|
end
|
data/gemfiles/Gemfile.rails4-0
CHANGED
@@ -6,6 +6,7 @@ gemspec path: '../'
|
|
6
6
|
gem 'railties', '4.0.2'
|
7
7
|
gem 'activemodel', '4.0.2'
|
8
8
|
gem 'minitest', '4.7.5'
|
9
|
-
gem '
|
9
|
+
gem 'sprockets', '~> 2.1'
|
10
|
+
gem 'sprockets-rails', '~> 2.1.3', :require => 'sprockets/railtie'
|
10
11
|
|
11
12
|
gem 'label', :path => "../test/dummy/label"
|
data/gemfiles/Gemfile.rails4-1
CHANGED
@@ -3,8 +3,10 @@ source "http://rubygems.org"
|
|
3
3
|
# Specify your gem's dependencies in cells.gemspec
|
4
4
|
gemspec path: '../'
|
5
5
|
|
6
|
-
gem 'railties', '4.1.
|
7
|
-
gem 'activemodel', '4.1.
|
6
|
+
gem 'railties', '4.1.1'
|
7
|
+
gem 'activemodel', '4.1.1'
|
8
8
|
gem 'minitest', '5.2.0'
|
9
|
+
gem 'sprockets', '~> 2.1'
|
10
|
+
gem 'sprockets-rails', '~> 2.1.3', :require => 'sprockets/railtie'
|
9
11
|
|
10
|
-
gem 'label', :path => "../test/dummy/label"
|
12
|
+
gem 'label', :path => "../test/dummy/label", :require => 'label'
|
data/lib/cell/base.rb
CHANGED
@@ -5,109 +5,78 @@ require 'cell/rendering'
|
|
5
5
|
require 'cell/dsl'
|
6
6
|
|
7
7
|
module Cell
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def rails3_1_or_more?
|
14
|
-
(::ActionPack::VERSION::MAJOR == 3 and ::ActionPack::VERSION::MINOR >= 1)
|
15
|
-
end
|
16
|
-
|
17
|
-
def rails3_2_or_more?
|
18
|
-
(::ActionPack::VERSION::MAJOR == 3 and ::ActionPack::VERSION::MINOR >= 2)
|
19
|
-
end
|
20
|
-
|
21
|
-
def rails4_0?
|
22
|
-
::ActionPack::VERSION::MAJOR == 4 and ::ActionPack::VERSION::MINOR == 0
|
23
|
-
end
|
24
|
-
|
25
|
-
def rails4_1_or_more?
|
26
|
-
(::ActionPack::VERSION::MAJOR == 4 and ::ActionPack::VERSION::MINOR >= 1) or ::ActionPack::VERSION::MAJOR > 4
|
27
|
-
end
|
28
|
-
alias_method :rails4_1?, :rails4_1_or_more?
|
8
|
+
require 'uber/version'
|
9
|
+
def self.rails_version
|
10
|
+
Uber::Version.new(::ActionPack::VERSION::STRING)
|
29
11
|
end
|
30
|
-
extend RailsVersion # TODO: deprecate in 3.10.
|
31
12
|
|
32
13
|
|
33
14
|
class Base < AbstractController::Base
|
34
15
|
# TODO: deprecate Base in favour of Cell.
|
35
|
-
|
36
16
|
abstract!
|
37
|
-
DEFAULT_VIEW_PATHS = [File.join('app', 'cells')]
|
38
17
|
|
39
|
-
extend Builder
|
40
18
|
include AbstractController
|
41
19
|
include AbstractController::Rendering, Helpers, Callbacks, Translation, Logger
|
42
20
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
require 'cell/
|
21
|
+
self.view_paths = "app/cells"
|
22
|
+
|
23
|
+
|
24
|
+
require 'cell/rails3_0_strategy' if Cell.rails_version.~ "3.0"
|
25
|
+
require 'cell/rails3_1_strategy' if Cell.rails_version.~( "3.1", "3.2")
|
26
|
+
require 'cell/rails4_0_strategy' if Cell.rails_version.~ "4.0"
|
27
|
+
require 'cell/rails4_1_strategy' if Cell.rails_version >= "4.1"
|
47
28
|
include VersionStrategy
|
48
29
|
include Layouts
|
49
30
|
include Rendering
|
50
31
|
include Caching
|
51
32
|
include Cell::DSL
|
52
33
|
|
34
|
+
extend Builder::ClassMethods # ::build DSL method and ::builders.
|
35
|
+
|
36
|
+
|
53
37
|
def initialize(*args)
|
54
38
|
super() # AbC::Base.
|
55
39
|
process_args(*args)
|
56
40
|
end
|
57
41
|
|
58
|
-
|
59
|
-
|
42
|
+
def self.class_from_cell_name(name)
|
43
|
+
"#{name}_cell".classify.constantize
|
60
44
|
end
|
61
45
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
46
|
+
|
47
|
+
class << self
|
48
|
+
# Main entry point for instantiating cells.
|
49
|
+
def cell_for(name, *args)
|
50
|
+
Builder.new(class_from_cell_name(name), self).call(*args)
|
68
51
|
end
|
69
52
|
|
70
|
-
|
71
|
-
|
53
|
+
alias_method :create_cell_for, :cell_for # TODO: remove us in 3.12.
|
54
|
+
ActiveSupport::Deprecation.deprecate_methods(self, :create_cell_for => :cell_for)
|
55
|
+
end
|
72
56
|
|
73
|
-
|
74
|
-
|
75
|
-
end
|
57
|
+
private
|
58
|
+
def process_args(*)
|
76
59
|
end
|
77
60
|
|
78
61
|
|
79
|
-
def self.view_context_class
|
62
|
+
def self.view_context_class # DISCUSS: this is only needed for non-vm cells.
|
80
63
|
@view_context_class ||= begin
|
81
64
|
Cell::Base::View.prepare(helper_modules)
|
82
65
|
end
|
83
66
|
end
|
84
67
|
|
85
|
-
# Called in Railtie at initialization time.
|
86
|
-
def self.setup_view_paths!
|
87
|
-
self.view_paths = self::DEFAULT_VIEW_PATHS
|
88
|
-
end
|
89
|
-
|
90
68
|
def self.controller_path
|
91
69
|
@controller_path ||= name.sub(/Cell$/, '').underscore unless anonymous?
|
92
70
|
end
|
93
71
|
|
94
72
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
module Prefixes
|
102
|
-
def _prefixes
|
103
|
-
@_prefixes ||= begin
|
104
|
-
super.tap do |prefixes|
|
105
|
-
prefixes[-1] = "#{controller_path}/views" # replace comment/.
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
73
|
+
require 'cell/base/view'
|
74
|
+
require 'cell/base/prefixes'
|
75
|
+
include Prefixes
|
76
|
+
require 'cell/base/self_contained'
|
111
77
|
extend SelfContained
|
112
78
|
end
|
79
|
+
|
80
|
+
autoload :ViewModel, 'cell/view_model'
|
81
|
+
autoload :Concept, 'cell/concept'
|
113
82
|
end
|