dry-view 0.1.1 → 0.2.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +15 -11
  3. data/CHANGELOG.md +23 -0
  4. data/Gemfile +6 -5
  5. data/README.md +8 -1
  6. data/benchmarks/templates/{button.erb → button.html.erb} +0 -0
  7. data/benchmarks/view.rb +3 -4
  8. data/bin/console +7 -0
  9. data/dry-view.gemspec +7 -6
  10. data/lib/dry/view/controller.rb +107 -0
  11. data/lib/dry/view/exposure.rb +61 -0
  12. data/lib/dry/view/exposures.rb +50 -0
  13. data/lib/dry/view/path.rb +40 -0
  14. data/lib/dry/view/renderer.rb +20 -28
  15. data/lib/dry/view/scope.rb +55 -0
  16. data/lib/dry/view/version.rb +1 -1
  17. data/lib/dry/view.rb +1 -1
  18. data/spec/fixtures/templates/empty.html.slim +1 -0
  19. data/spec/fixtures/templates/layouts/app.html.slim +1 -1
  20. data/spec/fixtures/templates/layouts/app.txt.erb +1 -1
  21. data/spec/fixtures/templates/parts_with_args/_box.html.slim +3 -0
  22. data/spec/fixtures/templates/parts_with_args.html.slim +3 -0
  23. data/spec/fixtures/templates/users/_tbody.html.slim +1 -1
  24. data/spec/fixtures/templates/users.html.slim +4 -4
  25. data/spec/fixtures/templates/users.txt.erb +0 -2
  26. data/spec/fixtures/templates/users_with_count.html.slim +5 -0
  27. data/spec/fixtures/templates_override/users.html.slim +5 -0
  28. data/spec/integration/exposures_spec.rb +178 -0
  29. data/spec/integration/view_spec.rb +83 -20
  30. data/spec/spec_helper.rb +13 -3
  31. data/spec/unit/controller_spec.rb +36 -0
  32. data/spec/unit/exposure_spec.rb +146 -0
  33. data/spec/unit/exposures_spec.rb +63 -0
  34. data/spec/unit/renderer_spec.rb +2 -1
  35. data/spec/unit/scope_spec.rb +98 -0
  36. metadata +36 -46
  37. data/lib/dry/view/layout.rb +0 -126
  38. data/lib/dry/view/null_part.rb +0 -30
  39. data/lib/dry/view/part.rb +0 -39
  40. data/lib/dry/view/value_part.rb +0 -50
  41. data/spec/unit/layout_spec.rb +0 -55
  42. data/spec/unit/null_part_spec.rb +0 -39
  43. data/spec/unit/value_part_spec.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3b4e09263f41a0b0972c1270fa32e5911ad028b
4
- data.tar.gz: b7787ff1b20f6fae7c4c67461ac7e2c1cf51e498
3
+ metadata.gz: 5cf179c08c3deb29086bc87197420a301595a70f
4
+ data.tar.gz: 1c6eccdfb39502b559748c8c75d4c4b127b16019
5
5
  SHA512:
6
- metadata.gz: d79d4a61109cce4b3885d5c0bba544563ebd8d253465acb33c1022f62a61f369de0c972a2ea6657d1d6fb76841a4e4e5baaea7d5df16864e6f2f0b43e54ae881
7
- data.tar.gz: 84a995bd47ddd4909cc8658bb2af52dc369b96b9c37d4f74add32a8fc21ce682837fbb7226c16aab164c0389197b5d9183b3bc82009ed608c7fb2d6c9002c3dc
6
+ metadata.gz: 390c86f0b801d44bfe8a5958a982da88a52030dbfbf4403380af90c82c1279d3603a0f4376d1b2f349f3e42f36628c3a551b37e3fe8d2d75874b77d1e4d1efb3
7
+ data.tar.gz: cfdc7df2e7d8b63cda8611d203d9ec39da0a31d9237e742a00e861244556b2cfc5854b09a312abb358f77c572d4102b56d707d74ee27a61154fb7d6c44952756
data/.travis.yml CHANGED
@@ -1,25 +1,29 @@
1
1
  language: ruby
2
+ dist: trusty
2
3
  sudo: false
3
4
  cache: bundler
4
5
  bundler_args: --without tools benchmarks
6
+ before_install:
7
+ - gem update --system
8
+ - rvm @global do gem uninstall bundler -a -x
9
+ - rvm @global do gem install bundler -v 1.13.7
5
10
  script:
6
- - bundle exec rake spec
11
+ - bundle exec rake
12
+ after_success:
13
+ # Send coverage report from the job #1 == current MRI release
14
+ - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
7
15
  rvm:
8
- - 2.0
9
- - 2.1
10
- - 2.2
11
- - 2.3.0
12
- - rbx
13
- - jruby-9000
14
- - ruby-head
15
- - jruby-head
16
+ - 2.4.0
17
+ - 2.3.3
18
+ - 2.2.6
19
+ - 2.1.10
20
+ - jruby-9.1.6.0
16
21
  env:
17
22
  global:
18
23
  - JRUBY_OPTS='--dev -J-Xmx1024M'
19
24
  matrix:
20
25
  allow_failures:
21
- - rvm: ruby-head
22
- - rvm: jruby-head
26
+ - rvm: jruby-9.1.6.0
23
27
  notifications:
24
28
  email: false
25
29
  webhooks:
data/CHANGELOG.md CHANGED
@@ -1,7 +1,30 @@
1
+ # 0.2.0 / 2017-01-30
2
+
3
+ This release is a major reorientation for dry-view, and it should allow for more natural, straightforward template authoring.
4
+
5
+ ### Changed
6
+
7
+ - [BREAKING] `Dry::View::Layout` renamed to `Dry::View::Controller`. The "view controller" name better represents this object's job: to (timriley)
8
+ - [BREAKING] `Dry::View::Controller`'s `name` setting is replaced by `template`, which also supports falsey values to disable layout rendering entirely (timriley)
9
+ - [BREAKING] `Dry::View::Controller`'s `formats` setting is replaced by `default_format`, which expects a simple string or symbol. The default value is `:html`. (timriley)
10
+ - [BREAKING] `Dry::View::Controller`'s `root` setting is replaced by `paths`, which can now accept an array of one or more directories. These will be searched for templates in order, with the first match winning (timriley)
11
+ - [BREAKING] `Dry::View::Controller`'s `scope` setting is removed and replaced by `context`, which will be made available to all templates rendered from a view controller (layouts and partials inculded), not just the layout (timriley)
12
+ - [BREAKING] View parts have been replaced by a simple `Scope`. Data passed to the templates can be accessed directly, rather than wrapped up in a view part. (timriley)
13
+ - [BREAKING] With view parts removed, partials can only be rendered by top-level method calls within templates (timriley)
14
+ - Ruby version 2.1.0 is now the earliest supported version (timriley)
15
+
16
+ ### Added
17
+
18
+ - Will render templates using any Tilt-supported engine, based on the template's final file extension (e.g. `hello.html.slim` will use Slim). For thread-safety, be sure to explicitly require any engine gems you intend to use. (timriley)
19
+ - `expose` (and `expose_private`) `Dry::View::Controller` class methods allow you to more easily declare and prepare the data for your template (timriley)
20
+ - Added `Dry::View::Scope`, which is the scope used for rendering templates. This includes the data from the exposures along with the context object (timriley)
21
+
1
22
  # 0.1.1 / 2016-07-07
2
23
 
3
24
  ### Changed
4
25
 
26
+ - Wrap `page` object exposed to layout templates in a part object, so it offers behaviour that is consistent with the part objects that template authors work with on other templates (timriley)
27
+ - Render template content first, before passing that content to the layout. This makes "content_for"-style behaviours possible, where the template stores some data that the layout can then use later (timriley)
5
28
  - Configure default template encoding to be UTF-8, fixing some issues with template rendering on deployed sites (gotar)
6
29
 
7
30
  # 0.1.0 / 2016-03-28
data/Gemfile CHANGED
@@ -2,16 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ group :tools do
6
+ gem 'pry'
7
+ end
8
+
5
9
  group :test do
6
10
  gem 'byebug', platform: :mri
7
11
  gem 'rack', '>= 1.0.0', '<= 2.0.0'
8
12
  gem 'slim'
9
13
 
10
- gem 'codeclimate-test-reporter', platform: :rbx
11
- end
12
-
13
- group :tools do
14
- gem 'pry'
14
+ gem 'simplecov'
15
+ gem 'codeclimate-test-reporter'
15
16
  end
16
17
 
17
18
  group :benchmarks do
data/README.md CHANGED
@@ -12,4 +12,11 @@
12
12
  [![Test Coverage](https://img.shields.io/codeclimate/coverage/github/dry-rb/dry-view.svg)][code_climate]
13
13
  [![API Documentation Coverage](http://inch-ci.org/github/dry-rb/dry-view.svg)][inch]
14
14
 
15
- Data-oriented view rendering system.
15
+
16
+ A simple, standalone view rendering system built around functional view
17
+ controllers and templates. dry-view allows you to model your views as stateless
18
+ transformations, accepting user input and returning your rendered view.
19
+
20
+ ## Links
21
+
22
+ * [Documentation](http://dry-rb.org/gems/dry-view)
data/benchmarks/view.rb CHANGED
@@ -12,14 +12,13 @@ class ActionRender
12
12
  end
13
13
 
14
14
  action_renderer = ActionRender.new
15
- rodakase_renderer = Dry::View::Renderer.new(Pathname(__FILE__).dirname.join('templates'), engine: :erb)
16
-
17
- template = rodakase_renderer.dir.join('button.erb')
15
+ dry_view_renderer = Dry::View::Renderer.new(Pathname(__FILE__).dirname.join('templates'), format: :html)
18
16
 
17
+ template = Pathname(__FILE__).dirname.join('templates').join('button.html.erb')
19
18
  SCOPE = {}
20
19
 
21
20
  Benchmark.ips do |x|
22
21
  x.report('actionview') { action_renderer.button }
23
- x.report('rodakase') { rodakase_renderer.render(template, SCOPE) }
22
+ x.report('dry-view') { dry_view_renderer.render(template, SCOPE) }
24
23
  x.compare!
25
24
  end
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "dry-view"
5
+
6
+ require "pry"
7
+ Pry.start
data/dry-view.gemspec CHANGED
@@ -6,19 +6,21 @@ require 'dry/view/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "dry-view"
8
8
  spec.version = Dry::View::VERSION
9
- spec.authors = ["Piotr Solnica"]
10
- spec.email = ["piotr.solnica@gmail.com"]
11
- spec.summary = "Lightweight web application stack on top of Roda"
9
+ spec.authors = ["Piotr Solnica", "Tim Riley"]
10
+ spec.email = ["piotr.solnica@gmail.com", "tim@icelab.com.au"]
11
+ spec.summary = "Functional view rendering system"
12
12
  spec.description = spec.summary
13
13
  spec.homepage = "https://github.com/dry-rb/dry-view"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
20
  spec.require_paths = ["lib"]
20
21
 
21
- spec.add_runtime_dependency "inflecto", "~> 0"
22
+ spec.required_ruby_version = '>= 2.1.0'
23
+
22
24
  spec.add_runtime_dependency "tilt", "~> 2.0"
23
25
  spec.add_runtime_dependency "dry-configurable", "~> 0.1"
24
26
  spec.add_runtime_dependency "dry-equalizer", "~> 0.2"
@@ -26,5 +28,4 @@ Gem::Specification.new do |spec|
26
28
  spec.add_development_dependency "bundler", "~> 1.7"
27
29
  spec.add_development_dependency "rake", "~> 10.0"
28
30
  spec.add_development_dependency "rspec", "~> 3.1"
29
- spec.add_development_dependency "capybara", "~> 2.5"
30
31
  end
@@ -0,0 +1,107 @@
1
+ require 'dry-configurable'
2
+ require 'dry-equalizer'
3
+
4
+ require 'dry/view/path'
5
+ require 'dry/view/exposures'
6
+ require 'dry/view/renderer'
7
+ require 'dry/view/scope'
8
+
9
+ module Dry
10
+ module View
11
+ class Controller
12
+ DEFAULT_LAYOUTS_DIR = 'layouts'.freeze
13
+ DEFAULT_CONTEXT = Object.new.freeze
14
+ EMPTY_LOCALS = {}.freeze
15
+
16
+ include Dry::Equalizer(:config)
17
+
18
+ extend Dry::Configurable
19
+
20
+ setting :paths
21
+ setting :layout, false
22
+ setting :context, DEFAULT_CONTEXT
23
+ setting :template
24
+ setting :default_format, :html
25
+
26
+ attr_reader :config
27
+ attr_reader :layout_dir
28
+ attr_reader :layout_path
29
+ attr_reader :template_path
30
+ attr_reader :exposures
31
+
32
+ def self.paths
33
+ Array(config.paths).map { |path| Dry::View::Path.new(path) }
34
+ end
35
+
36
+ def self.renderer(format)
37
+ renderers.fetch(format) {
38
+ renderers[format] = Renderer.new(paths, format: format)
39
+ }
40
+ end
41
+
42
+ def self.renderers
43
+ @renderers ||= {}
44
+ end
45
+
46
+ def self.expose(*names, **options, &block)
47
+ if names.length == 1
48
+ exposures.add(names.first, block, **options)
49
+ else
50
+ names.each do |name|
51
+ exposures.add(name, nil, **options)
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.private_expose(*names, &block)
57
+ expose(*names, to_view: false, &block)
58
+ end
59
+
60
+ def self.exposures
61
+ @exposures ||= Exposures.new
62
+ end
63
+
64
+ def initialize
65
+ @config = self.class.config
66
+ @layout_dir = DEFAULT_LAYOUTS_DIR
67
+ @layout_path = "#{layout_dir}/#{config.layout}"
68
+ @template_path = config.template
69
+ @exposures = self.class.exposures.bind(self)
70
+ end
71
+
72
+ def call(format: config.default_format, **input)
73
+ renderer = self.class.renderer(format)
74
+
75
+ template_content = renderer.(template_path, template_scope(renderer, **input))
76
+
77
+ return template_content unless layout?
78
+
79
+ renderer.(layout_path, layout_scope(renderer, **input)) do
80
+ template_content
81
+ end
82
+ end
83
+
84
+ def locals(locals: EMPTY_LOCALS, **input)
85
+ exposures.locals(input).merge(locals)
86
+ end
87
+
88
+ private
89
+
90
+ def layout?
91
+ !!config.layout
92
+ end
93
+
94
+ def layout_scope(renderer, context: config.context, **)
95
+ scope(renderer.chdir(layout_dir), EMPTY_LOCALS, context)
96
+ end
97
+
98
+ def template_scope(renderer, context: config.context, **input)
99
+ scope(renderer.chdir(template_path), locals(**input), context)
100
+ end
101
+
102
+ def scope(renderer, locals, context)
103
+ Scope.new(renderer, locals, context)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,61 @@
1
+ module Dry
2
+ module View
3
+ class Exposure
4
+ SUPPORTED_PARAMETER_TYPES = [:req, :opt].freeze
5
+
6
+ attr_reader :name
7
+ attr_reader :proc
8
+ attr_reader :to_view
9
+
10
+ def initialize(name, proc = nil, to_view: true)
11
+ ensure_proc_parameters(proc) if proc
12
+
13
+ @name = name
14
+ @proc = proc
15
+ @to_view = to_view
16
+ end
17
+
18
+ def bind(obj)
19
+ proc ? self : with_default_proc(obj)
20
+ end
21
+
22
+ def dependencies
23
+ proc.parameters.map(&:last)
24
+ end
25
+
26
+ alias_method :to_view?, :to_view
27
+
28
+ def call(input, locals = {})
29
+ params = dependencies.map.with_index { |name, position|
30
+ if position.zero?
31
+ locals.fetch(name) { input }
32
+ else
33
+ locals.fetch(name)
34
+ end
35
+ }
36
+
37
+ proc.(*params)
38
+ end
39
+
40
+ private
41
+
42
+ def with_default_proc(obj)
43
+ self.class.new(name, build_default_proc(obj), to_view: to_view)
44
+ end
45
+
46
+ def build_default_proc(obj)
47
+ if obj.respond_to?(name, _include_private = true)
48
+ obj.method(name)
49
+ else
50
+ -> input { input.fetch(name) }
51
+ end
52
+ end
53
+
54
+ def ensure_proc_parameters(proc)
55
+ if proc.parameters.any? { |type, _| !SUPPORTED_PARAMETER_TYPES.include?(type) }
56
+ raise ArgumentError, "+proc+ must take positional arugments only"
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,50 @@
1
+ require "tsort"
2
+ require "dry/view/exposure"
3
+
4
+ module Dry
5
+ module View
6
+ class Exposures
7
+ include TSort
8
+
9
+ attr_reader :exposures
10
+
11
+ def initialize(exposures = {})
12
+ @exposures = exposures
13
+ end
14
+
15
+ def [](name)
16
+ exposures[name]
17
+ end
18
+
19
+ def add(name, proc = nil, **options)
20
+ exposures[name] = Exposure.new(name, proc, **options)
21
+ end
22
+
23
+ def bind(obj)
24
+ bound_exposures = Hash[exposures.map { |name, exposure|
25
+ [name, exposure.bind(obj)]
26
+ }]
27
+
28
+ self.class.new(bound_exposures)
29
+ end
30
+
31
+ def locals(input)
32
+ tsort.each_with_object({}) { |name, memo|
33
+ memo[name] = self[name].(input, memo) if exposures.key?(name)
34
+ }.each_with_object({}) { |(name, val), memo|
35
+ memo[name] = val if self[name].to_view?
36
+ }
37
+ end
38
+
39
+ private
40
+
41
+ def tsort_each_node(&block)
42
+ exposures.each_key(&block)
43
+ end
44
+
45
+ def tsort_each_child(name, &block)
46
+ self[name].dependencies.each(&block) if exposures.key?(name)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ require "pathname"
2
+
3
+ module Dry
4
+ module View
5
+ class Path
6
+ include Dry::Equalizer(:dir, :root)
7
+
8
+ attr_reader :dir, :root
9
+
10
+ def initialize(dir, options = {})
11
+ @dir = Pathname(dir)
12
+ @root = Pathname(options.fetch(:root, dir))
13
+ end
14
+
15
+ def lookup(name, format)
16
+ template?(name, format) || template?("shared/#{name}", format) || !root? && chdir('..').lookup(name, format)
17
+ end
18
+
19
+ def chdir(dirname)
20
+ self.class.new(dir.join(dirname), root: root)
21
+ end
22
+
23
+ def to_s
24
+ dir
25
+ end
26
+
27
+ private
28
+
29
+ def root?
30
+ dir == root
31
+ end
32
+
33
+ # Search for a template using a wildcard for the engine extension
34
+ def template?(name, format)
35
+ glob = dir.join("#{name}.#{format}.*")
36
+ Dir[glob].first
37
+ end
38
+ end
39
+ end
40
+ end
@@ -4,21 +4,19 @@ require 'dry-equalizer'
4
4
  module Dry
5
5
  module View
6
6
  class Renderer
7
- include Dry::Equalizer(:dir, :root, :engine)
7
+ include Dry::Equalizer(:paths, :format)
8
8
 
9
9
  TemplateNotFoundError = Class.new(StandardError)
10
10
 
11
- attr_reader :dir, :root, :format, :engine, :tilts
11
+ attr_reader :paths, :format, :engine, :tilts
12
12
 
13
13
  def self.tilts
14
14
  @__engines__ ||= {}
15
15
  end
16
16
 
17
- def initialize(dir, options = {})
18
- @dir = dir
19
- @root = options.fetch(:root, dir)
20
- @format = options[:format]
21
- @engine = options[:engine]
17
+ def initialize(paths, format:)
18
+ @paths = paths
19
+ @format = format
22
20
  @tilts = self.class.tilts
23
21
  end
24
22
 
@@ -28,7 +26,8 @@ module Dry
28
26
  if path
29
27
  render(path, scope, &block)
30
28
  else
31
- raise TemplateNotFoundError, "Template #{template} could not be looked up within #{root}"
29
+ msg = "Template #{template.inspect} could not be found in paths:\n#{paths.map { |pa| "- #{pa.to_s}" }.join("\n")}"
30
+ raise TemplateNotFoundError, msg
32
31
  end
33
32
  end
34
33
 
@@ -36,32 +35,25 @@ module Dry
36
35
  tilt(path).render(scope, &block)
37
36
  end
38
37
 
39
- def tilt(path)
40
- tilts.fetch(path) { tilts[path] = Tilt[engine].new(path, nil, default_encoding: "utf-8") }
41
- end
42
-
43
- def lookup(name)
44
- template?(name) || template?("shared/#{name}") || !root? && chdir('..').lookup(name)
45
- end
38
+ def chdir(dirname)
39
+ new_paths = paths.map { |path| path.chdir(dirname) }
46
40
 
47
- def root?
48
- dir == root
41
+ self.class.new(new_paths, format: format)
49
42
  end
50
43
 
51
- def template?(name)
52
- template_path = path(name)
53
-
54
- if File.exist?(template_path)
55
- template_path
56
- end
44
+ def lookup(name)
45
+ paths.inject(false) { |result, path|
46
+ result || path.lookup(name, format)
47
+ }
57
48
  end
58
49
 
59
- def path(name)
60
- dir.join("#{name}.#{format}.#{engine}")
61
- end
50
+ private
62
51
 
63
- def chdir(dirname)
64
- self.class.new(dir.join(dirname), engine: engine, format: format, root: root)
52
+ # TODO: make default_encoding configurable
53
+ def tilt(path)
54
+ tilts.fetch(path) {
55
+ tilts[path] = Tilt.new(path, nil, default_encoding: "utf-8")
56
+ }
65
57
  end
66
58
  end
67
59
  end
@@ -0,0 +1,55 @@
1
+ require 'dry-equalizer'
2
+
3
+ module Dry
4
+ module View
5
+ class Scope
6
+ include Dry::Equalizer(:_renderer, :_data)
7
+
8
+ attr_reader :_renderer
9
+ attr_reader :_data
10
+ attr_reader :_context
11
+
12
+ def initialize(renderer, data, context = nil)
13
+ @_renderer = renderer
14
+ @_data = data.to_hash
15
+ @_context = context
16
+ end
17
+
18
+ def respond_to_missing?(name, include_private = false)
19
+ _template?(name) || _data.key?(name) || _context.respond_to?(name)
20
+ end
21
+
22
+ private
23
+
24
+ def method_missing(name, *args, &block)
25
+ if _data.key?(name)
26
+ _data[name]
27
+ elsif _context.respond_to?(name)
28
+ _context.public_send(name, *args, &block)
29
+ elsif (template_path = _template?(name))
30
+ _render(template_path, *args, &block)
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def _template?(name)
37
+ _renderer.lookup("_#{name}")
38
+ end
39
+
40
+ def _render(path, *args, &block)
41
+ _renderer.render(path, _render_args(*args), &block)
42
+ end
43
+
44
+ def _render_args(*args)
45
+ if args.empty?
46
+ self
47
+ elsif args.length == 1 && args.first.respond_to?(:to_hash)
48
+ self.class.new(_renderer, args.first, _context)
49
+ else
50
+ raise ArgumentError, "render argument must be a Hash"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module View
3
- VERSION = '0.1.1'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
data/lib/dry/view.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  require 'dry/view/renderer'
2
- require 'dry/view/layout'
2
+ require 'dry/view/controller'
@@ -0,0 +1 @@
1
+ p This is a view with no locals.
@@ -1,6 +1,6 @@
1
1
  doctype html
2
2
  html
3
3
  head
4
- title == page.title
4
+ title == title
5
5
  body
6
6
  == yield
@@ -1,3 +1,3 @@
1
- # <%= page.title %>
1
+ # <%= title %>
2
2
 
3
3
  <%= yield %>
@@ -0,0 +1,3 @@
1
+ div.box
2
+ h2 = label
3
+ = user[:name]
@@ -0,0 +1,3 @@
1
+ .users
2
+ - users.each do |user|
3
+ == box user: user, label: "Nombre"
@@ -1,5 +1,5 @@
1
1
  tbody
2
2
  - users.each do |user|
3
- == user.row do
3
+ == row do
4
4
  td = user[:name]
5
5
  td = user[:email]
@@ -1,5 +1,5 @@
1
- h2 = subtitle
2
-
3
1
  .users
4
- == users.index_table do
5
- == users.tbody
2
+ == index_table do
3
+ == tbody
4
+
5
+ img src=assets["mindblown"]
@@ -1,5 +1,3 @@
1
- ## <%= subtitle %>
2
-
3
1
  <% users.each do |user| %>
4
2
  * <%= user[:name] %> (<%= user[:email] %>)
5
3
  <% end %>
@@ -0,0 +1,5 @@
1
+ ul
2
+ - users.each do |user|
3
+ li = "#{user[:name]} (#{user[:email]})"
4
+
5
+ .count = users_count
@@ -0,0 +1,5 @@
1
+ h1 OVERRIDE
2
+
3
+ .users
4
+ == index_table do
5
+ == tbody