lotus-view 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -105
- data/README.md +20 -10
- data/lib/lotus/layout.rb +2 -1
- data/lib/lotus/presenter.rb +12 -0
- data/lib/lotus/view.rb +9 -11
- data/lib/lotus/view/configuration.rb +114 -6
- data/lib/lotus/view/dsl.rb +13 -13
- data/lib/lotus/view/rendering/layout_finder.rb +1 -1
- data/lib/lotus/view/rendering/layout_registry.rb +11 -0
- data/lib/lotus/view/rendering/layout_scope.rb +50 -5
- data/lib/lotus/view/rendering/null_template.rb +6 -2
- data/lib/lotus/view/rendering/scope.rb +27 -2
- data/lib/lotus/view/template.rb +3 -5
- data/lib/lotus/view/version.rb +1 -1
- data/lotus-view.gemspec +2 -1
- metadata +11 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e8fa1effeef34385f8e2500ab74842e8d196f9bf
|
|
4
|
+
data.tar.gz: 203e83425ed18d487d19cc825443fed66c53c86e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b1317306b81d7579d3a3894ba2f22584f69f28039a0161a706c3d3cb7f89cc5a2b591c09e7c57b684d53870a9b96010a8db882717cd8a6ce0d9574f59be4b81
|
|
7
|
+
data.tar.gz: bee5b8b82b89c9e561bc89bffb53ba3a01028393934fb8bfa350e7fb13c240a305061a3c9b8196abadb710c13d3654b932a4986a609b06280c49c7abc24c6af0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,105 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
426eaf7 2014-03-21 **Luca Guidi** Allow custom rendering policies. Views can override #render and decide how to return the output.
|
|
58
|
-
|
|
59
|
-
b2759f8 2014-03-18 **Luca Guidi** Lotus::View::Layout => Lotus::Layout
|
|
60
|
-
|
|
61
|
-
c0c04a8 2014-03-17 **Luca Guidi** Remove private method for Presenter: #object
|
|
62
|
-
|
|
63
|
-
74ca485 2014-03-13 **Luca Guidi** Introduced Lotus::Presenter
|
|
64
|
-
|
|
65
|
-
0ee9c10 2014-03-13 **Luca Guidi** Render partial from a layout
|
|
66
|
-
|
|
67
|
-
dc4a74f 2014-03-12 **Luca Guidi** Support for Tilt 2.0
|
|
68
|
-
|
|
69
|
-
728fe70 2014-02-20 **Luca Guidi** Added Lotus::View#locals
|
|
70
|
-
|
|
71
|
-
11c7e5a 2013-08-08 **Luca Guidi** Don't use global class vars.
|
|
72
|
-
|
|
73
|
-
570a20c 2013-08-07 **Luca Guidi** Scope templates discovery to registered engines
|
|
74
|
-
|
|
75
|
-
4b45b11 2013-08-06 **Luca Guidi** Added support for layouts.
|
|
76
|
-
|
|
77
|
-
96a2c66 2013-08-02 **Luca Guidi** Allow templates to be rendered from templates.
|
|
78
|
-
|
|
79
|
-
ba5acdc 2013-08-01 **Luca Guidi** Allow partials to be rendered from templates.
|
|
80
|
-
|
|
81
|
-
04474d4 2013-08-01 **Luca Guidi** Render template in the Lotus::View::Rendering::Scope context
|
|
82
|
-
|
|
83
|
-
d108767 2013-08-01 **Luca Guidi** Freeze at subclasses level too
|
|
84
|
-
|
|
85
|
-
04a3093 2013-08-01 **Luca Guidi** Let views to specify relative template filename
|
|
86
|
-
|
|
87
|
-
e7c832d 2013-08-01 **Luca Guidi** Lotus::View::Rendering::Template => Lotus::View::Template
|
|
88
|
-
|
|
89
|
-
f603ea9 2013-08-01 **Luca Guidi** Rework
|
|
90
|
-
|
|
91
|
-
5df49f1 2013-07-23 **Luca Guidi** Removed unnecessary indirection
|
|
92
|
-
|
|
93
|
-
683741c 2013-07-22 **Luca Guidi** Views can now transparently inheriths variables from locals, in order to reuse them.
|
|
94
|
-
|
|
95
|
-
3a31f63 2013-07-19 **Luca Guidi** Removed templates as class variable for views: introduced a registry for runtime resolution
|
|
96
|
-
|
|
97
|
-
f27e19f 2013-07-18 **Luca Guidi** WIP rendering resolver
|
|
98
|
-
|
|
99
|
-
05e1d8c 2013-07-18 **Luca Guidi** Allow views inheritance.
|
|
100
|
-
|
|
101
|
-
8236523 2013-07-18 **Luca Guidi** Refactoring: Engine is not relevant, let Tilt to deal with it. View has multiple templates. Intoduced DSL for format. Introduced resolver for runtime rendering. Dependency injection. :tophat:
|
|
102
|
-
|
|
103
|
-
f7f3d25 2013-07-17 **Luca Guidi** Extracted Lotus::View::Template::Finder
|
|
104
|
-
|
|
105
|
-
11d3c47 2013-07-15 **Luca Guidi** Initial mess
|
|
1
|
+
# Lotus::View
|
|
2
|
+
View layer for Lotus
|
|
3
|
+
|
|
4
|
+
## v0.3.0 - 2014-12-23
|
|
5
|
+
### Added
|
|
6
|
+
- [Trung Lê] When duplicate the framework, also duplicate `Presenter`
|
|
7
|
+
- [Benny Klotz] Introduced `Scope#class`, `#inspect`, `LayoutScope#class` and `#inspect`
|
|
8
|
+
- [Alfonso Uceda Pompa & Trung Lê] Introduced `Configuration#prepare`
|
|
9
|
+
- [Luca Guidi] Implemented "respond to" logic for `Lotus::View::Scope` (`respond_to?` and `respond_to_missing?`)
|
|
10
|
+
- [Luca Guidi] Implemented "respond to" logic for `Lotus::Layout` (`respond_to?` and `respond_to_missing?`)
|
|
11
|
+
- [Jeremy Stephens] Allow view concrete methods that accept a block to be invoked from templates
|
|
12
|
+
- [Peter Suschlik] Implemented "respond to" logic for `Lotus::Presenter` (`respond_to?` and `respond_to_missing?`)
|
|
13
|
+
- [Luca Guidi] Official support for Ruby 2.2
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- [Alfonso Uceda Pompa] Raise an exception when a layout doesn't have an associated template
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- [Luca Guidi] Ensure that concrete methods in layouts are available in templates
|
|
20
|
+
- [Luca Guidi] Ensure to associate the right layout to a view in case fo duplicated framework
|
|
21
|
+
- [Luca Guidi] Safe override of Ruby's top level methods in Scope. (Eg. use `select` from a view, not from `::Kernel`)
|
|
22
|
+
|
|
23
|
+
## v0.2.0 - 2014-06-23
|
|
24
|
+
### Added
|
|
25
|
+
- [Luca Guidi] Introduced `Configuration#duplicate`
|
|
26
|
+
- [Luca Guidi] Introduced `Configuration#layout` to define the layout that all the views will use
|
|
27
|
+
- [Luca Guidi] Introduced `Configuration#load_paths` to define several sources where to lookup for templates
|
|
28
|
+
- [Luca Guidi] Introduced `Configuration#root` to define the root path where to find templates
|
|
29
|
+
- [Luca Guidi] Introduced `Lotus::View::Configuration`
|
|
30
|
+
- [Grant Ammons] Allow view concrete methods with arity > 0 to be invoked from templates
|
|
31
|
+
- [Luca Guidi] Official support for Ruby 2.1
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- [Luca Guidi] `Rendering::TemplatesFinder` now look recursively for templates, starting from the root.
|
|
35
|
+
- [Luca Guidi] Removed `View.layout=`
|
|
36
|
+
- [Luca Guidi] Removed `View.root=`
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- [Luca Guidi] Ensure outermost locals to not shadow innermost inside templates/partials
|
|
40
|
+
|
|
41
|
+
## v0.1.0 - 2014-03-23
|
|
42
|
+
### Added
|
|
43
|
+
- [Luca Guidi] Allow custom rendering policy via `Action#render` override. This bypasses the template lookup and rendering.
|
|
44
|
+
- [Luca Guidi] Introduced `Lotus::Presenter`
|
|
45
|
+
- [Luca Guidi] Introduced templates rendering from templates and layouts
|
|
46
|
+
- [Luca Guidi] Introduced partials rendering from templates and layouts
|
|
47
|
+
- [Luca Guidi] Introduced layouts support
|
|
48
|
+
- [Luca Guidi] Introduced `Lotus::View.load!` as entry point to load views and templates
|
|
49
|
+
- [Luca Guidi] Allow to setup template name via `View.template`
|
|
50
|
+
- [Luca Guidi] Rendering context also considers locals passed to the constructor
|
|
51
|
+
- [Luca Guidi] Introduced `View.format` as DSL to declare which format to handle
|
|
52
|
+
- [Luca Guidi] Introduced view subclasses as way to handle different formats (mime types)
|
|
53
|
+
- [Luca Guidi] Introduced multiple templates per each View
|
|
54
|
+
- [Luca Guidi] Implemented basic rendering with templates
|
|
55
|
+
- [Luca Guidi] Official support for Ruby 2.0
|
data/README.md
CHANGED
|
@@ -6,13 +6,13 @@ It's based on a **separation between views and templates**.
|
|
|
6
6
|
|
|
7
7
|
A _view_ is an object that encapsulates the presentation logic of a page.
|
|
8
8
|
A _template_ is a file that defines the semantic and visual elements of a page.
|
|
9
|
-
In order to show a result to
|
|
9
|
+
In order to show a result to a user, a template must be _rendered_ by a view.
|
|
10
10
|
|
|
11
11
|
Keeping things separated helps to declutter templates and models from presentation logic.
|
|
12
12
|
Also, since views are objects, they are easily testable.
|
|
13
13
|
If you ever used [Mustache](http://mustache.github.io/), you are already aware of the advantages.
|
|
14
14
|
|
|
15
|
-
Like all the other Lotus
|
|
15
|
+
Like all the other Lotus components, it can be used as a standalone framework or within a full Lotus application.
|
|
16
16
|
|
|
17
17
|
## Status
|
|
18
18
|
|
|
@@ -40,7 +40,9 @@ __Lotus::View__ supports Ruby (MRI) 2+
|
|
|
40
40
|
|
|
41
41
|
Add this line to your application's Gemfile:
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
```ruby
|
|
44
|
+
gem 'lotus-view'
|
|
45
|
+
```
|
|
44
46
|
|
|
45
47
|
And then execute:
|
|
46
48
|
|
|
@@ -56,7 +58,7 @@ Or install it yourself as:
|
|
|
56
58
|
|
|
57
59
|
* Templates are searched under `Lotus::View.configuration.root`, set this value according to your app structure (eg. `"app/templates"`).
|
|
58
60
|
* A view will look for a template with a file name that is composed by its full class name (eg. `"articles/index"`).
|
|
59
|
-
* A template must have two concatenated extensions: one for the format one for the engine (eg. `".html.erb"`).
|
|
61
|
+
* A template must have two concatenated extensions: one for the format and one for the engine (eg. `".html.erb"`).
|
|
60
62
|
* The framework must be loaded before rendering the first time: `Lotus::View.load!`.
|
|
61
63
|
|
|
62
64
|
### Views
|
|
@@ -145,7 +147,7 @@ module Articles
|
|
|
145
147
|
include Lotus::View
|
|
146
148
|
|
|
147
149
|
def authors
|
|
148
|
-
article.map(&:
|
|
150
|
+
article.authors.map(&:full_name).join ', '
|
|
149
151
|
end
|
|
150
152
|
end
|
|
151
153
|
end
|
|
@@ -406,7 +408,7 @@ module Articles
|
|
|
406
408
|
end
|
|
407
409
|
end
|
|
408
410
|
|
|
409
|
-
Articles::
|
|
411
|
+
Articles::Create.template # => "articles/new"
|
|
410
412
|
```
|
|
411
413
|
|
|
412
414
|
### Partials
|
|
@@ -515,7 +517,7 @@ puts presenter.inspect_object # => #<Map:0x007fdeada0b2f0 @locations=["Rome", "B
|
|
|
515
517
|
|
|
516
518
|
### Configuration
|
|
517
519
|
|
|
518
|
-
|
|
520
|
+
__Lotus::View__ can be configured with a DSL that determines its behavior.
|
|
519
521
|
It supports a few options:
|
|
520
522
|
|
|
521
523
|
```ruby
|
|
@@ -533,9 +535,17 @@ Lotus::View.configure do
|
|
|
533
535
|
namespace 'MyApp::Views'
|
|
534
536
|
|
|
535
537
|
# Set the global layout
|
|
536
|
-
# Argument: Symbol,
|
|
538
|
+
# Argument: Symbol, defaults to nil
|
|
537
539
|
#
|
|
538
540
|
layout :application
|
|
541
|
+
|
|
542
|
+
# Set modules that you want to include in all views
|
|
543
|
+
# Argument: Block
|
|
544
|
+
#
|
|
545
|
+
prepare do
|
|
546
|
+
include MyCustomModule
|
|
547
|
+
before { do_something }
|
|
548
|
+
end
|
|
539
549
|
end
|
|
540
550
|
```
|
|
541
551
|
|
|
@@ -562,7 +572,7 @@ Show.root # => #<Pathname:/another/root>
|
|
|
562
572
|
|
|
563
573
|
### Reusability
|
|
564
574
|
|
|
565
|
-
|
|
575
|
+
__Lotus::View__ can be used as a singleton framework as seen in this README.
|
|
566
576
|
The application code includes `Lotus::View` or `Lotus::Layout` directly
|
|
567
577
|
and the configuration is unique per Ruby process.
|
|
568
578
|
|
|
@@ -597,7 +607,7 @@ configuration.
|
|
|
597
607
|
|
|
598
608
|
### Thread safety
|
|
599
609
|
|
|
600
|
-
|
|
610
|
+
__Lotus::View__ is thread safe during the runtime, but it isn't during the loading process.
|
|
601
611
|
Please load the framework as the last thing before your application starts.
|
|
602
612
|
Also, be sure that your app provides a thread safe context while it's loaded.
|
|
603
613
|
|
data/lib/lotus/layout.rb
CHANGED
data/lib/lotus/presenter.rb
CHANGED
|
@@ -59,6 +59,10 @@ module Lotus
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
protected
|
|
62
|
+
# Override Ruby's method_missing
|
|
63
|
+
#
|
|
64
|
+
# @api private
|
|
65
|
+
# @since 0.1.0
|
|
62
66
|
def method_missing(m, *args, &blk)
|
|
63
67
|
if @object.respond_to?(m)
|
|
64
68
|
@object.__send__ m, *args, &blk
|
|
@@ -66,5 +70,13 @@ module Lotus
|
|
|
66
70
|
super
|
|
67
71
|
end
|
|
68
72
|
end
|
|
73
|
+
|
|
74
|
+
# Override Ruby's respond_to_missing? in order to support proper delegation
|
|
75
|
+
#
|
|
76
|
+
# @api private
|
|
77
|
+
# @since 0.3.0
|
|
78
|
+
def respond_to_missing?(m, include_private = false)
|
|
79
|
+
@object.respond_to?(m, include_private)
|
|
80
|
+
end
|
|
69
81
|
end
|
|
70
82
|
end
|
data/lib/lotus/view.rb
CHANGED
|
@@ -148,8 +148,9 @@ module Lotus
|
|
|
148
148
|
# #
|
|
149
149
|
# # 1. Generate MyApp::View
|
|
150
150
|
# # 2. Generate MyApp::Layout
|
|
151
|
-
# # 3. Generate MyApp::
|
|
152
|
-
# # 4.
|
|
151
|
+
# # 3. Generate MyApp::Presenter
|
|
152
|
+
# # 4. Generate MyApp::Views
|
|
153
|
+
# # 5. Configure MyApp::Views as the default namespace for views
|
|
153
154
|
#
|
|
154
155
|
# module MyApp::Views::Dashboard
|
|
155
156
|
# class Index
|
|
@@ -227,7 +228,10 @@ module Lotus
|
|
|
227
228
|
def self.duplicate(mod, views = 'Views', &blk)
|
|
228
229
|
dupe.tap do |duplicated|
|
|
229
230
|
mod.module_eval %{ module #{ views }; end } if views
|
|
230
|
-
mod.module_eval %{
|
|
231
|
+
mod.module_eval %{
|
|
232
|
+
Layout = Lotus::Layout.dup
|
|
233
|
+
Presenter = Lotus::Presenter.dup
|
|
234
|
+
}
|
|
231
235
|
|
|
232
236
|
duplicated.configure do
|
|
233
237
|
namespace [mod, views].compact.join '::'
|
|
@@ -272,6 +276,8 @@ module Lotus
|
|
|
272
276
|
|
|
273
277
|
self.configuration = conf.duplicate
|
|
274
278
|
end
|
|
279
|
+
|
|
280
|
+
conf.copy!(base)
|
|
275
281
|
end
|
|
276
282
|
|
|
277
283
|
# Load the framework
|
|
@@ -281,13 +287,5 @@ module Lotus
|
|
|
281
287
|
def self.load!
|
|
282
288
|
configuration.load!
|
|
283
289
|
end
|
|
284
|
-
|
|
285
|
-
# Unload the framework
|
|
286
|
-
#
|
|
287
|
-
# @since 0.1.0
|
|
288
|
-
# @api private
|
|
289
|
-
def self.unload!
|
|
290
|
-
configuration.unload!
|
|
291
|
-
end
|
|
292
290
|
end
|
|
293
291
|
end
|
|
@@ -32,6 +32,7 @@ module Lotus
|
|
|
32
32
|
attr_reader :load_paths
|
|
33
33
|
attr_reader :views
|
|
34
34
|
attr_reader :layouts
|
|
35
|
+
attr_reader :modules
|
|
35
36
|
|
|
36
37
|
# Return the original configuration of the framework instance associated
|
|
37
38
|
# with the given class.
|
|
@@ -83,7 +84,7 @@ module Lotus
|
|
|
83
84
|
def self.for(base)
|
|
84
85
|
# TODO this implementation is similar to Lotus::Controller::Configuration consider to extract it into Lotus::Utils
|
|
85
86
|
namespace = Utils::String.new(base).namespace
|
|
86
|
-
framework = Utils::Class.
|
|
87
|
+
framework = Utils::Class.load_from_pattern!("(#{namespace}|Lotus)::View")
|
|
87
88
|
framework.configuration
|
|
88
89
|
end
|
|
89
90
|
|
|
@@ -229,10 +230,96 @@ module Lotus
|
|
|
229
230
|
#
|
|
230
231
|
# MyApp::View.configuration.layout # => MyApp::ApplicationLayout
|
|
231
232
|
def layout(value = nil)
|
|
232
|
-
if value
|
|
233
|
+
if value.nil?
|
|
234
|
+
Rendering::LayoutFinder.find(@layout, @namespace)
|
|
235
|
+
else
|
|
233
236
|
@layout = value
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Prepare the views.
|
|
241
|
+
#
|
|
242
|
+
# The given block will be yielded when `Lotus::View` will be included by
|
|
243
|
+
# a view.
|
|
244
|
+
#
|
|
245
|
+
# This method can be called multiple times.
|
|
246
|
+
#
|
|
247
|
+
# @param blk [Proc] the code block
|
|
248
|
+
#
|
|
249
|
+
# @return [void]
|
|
250
|
+
#
|
|
251
|
+
# @raise [ArgumentError] if called without passing a block
|
|
252
|
+
#
|
|
253
|
+
# @since 0.3.0
|
|
254
|
+
#
|
|
255
|
+
# @see Lotus::View.configure
|
|
256
|
+
# @see Lotus::View.duplicate
|
|
257
|
+
#
|
|
258
|
+
# @example Including shared utilities
|
|
259
|
+
# require 'lotus/view'
|
|
260
|
+
#
|
|
261
|
+
# module UrlHelpers
|
|
262
|
+
# def comments_path
|
|
263
|
+
# '/'
|
|
264
|
+
# end
|
|
265
|
+
# end
|
|
266
|
+
#
|
|
267
|
+
# Lotus::View.configure do
|
|
268
|
+
# prepare do
|
|
269
|
+
# include UrlHelpers
|
|
270
|
+
# end
|
|
271
|
+
# end
|
|
272
|
+
#
|
|
273
|
+
# Lotus::View.load!
|
|
274
|
+
#
|
|
275
|
+
# module Comments
|
|
276
|
+
# class New
|
|
277
|
+
# # The following include will cause UrlHelpers to be included too.
|
|
278
|
+
# # This makes `comments_path` available in the view context
|
|
279
|
+
# include Lotus::View
|
|
280
|
+
#
|
|
281
|
+
# def form
|
|
282
|
+
# %(<form action="#{ comments_path }" method="POST"></form>)
|
|
283
|
+
# end
|
|
284
|
+
# end
|
|
285
|
+
# end
|
|
286
|
+
#
|
|
287
|
+
# @example Preparing multiple times
|
|
288
|
+
# require 'lotus/view'
|
|
289
|
+
#
|
|
290
|
+
# Lotus::View.configure do
|
|
291
|
+
# prepare do
|
|
292
|
+
# include UrlHelpers
|
|
293
|
+
# end
|
|
294
|
+
#
|
|
295
|
+
# prepare do
|
|
296
|
+
# format :json
|
|
297
|
+
# end
|
|
298
|
+
# end
|
|
299
|
+
#
|
|
300
|
+
# Lotus::View.configure do
|
|
301
|
+
# prepare do
|
|
302
|
+
# include FormattingHelpers
|
|
303
|
+
# end
|
|
304
|
+
# end
|
|
305
|
+
#
|
|
306
|
+
# Lotus::View.load!
|
|
307
|
+
#
|
|
308
|
+
# module Articles
|
|
309
|
+
# class Index
|
|
310
|
+
# # The following include will cause the inclusion of:
|
|
311
|
+
# # * UrlHelpers
|
|
312
|
+
# # * FormattingHelpers
|
|
313
|
+
# #
|
|
314
|
+
# # It also sets the view to render only JSON
|
|
315
|
+
# include Lotus::View
|
|
316
|
+
# end
|
|
317
|
+
# end
|
|
318
|
+
def prepare(&blk)
|
|
319
|
+
if block_given?
|
|
320
|
+
@modules.push(blk)
|
|
234
321
|
else
|
|
235
|
-
|
|
322
|
+
raise ArgumentError.new('Please provide a block')
|
|
236
323
|
end
|
|
237
324
|
end
|
|
238
325
|
|
|
@@ -264,6 +351,7 @@ module Lotus
|
|
|
264
351
|
c.root = root
|
|
265
352
|
c.layout = @layout # lazy loading of the class
|
|
266
353
|
c.load_paths = load_paths.dup
|
|
354
|
+
c.modules = modules.dup
|
|
267
355
|
end
|
|
268
356
|
end
|
|
269
357
|
|
|
@@ -272,8 +360,9 @@ module Lotus
|
|
|
272
360
|
# @since 0.2.0
|
|
273
361
|
# @api private
|
|
274
362
|
def load!
|
|
275
|
-
views.each {|v| v.__send__(:load!) }
|
|
276
|
-
layouts.each {|l| l.__send__(:load!) }
|
|
363
|
+
views.each { |v| v.__send__(:load!) }
|
|
364
|
+
layouts.each { |l| l.__send__(:load!) }
|
|
365
|
+
freeze
|
|
277
366
|
end
|
|
278
367
|
|
|
279
368
|
# Reset all the values to the defaults
|
|
@@ -287,12 +376,31 @@ module Lotus
|
|
|
287
376
|
@layouts = Set.new
|
|
288
377
|
@load_paths = Utils::LoadPaths.new(root)
|
|
289
378
|
@layout = nil
|
|
379
|
+
@modules = []
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Copy the configuration for the given action
|
|
383
|
+
#
|
|
384
|
+
# @param base [Class] the target action
|
|
385
|
+
#
|
|
386
|
+
# @return void
|
|
387
|
+
#
|
|
388
|
+
# @since 0.3.0
|
|
389
|
+
# @api private
|
|
390
|
+
def copy!(base)
|
|
391
|
+
modules.each do |mod|
|
|
392
|
+
base.class_eval(&mod)
|
|
393
|
+
end
|
|
290
394
|
end
|
|
291
395
|
|
|
292
396
|
alias_method :unload!, :reset!
|
|
293
397
|
|
|
294
398
|
protected
|
|
295
|
-
attr_writer :namespace
|
|
399
|
+
attr_writer :namespace
|
|
400
|
+
attr_writer :root
|
|
401
|
+
attr_writer :load_paths
|
|
402
|
+
attr_writer :layout
|
|
403
|
+
attr_writer :modules
|
|
296
404
|
end
|
|
297
405
|
end
|
|
298
406
|
end
|
data/lib/lotus/view/dsl.rb
CHANGED
|
@@ -43,10 +43,10 @@ module Lotus
|
|
|
43
43
|
# Lotus::View.configuration.root # => 'app/templates'
|
|
44
44
|
# Articles::Show.root # => 'path/to/articles/templates'
|
|
45
45
|
def root(value = nil)
|
|
46
|
-
if value
|
|
47
|
-
configuration.root(value)
|
|
48
|
-
else
|
|
46
|
+
if value.nil?
|
|
49
47
|
configuration.root
|
|
48
|
+
else
|
|
49
|
+
configuration.root(value)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -75,10 +75,10 @@ module Lotus
|
|
|
75
75
|
# Articles::Show.format # => nil
|
|
76
76
|
# Articles::JsonShow.format # => :json
|
|
77
77
|
def format(value = nil)
|
|
78
|
-
if value
|
|
79
|
-
@format = value
|
|
80
|
-
else
|
|
78
|
+
if value.nil?
|
|
81
79
|
@format
|
|
80
|
+
else
|
|
81
|
+
@format = value
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -204,10 +204,10 @@ module Lotus
|
|
|
204
204
|
# Bookshelf::Web::Views::Books::Index.template # => 'books/index'
|
|
205
205
|
# Bookshelf::Api::Views::Books::Index.template # => 'books/index'
|
|
206
206
|
def template(value = nil)
|
|
207
|
-
if value
|
|
208
|
-
@@template = value
|
|
209
|
-
else
|
|
207
|
+
if value.nil?
|
|
210
208
|
@@template ||= Rendering::TemplateName.new(name, configuration.namespace).to_s
|
|
209
|
+
else
|
|
210
|
+
@@template = value
|
|
211
211
|
end
|
|
212
212
|
end
|
|
213
213
|
|
|
@@ -295,10 +295,10 @@ module Lotus
|
|
|
295
295
|
# Lotus::View.load!
|
|
296
296
|
# Articles::Show.layout # => :articles
|
|
297
297
|
def layout(value = nil)
|
|
298
|
-
if value
|
|
299
|
-
@layout
|
|
298
|
+
if value.nil?
|
|
299
|
+
@_layout ||= Rendering::LayoutFinder.find(@layout || configuration.layout, configuration.namespace)
|
|
300
300
|
else
|
|
301
|
-
@layout
|
|
301
|
+
@layout = value
|
|
302
302
|
end
|
|
303
303
|
end
|
|
304
304
|
|
|
@@ -317,8 +317,8 @@ module Lotus
|
|
|
317
317
|
v.root.freeze
|
|
318
318
|
v.format.freeze
|
|
319
319
|
v.template.freeze
|
|
320
|
-
v.layout(Rendering::LayoutFinder.new(v).find)
|
|
321
320
|
v.layout#.freeze
|
|
321
|
+
v.configuration.freeze
|
|
322
322
|
end
|
|
323
323
|
end
|
|
324
324
|
end
|
|
@@ -66,7 +66,7 @@ module Lotus
|
|
|
66
66
|
when Symbol, String
|
|
67
67
|
# TODO Move this low level logic into a Lotus::Utils solution
|
|
68
68
|
class_name = "#{ Utils::String.new(layout).classify }#{ SUFFIX }"
|
|
69
|
-
namespace = Utils::Class.
|
|
69
|
+
namespace = Utils::Class.load_from_pattern!(namespace)
|
|
70
70
|
namespace.const_get(class_name)
|
|
71
71
|
when Class
|
|
72
72
|
layout
|
|
@@ -4,6 +4,16 @@ require 'lotus/view/rendering/templates_finder'
|
|
|
4
4
|
module Lotus
|
|
5
5
|
module View
|
|
6
6
|
module Rendering
|
|
7
|
+
# Missing template layout error
|
|
8
|
+
#
|
|
9
|
+
# This is raised at the runtime when Lotus::Layout cannot find it's template.
|
|
10
|
+
#
|
|
11
|
+
# @since 0.3.0
|
|
12
|
+
class MissingTemplateLayoutError < ::StandardError
|
|
13
|
+
def initialize(template)
|
|
14
|
+
super("Can't find layout template '#{ template }'")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
7
17
|
# Holds the references of all the registered layouts.
|
|
8
18
|
# As now the registry is unique at the level of the framework.
|
|
9
19
|
#
|
|
@@ -48,6 +58,7 @@ module Lotus
|
|
|
48
58
|
templates.each do |template|
|
|
49
59
|
merge! template.format => template
|
|
50
60
|
end
|
|
61
|
+
self.any? or raise MissingTemplateLayoutError.new(@view)
|
|
51
62
|
end
|
|
52
63
|
|
|
53
64
|
def templates
|
|
@@ -4,7 +4,7 @@ module Lotus
|
|
|
4
4
|
# Scope for layout rendering
|
|
5
5
|
#
|
|
6
6
|
# @since 0.1.0
|
|
7
|
-
class LayoutScope
|
|
7
|
+
class LayoutScope < BasicObject
|
|
8
8
|
# Initialize the scope
|
|
9
9
|
#
|
|
10
10
|
# @param layout [Lotus::Layout] the layout to render
|
|
@@ -17,6 +17,27 @@ module Lotus
|
|
|
17
17
|
@layout, @scope = layout, scope
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Returns the classname as string
|
|
21
|
+
#
|
|
22
|
+
# @return classname
|
|
23
|
+
#
|
|
24
|
+
# @since 0.3.0
|
|
25
|
+
def class
|
|
26
|
+
(class << self; self end).superclass
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns an inspect String
|
|
30
|
+
#
|
|
31
|
+
# @return [String] inspect String (contains classname, objectid in hex, available ivars)
|
|
32
|
+
#
|
|
33
|
+
# @since 0.3.0
|
|
34
|
+
def inspect
|
|
35
|
+
base = "#<#{ self.class }:#{'%x' % (self.object_id << 1)}"
|
|
36
|
+
base << " @layout=\"#{@layout}\"" if @layout
|
|
37
|
+
base << " @scope=\"#{@scope}\"" if @scope
|
|
38
|
+
base << ">"
|
|
39
|
+
end
|
|
40
|
+
|
|
20
41
|
# Render a partial or a template within a layout template.
|
|
21
42
|
#
|
|
22
43
|
# @param options [Hash]
|
|
@@ -90,6 +111,30 @@ module Lotus
|
|
|
90
111
|
@locals || @scope.locals
|
|
91
112
|
end
|
|
92
113
|
|
|
114
|
+
# Implements "respond to" logic
|
|
115
|
+
#
|
|
116
|
+
# @return [TrueClass,FalseClass]
|
|
117
|
+
#
|
|
118
|
+
# @since 0.3.0
|
|
119
|
+
#
|
|
120
|
+
# @see http://ruby-doc.org/core/Object.html#method-i-respond_to-3F
|
|
121
|
+
def respond_to?(m, include_all = false)
|
|
122
|
+
respond_to_missing?(m, include_all)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Implements "respond to" logic
|
|
126
|
+
#
|
|
127
|
+
# @return [TrueClass,FalseClass]
|
|
128
|
+
#
|
|
129
|
+
# @since 0.3.0
|
|
130
|
+
# @api private
|
|
131
|
+
#
|
|
132
|
+
# @see http://ruby-doc.org/core/Object.html#method-i-respond_to_missing-3F
|
|
133
|
+
def respond_to_missing?(m, include_all)
|
|
134
|
+
@layout.respond_to?(m, include_all) ||
|
|
135
|
+
@scope.respond_to?(m, include_all)
|
|
136
|
+
end
|
|
137
|
+
|
|
93
138
|
protected
|
|
94
139
|
# Forward all the missing methods to the view scope or to the layout.
|
|
95
140
|
#
|
|
@@ -108,11 +153,11 @@ module Lotus
|
|
|
108
153
|
#
|
|
109
154
|
# # `article` will be looked up in the view scope first.
|
|
110
155
|
# # If not found, it will be searched within the layout.
|
|
111
|
-
def method_missing(m)
|
|
156
|
+
def method_missing(m, *args, &blk)
|
|
112
157
|
begin
|
|
113
|
-
@scope.__send__
|
|
158
|
+
@scope.__send__(m, *args, &blk)
|
|
114
159
|
rescue
|
|
115
|
-
@layout.__send__
|
|
160
|
+
@layout.__send__(m, *args, &blk)
|
|
116
161
|
end
|
|
117
162
|
end
|
|
118
163
|
|
|
@@ -129,7 +174,7 @@ module Lotus
|
|
|
129
174
|
options.dup.tap do |opts|
|
|
130
175
|
opts.merge!(format: format)
|
|
131
176
|
opts[:locals] = locals
|
|
132
|
-
opts[:locals].merge!(options.fetch(:locals){ Hash
|
|
177
|
+
opts[:locals].merge!(options.fetch(:locals){ ::Hash.new })
|
|
133
178
|
end
|
|
134
179
|
end
|
|
135
180
|
end
|
|
@@ -63,6 +63,10 @@ module Lotus
|
|
|
63
63
|
class NullTemplate
|
|
64
64
|
# Render the layout template
|
|
65
65
|
#
|
|
66
|
+
# @param scope [Lotus::View::Scope] the rendering scope
|
|
67
|
+
# @param locals [Hash] a set of objects available during the rendering
|
|
68
|
+
# @yield [Proc] yields the given block
|
|
69
|
+
#
|
|
66
70
|
# @return [String] the output of the rendering process
|
|
67
71
|
#
|
|
68
72
|
# @api private
|
|
@@ -70,8 +74,8 @@ module Lotus
|
|
|
70
74
|
#
|
|
71
75
|
# @see Lotus::Layout#render
|
|
72
76
|
# @see Lotus::View::Rendering#render
|
|
73
|
-
def render(scope, locals = {}
|
|
74
|
-
|
|
77
|
+
def render(scope, locals = {})
|
|
78
|
+
yield
|
|
75
79
|
end
|
|
76
80
|
end
|
|
77
81
|
end
|
|
@@ -23,6 +23,18 @@ module Lotus
|
|
|
23
23
|
@view, @locals = view, locals
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# Returns an inspect String
|
|
27
|
+
#
|
|
28
|
+
# @return [String] inspect String (contains classname, objectid in hex, available ivars)
|
|
29
|
+
#
|
|
30
|
+
# @since 0.3.0
|
|
31
|
+
def inspect
|
|
32
|
+
base = "#<#{ self.class }: #{'%x' % (self.object_id << 1)}"
|
|
33
|
+
base << " @view=\"#{@view}\"" if @view
|
|
34
|
+
base << " @locals=\"#{@locals}\"" if @locals
|
|
35
|
+
base << ">"
|
|
36
|
+
end
|
|
37
|
+
|
|
26
38
|
# Returns the requested format.
|
|
27
39
|
#
|
|
28
40
|
# @return [Symbol] the requested format (eg. :html, :json, :xml, etc..)
|
|
@@ -32,10 +44,23 @@ module Lotus
|
|
|
32
44
|
locals[:format]
|
|
33
45
|
end
|
|
34
46
|
|
|
47
|
+
# Implements "respond to" logic
|
|
48
|
+
#
|
|
49
|
+
# @return [TrueClass,FalseClass]
|
|
50
|
+
#
|
|
51
|
+
# @since 0.3.0
|
|
52
|
+
# @api private
|
|
53
|
+
#
|
|
54
|
+
# @see http://ruby-doc.org/core/Object.html#method-i-respond_to_missing-3F
|
|
55
|
+
def respond_to_missing?(m, include_all)
|
|
56
|
+
@view.respond_to?(m) ||
|
|
57
|
+
@locals.key?(m)
|
|
58
|
+
end
|
|
59
|
+
|
|
35
60
|
protected
|
|
36
|
-
def method_missing(m, *args)
|
|
61
|
+
def method_missing(m, *args, &block)
|
|
37
62
|
if @view.respond_to?(m)
|
|
38
|
-
@view.__send__ m, *args
|
|
63
|
+
@view.__send__ m, *args, &block
|
|
39
64
|
elsif @locals.key?(m)
|
|
40
65
|
@locals[m]
|
|
41
66
|
else
|
data/lib/lotus/view/template.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Lotus
|
|
|
12
12
|
|
|
13
13
|
# Returns the format that the template handles.
|
|
14
14
|
#
|
|
15
|
-
# @return [
|
|
15
|
+
# @return [Symbol] the format name
|
|
16
16
|
#
|
|
17
17
|
# @since 0.1.0
|
|
18
18
|
#
|
|
@@ -20,11 +20,9 @@ module Lotus
|
|
|
20
20
|
# require 'lotus/view'
|
|
21
21
|
#
|
|
22
22
|
# template = Lotus::View::Template.new('index.html.erb')
|
|
23
|
-
# template.format # =>
|
|
23
|
+
# template.format # => :html
|
|
24
24
|
def format
|
|
25
|
-
@_template.basename.match(
|
|
26
|
-
gsub('.', ''). # TODO shame on me, this should be part of the regex above
|
|
27
|
-
to_sym
|
|
25
|
+
@_template.basename.match(/\.([^.]+)/).captures.first.to_sym
|
|
28
26
|
end
|
|
29
27
|
|
|
30
28
|
# Render the template within the context of the given scope.
|
data/lib/lotus/view/version.rb
CHANGED
data/lotus-view.gemspec
CHANGED
|
@@ -17,9 +17,10 @@ Gem::Specification.new do |spec|
|
|
|
17
17
|
spec.executables = []
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
|
19
19
|
spec.require_paths = ['lib']
|
|
20
|
+
spec.required_ruby_version = '>= 2.0.0'
|
|
20
21
|
|
|
21
22
|
spec.add_runtime_dependency 'tilt', '~> 2.0', '>= 2.0.1'
|
|
22
|
-
spec.add_runtime_dependency 'lotus-utils', '~> 0.2'
|
|
23
|
+
spec.add_runtime_dependency 'lotus-utils', '~> 0.3', '>= 0.3.2'
|
|
23
24
|
|
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
|
25
26
|
spec.add_development_dependency 'minitest', '~> 5'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lotus-view
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luca Guidi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-12-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: tilt
|
|
@@ -36,14 +36,20 @@ dependencies:
|
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
39
|
+
version: '0.3'
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: 0.3.2
|
|
40
43
|
type: :runtime
|
|
41
44
|
prerelease: false
|
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
46
|
requirements:
|
|
44
47
|
- - "~>"
|
|
45
48
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0.
|
|
49
|
+
version: '0.3'
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 0.3.2
|
|
47
53
|
- !ruby/object:Gem::Dependency
|
|
48
54
|
name: bundler
|
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -133,7 +139,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
133
139
|
requirements:
|
|
134
140
|
- - ">="
|
|
135
141
|
- !ruby/object:Gem::Version
|
|
136
|
-
version:
|
|
142
|
+
version: 2.0.0
|
|
137
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
144
|
requirements:
|
|
139
145
|
- - ">="
|