lotus-view 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6054b04ffdb4d4b0bc17f0de1b4d239a45fa1062
4
- data.tar.gz: 3fdec77bf94ab52bf27916b979661619cc053b71
3
+ metadata.gz: e8fa1effeef34385f8e2500ab74842e8d196f9bf
4
+ data.tar.gz: 203e83425ed18d487d19cc825443fed66c53c86e
5
5
  SHA512:
6
- metadata.gz: ebf1e5d0839acda038d449cb18b9c9b12f49d7de7ec8c6460f7b4c7cef84cf685364e5d3e6ccd0882536024cc47e91f18a05f7aa6afb0cdff08587761d5f2b2f
7
- data.tar.gz: 73eecc96f67474d79ca0f21f4440d10aa0a510d3172966fe3939d811c1d2d623170328140097ed81f0b17f53bc3537baff7d8f9d5c8a6955cb95e8c0d0083a9c
6
+ metadata.gz: 6b1317306b81d7579d3a3894ba2f22584f69f28039a0161a706c3d3cb7f89cc5a2b591c09e7c57b684d53870a9b96010a8db882717cd8a6ce0d9574f59be4b81
7
+ data.tar.gz: bee5b8b82b89c9e561bc89bffb53ba3a01028393934fb8bfa350e7fb13c240a305061a3c9b8196abadb710c13d3654b932a4986a609b06280c49c7abc24c6af0
data/CHANGELOG.md CHANGED
@@ -1,105 +1,55 @@
1
- ## v0.2.0
2
- ### Jun 23, 2014
3
-
4
- f053805 2014-06-20 **Luca Guidi** [breaking] Make Rendering::TemplatesFinder to look recursively for templates, starting from the root
5
-
6
- 5a5ed1b 2014-06-18 **Luca Guidi** Depend on lotus-utils ~> 0.2
7
-
8
- d7858df 2014-06-18 **Luca Guidi** Ensure to handle correctly the namespace for views, when it's configured as nil
9
-
10
- 8f9e876 2014-06-18 **Luca Guidi** Renamed Lotus::View methods: .duplicate => .dupe, .generate => .duplicate
11
-
12
- 199c1d6 2014-06-11 **Luca Guidi** Introducing Lotus::View.generate as shortcut for .duplicate and .configure
13
-
14
- d3e65d9 2014-06-11 **Luca Guidi** Ensure lazy loading and correct namespace of the layout class when using configuration's "layout" DSL
15
-
16
- 850c9b9 2014-06-11 **Luca Guidi** Specify different scenario for template name in a standalone application
17
-
18
- 6199419 2014-06-06 **Luca Guidi** Ensure to return the correct template name for namespaced views
19
-
20
- 71d502f 2014-06-06 **Luca Guidi** Ensure independent configurations between the framework, the views and its children. Lotus::View::Dsl.root now internally uses the configuration.
21
-
22
- dd0ec4c 2014-06-06 **Luca Guidi** Lazily load layout for Configuration. This mechanism solves eventual race conditions between the loading of the framework and the application.
23
-
24
- d2e0775 2014-06-05 **Luca Guidi** [breaking] Lotus::View can be safely duplicated. Moved views and layout registries into Configuration. Configuration is now able to duplicated and (un)load itself. Layouts can be looked up in a given Ruby namespace.
25
-
26
- a619bd2 2014-06-05 **Luca Guidi** Implemented Lotus::View::Configuration#views and #layouts
27
-
28
- e4e892e 2014-06-04 **Luca Guidi** [breaking] Removed Lotus::View's class accessor for root, in favor of the API of Lotus::View::Configuration
29
-
30
- 1aa68c6 2014-06-04 **Luca Guidi** [breaking] Removed Lotus::View's class accessor for layout, in favor of the API of Lotus::View::Configuration
31
-
32
- da9bee4 2014-06-04 **Luca Guidi** Implemented Lotus::View::Configuration#layout
33
-
34
- da31e3e 2014-06-04 **Luca Guidi** Implemented Lotus::View::Configuration#load_paths
35
-
36
- 1471cdd 2014-06-03 **Luca Guidi** Introduced Lotus::View::Configuration with a bare minimum behavior
37
-
38
- 425c79e 2014-05-21 **Grant Ammons** Support arguments for methods inside templates
39
-
40
- d4d407b 2014-05-10 **Luca Guidi** Support Ruby 2.1.2
41
-
42
- 593f1a5 2014-04-07 **Luca Guidi** Ensure outermost locals to not shadow innermost inside templates/partials. Closes #3
43
-
44
- ## v0.1.0
45
- ### Mar 23, 2014
46
-
47
- af70191 2014-03-22 **Luca Guidi** Introduced Lotus::View::MissingFormatError in order to force a rendering context to specify the requested format (mime type)
48
-
49
- 320f322 2014-03-22 **Luca Guidi** Changed signature of Lotus::View.render: it now accepts only a context for the view
50
-
51
- 9d5de63 2014-03-21 **Luca Guidi** Test with other engines than ERb, HAML in this case.
52
-
53
- a5ade35 2014-03-21 **Luca Guidi** Erubis is no longer a dependency.
54
-
55
- 257e342 2014-03-21 **Luca Guidi** Performance: prefer `Hash#fetch(key) { default }`, over `#fetch(key, default)`.
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 an user, a template must be _rendered_ by a view.
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 compontents, it can be used as a standalone framework or within a full Lotus application.
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
- gem 'lotus-view'
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(&:author).join ', '
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::Index.template # => "articles/new"
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
- Lotus::View can be configured with a DSL that determines its behavior.
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, defautls to nil
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
- Lotus::View can be used as a singleton framework as seen in this README.
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
- **Lotus::View**'s is thread safe during the runtime, but it isn't during the loading process.
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
@@ -98,7 +98,8 @@ module Lotus
98
98
  #
99
99
  # @see Lotus::View.load!
100
100
  def load!
101
- # registry.freeze
101
+ registry.freeze
102
+ configuration.freeze
102
103
  end
103
104
  end
104
105
 
@@ -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::Views
152
- # # 4. Configure MyApp::Views as the default namespace for views
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 %{ Layout = Lotus::Layout.dup }
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.load!("(#{namespace}|Lotus)::View")
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
- Rendering::LayoutFinder.find(@layout, @namespace)
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, :root, :load_paths, :layout
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
@@ -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 = value
298
+ if value.nil?
299
+ @_layout ||= Rendering::LayoutFinder.find(@layout || configuration.layout, configuration.namespace)
300
300
  else
301
- @layout ||= configuration.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.load!(namespace)
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__ m
158
+ @scope.__send__(m, *args, &blk)
114
159
  rescue
115
- @layout.__send__ m
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 = {}, &blk)
74
- blk.call
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
@@ -12,7 +12,7 @@ module Lotus
12
12
 
13
13
  # Returns the format that the template handles.
14
14
  #
15
- # @return [String] the format name
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 # => 'html'
23
+ # template.format # => :html
24
24
  def format
25
- @_template.basename.match(/(\.[^.]+)/).to_s.
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.
@@ -3,6 +3,6 @@ module Lotus
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.2.0'.freeze
6
+ VERSION = '0.3.0'.freeze
7
7
  end
8
8
  end
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.2.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-06-23 00:00:00.000000000 Z
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.2'
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.2'
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: '0'
142
+ version: 2.0.0
137
143
  required_rubygems_version: !ruby/object:Gem::Requirement
138
144
  requirements:
139
145
  - - ">="