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
@@ -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