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.
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
@@ -10,3 +10,10 @@ gemfile:
10
10
  - gemfiles/Gemfile.rails3-2
11
11
  - gemfiles/Gemfile.rails4-0
12
12
  - gemfiles/Gemfile.rails4-1
13
+
14
+ matrix:
15
+ exclude:
16
+ - rvm: 2.0.0
17
+ gemfile: gemfiles/Gemfile.rails3-0
18
+ - rvm: 2.0.0
19
+ gemfile: gemfiles/Gemfile.rails3-1
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
@@ -5,4 +5,4 @@ gemspec
5
5
  #gem "rails" , :path => "../rayls"
6
6
 
7
7
  gem "rails", "~> 3.2.12"
8
- gem 'minitest', '4.7.5'
8
+ gem 'minitest', '4.7.5'
data/README.md CHANGED
@@ -1,35 +1,43 @@
1
1
  # Cells
2
2
 
3
- **View Components for Rails.**
3
+ *View Components for Rails.*
4
+
4
5
 
5
6
  ## Overview
6
7
 
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
+ 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
- No. That sucks. Take Cells.
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
- 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
+ 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
- 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
+ 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
- ## Installation
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
- Rails >= 3.0:
22
+ ## Installation
23
23
 
24
- ```shell
25
- gem install cells
24
+ ```ruby
25
+ gem 'cells'
26
26
  ```
27
27
 
28
- Rails 2.3:
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
- 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.
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
- In Cells 3.10 we introduce a new _optional_ file structure integrating with [trailblazer](https://github.com/apotonick/trailblazer)'s "concept-oriented" layout.
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
- options[:items].md5
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
- The block's return value is appended to the state key: `"cells/cart/show/0ecb1360644ce665a4ef"`.
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
- Cells 3.9 brings a new dialect to cells: view models.
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
- class SongCell < Cell::Rails
370
- include ViewModel
426
+ # app/cells/song_cell.rb
427
+ class SongCell < Cell::ViewModel
428
+ end
429
+ ```
371
430
 
372
- property :title
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
- ### Creation
461
+ The `render` call will render the cell's `show` view.
462
+
463
+ ### Views
386
464
 
387
- Creating the view model should usually happen in the controller.
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 DashboardController < ApplicationController
480
+ class SongCell < Cell::ViewModel
481
+ include TimeagoHelper
391
482
 
392
- def index
393
- @song = Song.find(1)
483
+ def show
484
+ render
485
+ end
394
486
 
395
- @cell = cell(:song, @song)
487
+ def composed_at
488
+ timeago(model.created_at)
396
489
  end
490
+ end
397
491
  ```
398
492
 
399
- You can now grab an instance of your cell using the `#cell` method. The 2nd argument will be the cell's decorated model.
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
- Have a look at how to use this cell in your controller view.
495
+ The `#model` methods lets you access the wrapped `Song` instance we passed into the cell when creating it.
402
496
 
403
- ```haml
404
- = @cell.show # renders its show view.
405
- ```
497
+ ### Properties
406
498
 
407
- You no longer use the `#render_cell` helper but call any method on that cell. Usually, this is a state (or "action") like `show`.
499
+ Often, it is helpful to automatically expose some reader methods to the model. You can do that with `::property`.
408
500
 
409
- ### Helpers
501
+ ```ruby
502
+ class SongCell < Cell::ViewModel
503
+ include TimeagoHelper
410
504
 
411
- Note that this doesn't have to be a rendering state, it could be any instance method (aka "helper").
505
+ property :title
412
506
 
413
- ```haml
414
- = @cell.self_link
507
+ # ...
508
+ end
415
509
  ```
416
510
 
417
- As all helpers are now instance methods, the `#self_link` example can use any existing helper (as the URL helpers) on the instance level.
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
- Attributes declared using ``::property` are automatically delegated to the decorated model.
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
- @cell.title # delegated to @song.title
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
- ### Views
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
- This greatly reduces wiring in the cell view (which is still in `app/cells/song/show.haml`).
533
+ ### Encapsulation
428
534
 
429
- ```haml
430
- %h1
431
- = title
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
- Bookmark! #{self_link}
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
- Making the cell instance itself the view context should be an interesting alternative for many views.
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-2013, Nick Sutterer
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
+ ```
@@ -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.4"
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
@@ -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 'simple_form', '~> 3.0.0'
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"
@@ -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.0.rc2'
7
- gem 'activemodel', '4.1.0.rc2'
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'
@@ -5,109 +5,78 @@ require 'cell/rendering'
5
5
  require 'cell/dsl'
6
6
 
7
7
  module Cell
8
- module RailsVersion
9
- def rails3_0?
10
- ::ActionPack::VERSION::MAJOR == 3 and ::ActionPack::VERSION::MINOR == 0
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
- require 'cell/rails3_0_strategy' if Cell.rails3_0?
44
- require 'cell/rails3_1_strategy' if Cell.rails3_1_or_more?
45
- require 'cell/rails4_0_strategy' if Cell.rails4_0?
46
- require 'cell/rails4_1_strategy' if Cell.rails4_1_or_more?
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
- private
59
- def process_args(*)
42
+ def self.class_from_cell_name(name)
43
+ "#{name}_cell".classify.constantize
60
44
  end
61
45
 
62
- class View < ActionView::Base
63
- def self.prepare(modules)
64
- # TODO: remove for 4.0 if PR https://github.com/rails/rails/pull/6826 is merged.
65
- Class.new(self) do # DISCUSS: why are we mixing that stuff into this _anonymous_ class at all? that makes things super complicated.
66
- include *modules.reverse
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
- def render(*args, &block)
71
- options = args.first.is_a?(::Hash) ? args.first : {} # this is copied from #render by intention.
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
- return controller.render(*args, &block) if options[:state] or options[:view]
74
- super
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
- # Enforces the new trailblazer directory layout where cells (or concepts in general) are fully self-contained in its own directory.
96
- module SelfContained
97
- def self_contained!
98
- include Prefixes
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