Rename dry-view to hanami-view

This commit is contained in:
Tim Riley 2020-03-15 22:37:02 +11:00
parent 1374f99f3b
commit c2c62434cc
No known key found for this signature in database
GPG Key ID: 747ABA1282E88BC9
74 changed files with 390 additions and 397 deletions

View File

@ -1,5 +1,3 @@
# this file is managed by dry-rb/devtools project
AllCops: AllCops:
TargetRubyVersion: 2.4 TargetRubyVersion: 2.4
Exclude: Exclude:

View File

@ -1,21 +1,21 @@
[gem]: https://rubygems.org/gems/dry-view [gem]: https://rubygems.org/gems/hanami-view
[actions]: https://github.com/dry-rb/dry-view/actions [actions]: https://github.com/hanami/view/actions
[codacy]: https://www.codacy.com/gh/dry-rb/dry-view [codacy]: https://www.codacy.com/gh/hanami/view
[chat]: https://dry-rb.zulipchat.com [chat]: https://dry-rb.zulipchat.com
[inchpages]: http://inch-ci.org/github/dry-rb/dry-view [inchpages]: http://inch-ci.org/github/hanami/view
# dry-view [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat] # hanami-view [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
[![Gem Version](https://badge.fury.io/rb/dry-view.svg)][gem] [![Gem Version](https://badge.fury.io/rb/hanami-view.svg)][gem]
[![CI Status](https://github.com/dry-rb/dry-view/workflows/ci/badge.svg)][actions] [![CI Status](https://github.com/hanami/view/workflows/ci/badge.svg)][actions]
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fe8a45d76d8b45f6a680a29c48b43a99)][codacy] [![Codacy Badge](https://api.codacy.com/project/badge/Grade/fe8a45d76d8b45f6a680a29c48b43a99)][codacy]
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/fe8a45d76d8b45f6a680a29c48b43a99)][codacy] [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/fe8a45d76d8b45f6a680a29c48b43a99)][codacy]
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-view.svg?branch=master)][inchpages] [![Inline docs](http://inch-ci.org/github/hanami/view.svg?branch=master)][inchpages]
## Links ## Links
* [User documentation](http://dry-rb.org/gems/dry-view) * [User documentation](http://dry-rb.org/gems/hanami-view)
* [API documentation](http://rubydoc.info/gems/dry-view) * [API documentation](http://rubydoc.info/gems/hanami-view)
## Supported Ruby versions ## Supported Ruby versions

View File

@ -3,7 +3,7 @@
require "pathname" require "pathname"
require "ostruct" require "ostruct"
require "benchmark/ips" require "benchmark/ips"
require "dry/view" require "hanami/view"
require "action_view" require "action_view"
require "action_controller" require "action_controller"
@ -29,7 +29,7 @@ class UsersController < ActionController::Base
end end
end end
class DryView < Dry::View class HanamiView < Hanami::View
config.paths = TEMPLATES_PATHS config.paths = TEMPLATES_PATHS
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -39,16 +39,16 @@ class DryView < Dry::View
end end
action_controller = UsersController.new action_controller = UsersController.new
dry_view = DryView.new hanami_view = HanamiView.new
action_controller_output = action_controller.index action_controller_output = action_controller.index
dry_view_output = dry_view.(TEMPLATE_LOCALS).to_s hanami_view_output = hanami_view.(TEMPLATE_LOCALS).to_s
if action_controller_output != dry_view_output if action_controller_output != hanami_view_output
puts "Output doesn't match:" puts "Output doesn't match:"
puts puts
puts "ActionView:\n\n#{action_controller_output}\n" puts "ActionView:\n\n#{action_controller_output}\n"
puts "dry-view:\n\n#{dry_view_output}\n" puts "hanami-view:\n\n#{hanami_view_output}\n"
end end
Benchmark.ips do |x| Benchmark.ips do |x|
@ -56,8 +56,8 @@ Benchmark.ips do |x|
1000.times { action_controller.index } 1000.times { action_controller.index }
end end
x.report("dry-view") do x.report("hanami-view") do
1000.times { dry_view.(TEMPLATE_LOCALS).to_s } 1000.times { hanami_view.(TEMPLATE_LOCALS).to_s }
end end
x.compare! x.compare!

View File

@ -3,7 +3,7 @@
require "hotch" require "hotch"
require "pathname" require "pathname"
require "ostruct" require "ostruct"
require "dry/view" require "hanami/view"
TEMPLATES_PATHS = Pathname(__FILE__).dirname.join("templates") TEMPLATES_PATHS = Pathname(__FILE__).dirname.join("templates")
@ -14,7 +14,7 @@ TEMPLATE_LOCALS = {
] ]
}.freeze }.freeze
class View < Dry::View class View < Hanami::View
config.paths = TEMPLATES_PATHS config.paths = TEMPLATES_PATHS
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -25,5 +25,5 @@ end
view = View.new view = View.new
Hotch(filter: /View/) do Hotch(filter: /View/) do
100.times { view.(TEMPLATE_LOCALS).to_s } 100.times { view.(**TEMPLATE_LOCALS).to_s }
end end

View File

@ -1,4 +1,4 @@
<% users.each_with_index do |user, index| %> <% users.each_with_index do |user, index| %>
<h1><%= user.name %></h1> <h1><%= user.name %></h1>
<%= render 'button', { user_link: user.email, index: index + 1 } %> <%= render 'button', user_link: user.email, index: index + 1 %>
<% end %> <% end %>

View File

@ -2,7 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "bundler/setup" require "bundler/setup"
require "dry-view" require "hanami-view"
require "pry" require "pry"
Pry.start Pry.start

View File

@ -1,13 +1,13 @@
--- ---
title: Configuration title: Configuration
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
You can configure your views via class-level `config`. Basic configuration looks like this: You can configure your views via class-level `config`. Basic configuration looks like this:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.paths = [File.join(__dir__, "templates")] config.paths = [File.join(__dir__, "templates")]
config.layout = "application" config.layout = "application"
config.template = "my_view" config.template = "my_view"
@ -40,7 +40,7 @@ In an app with many views, its helpful to use inheritance to share common set
```ruby ```ruby
module MyApp module MyApp
class View < Dry::View class View < Hanami::View
# Set common configuration in the shared base view class # Set common configuration in the shared base view class
config.paths = [File.join(__dir__, "templates")] config.paths = [File.join(__dir__, "templates")]
config.layout = "application" config.layout = "application"
@ -61,7 +61,7 @@ end
## Changing configuration at render-time ## Changing configuration at render-time
Some configuration-related options can also be passed at render-time, to `Dry::View#call`. Some configuration-related options can also be passed at render-time, to `Hanami::View#call`.
- **format**: Specify another format for rendering the view. This overrides the `default_format` setting. - **format**: Specify another format for rendering the view. This overrides the `default_format` setting.
- **context**: Provide an alternative [context object](docs::context) for the [template scope](docs::templates). This is helpful for providing a context object that has, for example, data specific to the current HTTP request. - **context**: Provide an alternative [context object](docs::context) for the [template scope](docs::templates). This is helpful for providing a context object that has, for example, data specific to the current HTTP request.

View File

@ -1,7 +1,7 @@
--- ---
title: Context title: Context
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
Use a context object to provide shared facilities to every template, partial, scope, and part in a given view rendering. Use a context object to provide shared facilities to every template, partial, scope, and part in a given view rendering.
@ -15,19 +15,19 @@ A context object is helpful in holding any behaviour or data you don't want to p
## Defining a context ## Defining a context
Context classes must inherit from `Dry::View::Context` Context classes must inherit from `Hanami::View::Context`
```ruby ```ruby
class MyContext < Dry::View::Context class MyContext < Hanami::View::Context
end end
``` ```
## Injecting dependencies ## Injecting dependencies
`Dry::View::Context` is designed to allow dependencies to be injected into your subclasses. To do this, accept your dependencies as keyword arguments to `#initialize`, and pass every other keyword argument through to `super`: `Hanami::View::Context` is designed to allow dependencies to be injected into your subclasses. To do this, accept your dependencies as keyword arguments to `#initialize`, and pass every other keyword argument through to `super`:
```ruby ```ruby
class MyContext < Dry::View::Context class MyContext < Hanami::View::Context
attr_reader :assets attr_reader :assets
def initialize(assets:, **args) def initialize(assets:, **args)
@ -41,13 +41,13 @@ class MyContext < Dry::View::Context
end end
``` ```
If your app uses [dry-system](/gems/dry-system) or [dry-auto_inject](/gems/dry-auto_inject), this is even less work. dry-auto_inject works out of the box with `Dry::View::Context`s initializer: If your app uses [dry-system](/gems/dry-system) or [dry-auto_inject](/gems/dry-auto_inject), this is even less work. dry-auto_inject works out of the box with `Hanami::View::Context`s initializer:
```ruby ```ruby
# Require the auto-injector module for your app's container # Require the auto-injector module for your app's container
require "my_app/import" require "my_app/import"
class MyContext < Dry::View::Context class MyContext < Hanami::View::Context
include MyApp::Import["assets"] include MyApp::Import["assets"]
def asset_path(asset_name) def asset_path(asset_name)
@ -61,7 +61,7 @@ end
The default context can be `configured` for a view: The default context can be `configured` for a view:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.default_context = MyContext.new config.default_context = MyContext.new
end end
``` ```
@ -81,7 +81,7 @@ When providing a context at render time, you may wish to provide a version of yo
Your context may have attribute that you want decorated as [parts](docs::parts). Declare these using `decorate` in your context class: Your context may have attribute that you want decorated as [parts](docs::parts). Declare these using `decorate` in your context class:
```ruby ```ruby
class MyContext < Dry::View::Context class MyContext < Hanami::View::Context
decorate :navigation_items decorate :navigation_items
attr_reader :navigation_items attr_reader :navigation_items
@ -96,7 +96,7 @@ end
You can pass the same options to `decorate` as you do to [exposures](docs::exposures), for example: You can pass the same options to `decorate` as you do to [exposures](docs::exposures), for example:
```ruby ```ruby
class MyContext < Dry::View::Context class MyContext < Hanami::View::Context
decorate :navigation_items, as: :menu_items decorate :navigation_items, as: :menu_items
# ... # ...

View File

@ -1,7 +1,7 @@
--- ---
title: Exposures title: Exposures
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
Define _exposures_ within your view to declare and prepare the values to be passed to the template, decorated as [parts](docs::parts). Define _exposures_ within your view to declare and prepare the values to be passed to the template, decorated as [parts](docs::parts).
@ -9,7 +9,7 @@ Define _exposures_ within your view to declare and prepare the values to be pass
An exposure can take a block: An exposure can take a block:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
expose :users do expose :users do
user_repo.listing user_repo.listing
end end
@ -19,7 +19,7 @@ end
Or refer to an instance method: Or refer to an instance method:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
expose :users expose :users
private private
@ -33,7 +33,7 @@ end
Or allow a matching value from the input data to pass through to the view: Or allow a matching value from the input data to pass through to the view:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
# With no matching instance method, passes the `users:` argument provided to # With no matching instance method, passes the `users:` argument provided to
# `#call` straight to the template # `#call` straight to the template
expose :users expose :users
@ -45,7 +45,7 @@ end
If your exposure needs to work with input data (i.e. the arguments passed to the views `#call`), specify these as keyword arguments for your exposure block. Make this a _required_ keyword argument if you require the data passed to the views `#call`: If your exposure needs to work with input data (i.e. the arguments passed to the views `#call`), specify these as keyword arguments for your exposure block. Make this a _required_ keyword argument if you require the data passed to the views `#call`:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
expose :users do |page:| expose :users do |page:|
user_repo.listing(page: page) user_repo.listing(page: page)
end end
@ -55,7 +55,7 @@ end
The same applies to instance methods acting as exposures: The same applies to instance methods acting as exposures:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
expose :users expose :users
private private
@ -71,7 +71,7 @@ end
To make input data optional, provide a default value for the keyword argument (either `nil` or something more meaningful): To make input data optional, provide a default value for the keyword argument (either `nil` or something more meaningful):
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
expose :users do |page: 1| expose :users do |page: 1|
user_repo.listing(page: page) user_repo.listing(page: page)
end end
@ -81,7 +81,7 @@ end
If your exposure passes through input data directly, use the `default:` option: If your exposure passes through input data directly, use the `default:` option:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
# With no matching instance method, passes the `users:` argument to `#call` # With no matching instance method, passes the `users:` argument to `#call`
# straight to the template # straight to the template
expose :users, default: [] expose :users, default: []
@ -103,7 +103,7 @@ end
Sometimes you may want to prepare data for other exposures to use. You can _depend_ on another exposure by naming it as a positional argument for your exposure block or method. Sometimes you may want to prepare data for other exposures to use. You can _depend_ on another exposure by naming it as a positional argument for your exposure block or method.
```ruby ```ruby
class MyView < Dry::View::Controller class MyView < Hanami::View::Controller
expose :users do |page:| expose :users do |page:|
user_repo.listing(page: page) user_repo.listing(page: page)
end end
@ -139,7 +139,7 @@ end
You can create _private exposures_ that are not passed to the template. This is helpful if you have an exposure that others will depend on, but is not otherwise needed in the template. Use `private_expose` for this: You can create _private exposures_ that are not passed to the template. This is helpful if you have an exposure that others will depend on, but is not otherwise needed in the template. Use `private_expose` for this:
```ruby ```ruby
class MyView < Dry::View::Controller class MyView < Hanami::View::Controller
private_expose :user_listing do private_expose :user_listing do
user_repo.listing user_repo.listing
end end

View File

@ -2,7 +2,7 @@
title: Introduction title: Introduction
layout: gem-single layout: gem-single
type: gem type: gem
name: dry-view name: hanami-view
sections: sections:
- configuration - configuration
- injecting-dependencies - injecting-dependencies
@ -14,20 +14,20 @@ sections:
- testing - testing
--- ---
dry-view is a complete, standalone view rendering system that gives you everything you need to write well-factored view code. hanami-view is a complete, standalone view rendering system that gives you everything you need to write well-factored view code.
Use dry-view if: Use hanami-view if:
- You recognize that view code can be complex, and want to work with a system that allows you to break your view logic apart into sensible units - You recognize that view code can be complex, and want to work with a system that allows you to break your view logic apart into sensible units
- You want to be able to [unit test](docs::testing) all aspects of your views, in complete isolation - You want to be able to [unit test](docs::testing) all aspects of your views, in complete isolation
- You want to maintain a sensible separation of concerns between the layers of functionality within your app - You want to maintain a sensible separation of concerns between the layers of functionality within your app
- You want to build and render views in any kind of context, not just when serving HTTP requests - You want to build and render views in any kind of context, not just when serving HTTP requests
- You're using a lightweight routing DSL like Roda or Sinatra and you want to keep your routes clean and easy to understand (dry-view handles the integration with your application, so all you need to provide from routes is the user-provided input params) - You're using a lightweight routing DSL like Roda or Sinatra and you want to keep your routes clean and easy to understand (hanami-view handles the integration with your application, so all you need to provide from routes is the user-provided input params)
- Your application structure supports dependency injection as the preferred way to share behaviour between components (e.g. dry-view fits perfectly with [dry-system](/gems/dry-system), [dry-container](/gems/dry-container), and [dry-auto_inject](/gems/dry-auto_inject)) - Your application structure supports dependency injection as the preferred way to share behaviour between components (e.g. hanami-view fits perfectly with [dry-system](/gems/dry-system), [dry-container](/gems/dry-container), and [dry-auto_inject](/gems/dry-auto_inject))
## Concepts ## Concepts
dry-view divides the responsibility of view rendering across several different components: hanami-view divides the responsibility of view rendering across several different components:
- The **View**, representing a view in its entirety, holding its configuration as well as any application-provided dependencies - The **View**, representing a view in its entirety, holding its configuration as well as any application-provided dependencies
- [**Exposures**](docs::exposures), defined as part of the view, declare the values that should be exposed to the template, and how they should be prepared - [**Exposures**](docs::exposures), defined as part of the view, declare the values that should be exposed to the template, and how they should be prepared
@ -43,7 +43,7 @@ dry-view divides the responsibility of view rendering across several different c
```ruby ```ruby
require "dry/view" require "dry/view"
class ArticleView < Dry::View class ArticleView < Hanami::View
config.paths = [File.join(__dir__, "templates")] config.paths = [File.join(__dir__, "templates")]
config.part_namespace = Parts config.part_namespace = Parts
config.layout = "application" config.layout = "application"
@ -82,7 +82,7 @@ Define a [part](docs::parts) to provide view-specific behavior around the expose
```ruby ```ruby
module Parts module Parts
class Article < Dry::View::Part class Article < Hanami::View::Part
def byline_text def byline_text
authors.map(&:name).join(", ") authors.map(&:name).join(", ")
end end
@ -98,4 +98,4 @@ view.call(slug: "cheeseburger-backpack").to_s
# => "<html><body><h1>Cheeseburger Backpack</h1><p>Rebecca Sugar, Ian Jones-Quartey</p></body></html> # => "<html><body><h1>Cheeseburger Backpack</h1><p>Rebecca Sugar, Ian Jones-Quartey</p></body></html>
``` ```
`Dry::View::#call` expects keyword arguments for input data. These arguments are handled by your [exposures](docs::exposures), which prepare [view parts](docs::parts) that are passed to your [template](docs::templates) for rendering. `Hanami::View::#call` expects keyword arguments for input data. These arguments are handled by your [exposures](docs::exposures), which prepare [view parts](docs::parts) that are passed to your [template](docs::templates) for rendering.

View File

@ -1,7 +1,7 @@
--- ---
title: Injecting dependencies title: Injecting dependencies
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
Most views will need access to other parts of your application to prepare values for the view. Since views follow the "functional object" pattern (local state for config and collaborators only, with any variable data passed to `#call`), its easy to use dependency injection to make your applications objects available to your views. Most views will need access to other parts of your application to prepare values for the view. Since views follow the "functional object" pattern (local state for config and collaborators only, with any variable data passed to `#call`), its easy to use dependency injection to make your applications objects available to your views.
@ -9,7 +9,7 @@ Most views will need access to other parts of your application to prepare values
To set up the injection manually, accept arguments to `#initialize` and assign them to instance variables. To set up the injection manually, accept arguments to `#initialize` and assign them to instance variables.
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
attr_reader :user_repo attr_reader :user_repo
def initialize(user_repo:) def initialize(user_repo:)
@ -29,7 +29,7 @@ Or if your app uses [dry-system](/gems/dry-system) or [dry-auto_inject](/gems/dr
# Require the auto-injector module for your app's container # Require the auto-injector module for your app's container
require "my_app/import" require "my_app/import"
class MyView < Dry::View class MyView < Hanami::View
include MyApp::Import["user_repo"] include MyApp::Import["user_repo"]
expose :users do expose :users do

View File

@ -1,22 +1,22 @@
--- ---
title: Parts title: Parts
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
All values [exposed](docs::exposures) by your view are decorated and passed to your templates as _parts_, which allow encapsulation of view-specific behavior alongside your application's domain objects. All values [exposed](docs::exposures) by your view are decorated and passed to your templates as _parts_, which allow encapsulation of view-specific behavior alongside your application's domain objects.
Unlike many third-party approaches to view object decoration, dry-view's parts are fully integrated and have access to the full rendering environment, which means that anything you can do from a template, you can also do from a part. This includes accessing the context object as well as rendering partials and building scopes. Unlike many third-party approaches to view object decoration, hanami-view's parts are fully integrated and have access to the full rendering environment, which means that anything you can do from a template, you can also do from a part. This includes accessing the context object as well as rendering partials and building scopes.
This means that much more view logic can move out of template and into parts, which makes the templates simpler and more declarative, and puts the view logic into a place where it can be reused and refactored using typical object oriented approaches, as well as tested in isolation. This means that much more view logic can move out of template and into parts, which makes the templates simpler and more declarative, and puts the view logic into a place where it can be reused and refactored using typical object oriented approaches, as well as tested in isolation.
## Defining a part class ## Defining a part class
To provide custom part behavior, define your own part classes in a common namespace (e.g. `Parts`) and [configure that](docs::configuration) as your view's `part_namespace` Each part class must inherit from `Dry::View::Part`. To provide custom part behavior, define your own part classes in a common namespace (e.g. `Parts`) and [configure that](docs::configuration) as your view's `part_namespace` Each part class must inherit from `Hanami::View::Part`.
```ruby ```ruby
module Parts module Parts
class User < Dry::View::Part class User < Hanami::View::Part
end end
end end
``` ```
@ -31,7 +31,7 @@ For an exposure returning an array, the exposure's name will be singularized and
So for an exposure named `:articles`, the `Parts::Article` class will be looked up for decorating each element, and the `Parts::Articles` class will be looked up for decorating the entire array. So for an exposure named `:articles`, the `Parts::Article` class will be looked up for decorating each element, and the `Parts::Articles` class will be looked up for decorating the entire array.
If a matching part class cannot be found, the standard `Dry::View::Part` class will be used. If a matching part class cannot be found, the standard `Hanami::View::Part` class will be used.
## Accessing the decorated value ## Accessing the decorated value
@ -47,7 +47,7 @@ For example, from a template:
Or when defining a custom part class: Or when defining a custom part class:
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def display_name def display_name
# `name` and `email` are methods on the decorated user value # `name` and `email` are methods on the decorated user value
"#{name} <#{email}>" "#{name} <#{email}>"
@ -58,7 +58,7 @@ end
In case of naming collisions or when overriding a method, you can access the value directly via `#_value` (or `#value` as a convenience, as long the decorated value itself doesn't respond to `#value`): In case of naming collisions or when overriding a method, you can access the value directly via `#_value` (or `#value` as a convenience, as long the decorated value itself doesn't respond to `#value`):
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def name def name
value.name.upcase value.name.upcase
end end
@ -78,7 +78,7 @@ When used to output to the template, a part will use it's value `#to_s` behavior
From a part, you can render a partial, with the part object included in the partial's own locals: From a part, you can render a partial, with the part object included in the partial's own locals:
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def info_box def info_box
render(:info_box) render(:info_box)
end end
@ -110,7 +110,7 @@ You can also provide additional locals for the partial:
You may [build custom scopes](docs::scopes) from within a part using `#_scope` (or `#scope` as a convenience, as long as the decorated value doesn't respond to `#scope`): You may [build custom scopes](docs::scopes) from within a part using `#_scope` (or `#scope` as a convenience, as long as the decorated value doesn't respond to `#scope`):
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def info_box def info_box
scope(:info_box, size: :large).render scope(:info_box, size: :large).render
end end
@ -124,7 +124,7 @@ In your part classes, you can access the [context object](docs::context) as `#_c
For example: For example:
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def avatar_url def avatar_url
# asset_path is a method defined on the context object (in this case, # asset_path is a method defined on the context object (in this case,
# providing static asset URLs) # providing static asset URLs)
@ -138,7 +138,7 @@ end
Your values may have their own attributes that you also want decorated as view parts. Declare these using `decorate` in your own view part classes: Your values may have their own attributes that you also want decorated as view parts. Declare these using `decorate` in your own view part classes:
```ruby ```ruby
class UserPart < Dry::View::Part class UserPart < Hanami::View::Part
decorate :address decorate :address
end end
``` ```
@ -146,7 +146,7 @@ end
You can pass the same options to `decorate` as you do to [exposures](docs::exposures), for example: You can pass the same options to `decorate` as you do to [exposures](docs::exposures), for example:
```ruby ```ruby
class UserPart < Dry::View::Part class UserPart < Hanami::View::Part
decorate :address, as: :location decorate :address, as: :location
end end
``` ```
@ -156,7 +156,7 @@ end
A part object lives for the entirety of a view rendering, you can memoize expensive operations to ensure they only run once. A part object lives for the entirety of a view rendering, you can memoize expensive operations to ensure they only run once.
```ruby ```ruby
class User < Dry::View::Part class User < Hanami::View::Part
def bio_html def bio_html
@bio_html ||= rich_text_renderer.render(bio) @bio_html ||= rich_text_renderer.render(bio)
end end
@ -192,7 +192,7 @@ All of these examples presume a configured `part_namespace` of `Parts`.
To fully customize part decoration, you can provide a replacement part builder: To fully customize part decoration, you can provide a replacement part builder:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.part_builder = MyPartBuilder config.part_builder = MyPartBuilder
end end
``` ```
@ -203,4 +203,4 @@ Your part builder must conform to the following interface:
- `#for_render_env(render_env)` - `#for_render_env(render_env)`
- `#call(name, value, **options)` - `#call(name, value, **options)`
You can also inherit from `Dry::View::PartBuilder` and override any of its methods, if you want to customize just a particular aspect of the standard behavior. You can also inherit from `Hanami::View::PartBuilder` and override any of its methods, if you want to customize just a particular aspect of the standard behavior.

View File

@ -1,7 +1,7 @@
--- ---
title: Scopes title: Scopes
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
A scope is the object that determines which methods are available to use from within the template. The [standard scope](docs::templates) provides access to template locals (exposed values), partial rendering, as well as the building of custom scopes. A scope is the object that determines which methods are available to use from within the template. The [standard scope](docs::templates) provides access to template locals (exposed values), partial rendering, as well as the building of custom scopes.
@ -13,16 +13,16 @@ With a custom scope, you can add your own behavior around a template and its par
To provide custom scope behavior, define your own scope classes in a common namespace (e.g. `Scopes`) and [configure that](docs::configuration) as your view's `scope_namespace`: To provide custom scope behavior, define your own scope classes in a common namespace (e.g. `Scopes`) and [configure that](docs::configuration) as your view's `scope_namespace`:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.scope_namespace = Scopes config.scope_namespace = Scopes
end end
``` ```
Each scope class must inherit from `Dry::View::Scope`: Each scope class must inherit from `Hanami::View::Scope`:
```ruby ```ruby
module Scopes module Scopes
class MediaPlayer < Dry::View::Scope class MediaPlayer < Hanami::View::Scope
end end
end end
``` ```
@ -47,7 +47,7 @@ Scope classes are looked up based on the configured `scope_namespace` and the na
So for a `scope_namespace` of `Scopes` and scope built as `:media_player`, the `Scopes::MediaPlayer` class will be looked up. So for a `scope_namespace` of `Scopes` and scope built as `:media_player`, the `Scopes::MediaPlayer` class will be looked up.
If a matching scope class cannot be found, the standard `Dry::View::Scope` class will be used. If a matching scope class cannot be found, the standard `Hanami::View::Scope` class will be used.
## Rendering partials ## Rendering partials
@ -70,7 +70,7 @@ This will use the scope's name for the name of the partial. In the example above
You can also render partials from within your scope class' own methods: You can also render partials from within your scope class' own methods:
```ruby ```ruby
class MediaPlayer < Dry::View::Scope class MediaPlayer < Hanami::View::Scope
def audio_player_html def audio_player_html
render(:audio_player) render(:audio_player)
end end
@ -91,7 +91,7 @@ For example, from a template:
Or from a custom scope class: Or from a custom scope class:
```ruby ```ruby
class MediaPlayer < Dry::View::Scope class MediaPlayer < Hanami::View::Scope
def display_title def display_title
# `item` is a local # `item` is a local
"#{item.title} (#{item.duration})" "#{item.title} (#{item.duration})"
@ -104,7 +104,7 @@ You can also access the full hash of locals via `#_locals` (or `#locals` as a co
This is useful for providing default values for locals that may not explicitly be passed when the scope is built: This is useful for providing default values for locals that may not explicitly be passed when the scope is built:
```ruby ```ruby
class MediaPlayer < Dry::View::Scope class MediaPlayer < Hanami::View::Scope
def show_artwork? def show_artwork?
locals.fetch(:show_artwork, true) locals.fetch(:show_artwork, true)
end end
@ -120,7 +120,7 @@ Scopes also delegate missing methods to the context object (provided there is no
For example: For example:
```ruby ```ruby
class MediaPlayer < Dry::View::Scope class MediaPlayer < Hanami::View::Scope
def image_urls def image_urls
# item is a local, and asset_path is a method defined on the context object # item is a local, and asset_path is a method defined on the context object
[item.image_url, asset_path("standard-media-artwork.png")] [item.image_url, asset_path("standard-media-artwork.png")]
@ -139,7 +139,7 @@ Aside from building custom scopes explicitly, you can also specify a scope to be
You can specify the scope as a direct class reference: You can specify the scope as a direct class reference:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.template = "my_view" config.template = "my_view"
config.scope = Scopes::MyView config.scope = Scopes::MyView
end end
@ -148,7 +148,7 @@ end
Or if you have a scope namepace configured, you can use a symbolic name and a matching scope will be looked up: Or if you have a scope namepace configured, you can use a symbolic name and a matching scope will be looked up:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.template = "my_view" config.template = "my_view"
config.scope_namespace = Scopes config.scope_namespace = Scopes
config.scope = :my_view config.scope = :my_view
@ -160,7 +160,7 @@ end
To fully customize scope lookup and initialization, you can provide a replacement scope builder: To fully customize scope lookup and initialization, you can provide a replacement scope builder:
```ruby ```ruby
class MyView < Dry::View class MyView < Hanami::View
config.scope_builder = MyScopeBuilder config.scope_builder = MyScopeBuilder
end end
``` ```
@ -171,4 +171,4 @@ Your scope builder must conform to the following interface:
- `#for_render_env(render_env)` - `#for_render_env(render_env)`
- `#call(name = nil, locals)` - `#call(name = nil, locals)`
You can also inherit from `Dry::View::ScopeBuilder` and override any of its methods, if you want to customize just a particular aspect of the standard behavior. You can also inherit from `Hanami::View::ScopeBuilder` and override any of its methods, if you want to customize just a particular aspect of the standard behavior.

View File

@ -1,7 +1,7 @@
--- ---
title: Templates title: Templates
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
Every view has a template, which is passed the values from the views [exposures](docs::exposures) and then used to render the view output. Every view has a template, which is passed the values from the views [exposures](docs::exposures) and then used to render the view output.
@ -18,9 +18,9 @@ An example is `index.html.slim`, which would be found for a view controller with
## Template engines ## Template engines
dry-view uses [Tilt](https://github.com/rtomayko/tilt) to render its templates, and relies upon Tilts auto-detection of rendering engine based on the template files extension. However, you should explicitly `require` any engine gems that you intend to use. hanami-view uses [Tilt](https://github.com/rtomayko/tilt) to render its templates, and relies upon Tilts auto-detection of rendering engine based on the template files extension. However, you should explicitly `require` any engine gems that you intend to use.
Some Tilt-supplied template engines may not fully support dry-view's features (like implicit block capturing). Your view will raise an exception, along with instructions for resolving the issue, if Tilt provides a non-compatible engine. Some Tilt-supplied template engines may not fully support hanami-view's features (like implicit block capturing). Your view will raise an exception, along with instructions for resolving the issue, if Tilt provides a non-compatible engine.
The currently known problematic engines are: The currently known problematic engines are:
@ -31,7 +31,7 @@ The currently known problematic engines are:
Each template is rendered with its own _scope_, which determines the methods available within the template. The scope behavior is established by 3 things: Each template is rendered with its own _scope_, which determines the methods available within the template. The scope behavior is established by 3 things:
1. The scopes class, which is `Dry::View::Scope` by default, but can be changed for a template by specifying a class for the views [`scope` setting](docs::configuration), or for a partial rendering by using [`#scope`](docs::scopes) from within a part or scope method, or within the template itself 1. The scopes class, which is `Hanami::View::Scope` by default, but can be changed for a template by specifying a class for the views [`scope` setting](docs::configuration), or for a partial rendering by using [`#scope`](docs::scopes) from within a part or scope method, or within the template itself
2. The templates _locals_, the [exposure values](docs::exposures) decorated by their [parts](docs::parts) 2. The templates _locals_, the [exposure values](docs::exposures) decorated by their [parts](docs::parts)
3. The [context object](docs::context) 3. The [context object](docs::context)

View File

@ -1,10 +1,10 @@
--- ---
title: Testing title: Testing
layout: gem-single layout: gem-single
name: dry-view name: hanami-view
--- ---
dry-view is designed to encourage better testing of your views, with every component designed to support unit testing, in full isolation. This means you can test your views at whatever level of granularity makes sense for you, all the while maintaining a responsive test-driven development cycle. hanami-view is designed to encourage better testing of your views, with every component designed to support unit testing, in full isolation. This means you can test your views at whatever level of granularity makes sense for you, all the while maintaining a responsive test-driven development cycle.
## Testing views ## Testing views
@ -13,7 +13,7 @@ To test a view object in full, initialize it, passing in any [dependencies](docs
Given this view: Given this view:
```ruby ```ruby
class ArticleView < Dry::View class ArticleView < Hanami::View
config.template = "article" config.template = "article"
attr_reader :repo attr_reader :repo
@ -82,7 +82,7 @@ To test simple [part](docs::parts) behavior, initialize a part and make your exp
```ruby ```ruby
module Parts module Parts
class Article < Dry::View::Part class Article < Hanami::View::Part
def byline def byline
"By #{author_name}" "By #{author_name}"
end end
@ -106,14 +106,14 @@ end
To test [part](docs::parts) behavior that [renders partials](docs::templates) or accesses the [context](docs::context), the part will need to be initialized with a name and _render environment_. You can get a render environment from a related view class via its `.template_env`: To test [part](docs::parts) behavior that [renders partials](docs::templates) or accesses the [context](docs::context), the part will need to be initialized with a name and _render environment_. You can get a render environment from a related view class via its `.template_env`:
```ruby ```ruby
class ArticleView < Dry::View class ArticleView < Hanami::View
config.template = "article" config.template = "article"
config.part_namespace = Parts config.part_namespace = Parts
# ... # ...
end end
module Parts module Parts
class Article < Dry::View::Part class Article < Hanami::View::Part
def author_details_html def author_details_html
render(:author_details, author: author) render(:author_details, author: author)
end end

View File

@ -3,7 +3,7 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "byebug" gem "byebug"
gem "dry-view", path: "../.." gem "hanami-view", path: "../.."
gem "dry-web" gem "dry-web"
gem "sinatra" gem "sinatra"
gem "slim" gem "slim"

View File

@ -1,4 +1,4 @@
# dry-view example dry-system/sinatra app # hanami-view example dry-system/sinatra app
## Setup ## Setup
@ -12,7 +12,7 @@ To see the rendered views, run `bundle exec rackup` and visit http://localhost:9
## Integration ## Integration
The following files/folders are specific to the dry-view integration: The following files/folders are specific to the hanami-view integration:
- View helper methods in `lib/example_app/web.rb` - View helper methods in `lib/example_app/web.rb`
- `lib/example_app/view.rb` - `lib/example_app/view.rb`
@ -20,4 +20,4 @@ The following files/folders are specific to the dry-view integration:
- `lib/example_app/views/` - `lib/example_app/views/`
- `web/templates/` - `web/templates/`
n.b. this is a minimal integration to demonstrate how dry-view can fit within an app using dry-system and a web front-end like Sinatra; there's plenty more that could be done to flesh out the view-related features and improve the overall experience. n.b. this is a minimal integration to demonstrate how hanami-view can fit within an app using dry-system and a web front-end like Sinatra; there's plenty more that could be done to flesh out the view-related features and improve the overall experience.

View File

@ -2,12 +2,12 @@
# auto_register: false # auto_register: false
require "dry/view" require "hanami/view"
require "slim" require "slim"
require "example_app/container" require "example_app/container"
module ExampleApp module ExampleApp
class View < Dry::View class View < Hanami::View
config.paths = Container.root.join("web/templates") config.paths = Container.root.join("web/templates")
config.layout = "application" config.layout = "application"
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative "../view" require_relative "../view"
require "dry/view/context" require "hanami/view/context"
module ExampleApp module ExampleApp
class View class View
class Context < Dry::View::Context class Context < Hanami::View::Context
def initialize(**options) def initialize(**options)
@options = options @options = options
super(**options) super(**options)

View File

@ -1,5 +1,5 @@
html html
head head
title dry-view example app using dry-system/sinatra title hanami-view example app using dry-system/sinatra
body body
== yield == yield

View File

@ -8,7 +8,7 @@ gem "puma", "~> 3.11"
gem "rails", "~> 5.2.2" gem "rails", "~> 5.2.2"
gem "sqlite3" gem "sqlite3"
gem "dry-view", path: "../.." gem "hanami-view", path: "../.."
gem "slim" gem "slim"
group :development, :test do group :development, :test do

View File

@ -1,4 +1,4 @@
# dry-view example Rails app # hanami-view example Rails app
## Setup ## Setup
@ -18,14 +18,14 @@ To see the rendered views, run `./bin/rails server` and visit http://localhost:3
## Integration ## Integration
The following files/folders are specific to the dry-view integration: The following files/folders are specific to the hanami-view integration:
- Setup lines in `config/application.rb` - Setup lines in `config/application.rb`
- `app/views/` - `app/views/`
- `app/templates/` - `app/templates/`
n.b. this is a minimal integration to demonstrate how dry-view can work with Rails; there's plenty more that could be done to deepen the integration, flesh out the view-related features, and improve the overall experience. n.b. this is a minimal integration to demonstrate how hanami-view can work with Rails; there's plenty more that could be done to deepen the integration, flesh out the view-related features, and improve the overall experience.
The ideal integration would come via a dry-view-rails integration gem. See [this open issue][issue] for more details. The ideal integration would come via a hanami-view-rails integration gem. See [this open issue][issue] for more details.
[issue]: https://github.com/dry-rb/dry-view/issues/114 [issue]: https://github.com/dry-rb/dry-view/issues/114

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class ApplicationView < Dry::View class ApplicationView < Hanami::View
config.paths = Rails.root.join("app/templates") config.paths = Rails.root.join("app/templates")
config.default_context = ApplicationViewContext.new config.default_context = ApplicationViewContext.new
end end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/context" require "hanami/view/context"
class ApplicationViewContext < Dry::View::Context class ApplicationViewContext < Hanami::View::Context
def method_missing(name, *args, &block) def method_missing(name, *args, &block)
if url_helpers.respond_to?(name) if url_helpers.respond_to?(name)
url_helpers.public_send(name, *args, &block) url_helpers.public_send(name, *args, &block)

View File

@ -12,14 +12,14 @@ require "action_view/railtie"
# you've limited to :test, :development, or :production. # you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups) Bundler.require(*Rails.groups)
module DryViewExample module HanamiViewExample
class Application < Rails::Application class Application < Rails::Application
config.load_defaults 5.2 config.load_defaults 5.2
# dry-view setup # hanami-view setup
Rails.application.config.autoload_paths << Rails.root.join("app/views") Rails.application.config.autoload_paths << Rails.root.join("app/views")
# Remove heinous monkey patch # Remove heinous monkey patch
Dry::View::Part.undef_method :to_param Hanami::View::Part.undef_method :to_param
end end
end end

View File

@ -1,29 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
# this file is managed by dry-rb/devtools project
lib = File.expand_path('lib', __dir__) lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'dry/view/version' require 'hanami/view/version'
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = 'dry-view' spec.name = 'hanami-view'
spec.authors = ["Tim Riley", "Piotr Solnica"] spec.authors = ["Tim Riley", "Piotr Solnica"]
spec.email = ["tim@icelab.com.au", "piotr.solnica@gmail.com"] spec.email = ["tim@icelab.com.au", "piotr.solnica@gmail.com"]
spec.license = 'MIT' spec.license = 'MIT'
spec.version = Dry::View::VERSION.dup spec.version = Hanami::View::VERSION.dup
spec.summary = "A complete, standalone view rendering system that gives you everything you need to write well-factored view code" spec.summary = "A complete, standalone view rendering system that gives you everything you need to write well-factored view code"
spec.description = spec.summary spec.description = spec.summary
spec.homepage = 'https://dry-rb.org/gems/dry-view' spec.homepage = 'https://dry-rb.org/gems/hanami-view'
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-view.gemspec", "lib/**/*"] spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "hanami-view.gemspec", "lib/**/*"]
spec.bindir = 'bin' spec.bindir = 'bin'
spec.executables = [] spec.executables = []
spec.require_paths = ['lib'] spec.require_paths = ['lib']
spec.metadata['allowed_push_host'] = 'https://rubygems.org' spec.metadata['allowed_push_host'] = 'https://rubygems.org'
spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-view/blob/master/CHANGELOG.md' spec.metadata['changelog_uri'] = 'https://github.com/hanami/view/blob/master/CHANGELOG.md'
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-view' spec.metadata['source_code_uri'] = 'https://github.com/hanami/view'
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-view/issues' spec.metadata['bug_tracker_uri'] = 'https://github.com/hanami/view/issues'
spec.required_ruby_version = ">= 2.4.0" spec.required_ruby_version = ">= 2.4.0"

View File

@ -1,3 +1,3 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"

View File

@ -15,11 +15,7 @@ require_relative "view/rendered"
require_relative "view/renderer" require_relative "view/renderer"
require_relative "view/scope_builder" require_relative "view/scope_builder"
# A collection of next-generation Ruby libraries, helping you to write clear, module Hanami
# flexible, and more maintainable Ruby code. Each dry-rb gem fulfils a common
# task, and together they make a powerful platform for any kind of Ruby
# application.
module Dry
# A standalone, template-based view rendering system that offers everything # A standalone, template-based view rendering system that offers everything
# you need to write well-factored view code. # you need to write well-factored view code.
# #
@ -102,7 +98,7 @@ module Dry
# #
# @see https://dry-rb.org/gems/dry-view/scopes/ # @see https://dry-rb.org/gems/dry-view/scopes/
# #
# @param scope_class [Class] scope class (inheriting from `Dry::View::Scope`) # @param scope_class [Class] scope class (inheriting from `Hanami::View::Scope`)
# @api public # @api public
# @!scope class # @!scope class
setting :scope setting :scope
@ -111,11 +107,11 @@ module Dry
# Set the default context object to use when rendering. This will be used # Set the default context object to use when rendering. This will be used
# unless another context object is applied at render-time to `View#call` # unless another context object is applied at render-time to `View#call`
# #
# Defaults to a frozen instance of `Dry::View::Context`. # Defaults to a frozen instance of `Hanami::View::Context`.
# #
# @see View#call # @see View#call
# #
# @param context [Dry::View::Context] context object # @param context [Hanami::View::Context] context object
# @api public # @api public
# @!scope class # @!scope class
setting :default_context, Context.new.freeze setting :default_context, Context.new.freeze

View File

@ -3,7 +3,7 @@
require "dry/equalizer" require "dry/equalizer"
require_relative "decorated_attributes" require_relative "decorated_attributes"
module Dry module Hanami
class View class View
# Provides a baseline environment across all the templates, parts and scopes # Provides a baseline environment across all the templates, parts and scopes
# in a given rendering. # in a given rendering.
@ -25,7 +25,7 @@ module Dry
# while preserving your dependencies. # while preserving your dependencies.
# #
# @example # @example
# class MyContext < Dry::View::Context # class MyContext < Hanami::View::Context
# # Injected dependency # # Injected dependency
# attr_reader :assets # attr_reader :assets
# #
@ -54,7 +54,7 @@ module Dry
# when initializing your custom Context subclass. # when initializing your custom Context subclass.
# #
# @example # @example
# class MyContext < Dry::View::Context # class MyContext < Hanami::View::Context
# # Injected dependencies (request is optional) # # Injected dependencies (request is optional)
# attr_reader :assets, :request # attr_reader :assets, :request
# #

View File

@ -2,7 +2,7 @@
require "set" require "set"
module Dry module Hanami
class View class View
# Decorates attributes in Parts. # Decorates attributes in Parts.
module DecoratedAttributes module DecoratedAttributes
@ -20,7 +20,7 @@ module Dry
# current render environment. # current render environment.
# #
# @example # @example
# class Article < Dry::View::Part # class Article < Hanami::View::Part
# decorate :feature_image # decorate :feature_image
# decorate :author as: :person # decorate :author as: :person
# end # end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
module Dry module Hanami
class View class View
# Error raised when critical settings are not configured # Error raised when critical settings are not configured
# #

View File

@ -2,7 +2,7 @@
require "dry-equalizer" require "dry-equalizer"
module Dry module Hanami
class View class View
# An exposure defined on a view # An exposure defined on a view
# #

View File

@ -2,9 +2,9 @@
require "tsort" require "tsort"
require "dry/equalizer" require "dry/equalizer"
require "dry/view/exposure" require_relative "exposure"
module Dry module Hanami
class View class View
# @api private # @api private
class Exposures class Exposures

View File

@ -4,7 +4,7 @@ require "dry/equalizer"
require_relative "decorated_attributes" require_relative "decorated_attributes"
require_relative "render_environment_missing" require_relative "render_environment_missing"
module Dry module Hanami
class View class View
# Decorates an exposure value and provides a place to encapsulate # Decorates an exposure value and provides a place to encapsulate
# view-specific behavior alongside your application's domain objects. # view-specific behavior alongside your application's domain objects.
@ -144,7 +144,7 @@ module Dry
# scope class # scope class
# @param locals [Hash<Symbol, Object>] other locals to provide the partial # @param locals [Hash<Symbol, Object>] other locals to provide the partial
# #
# @return [Dry::View::Scope] scope # @return [Hanami::View::Scope] scope
# #
# @api public # @api public
def _scope(scope_name = nil, **locals) def _scope(scope_name = nil, **locals)

View File

@ -4,7 +4,7 @@ require "dry/core/cache"
require "dry/equalizer" require "dry/equalizer"
require_relative "part" require_relative "part"
module Dry module Hanami
class View class View
# Decorates exposure values with matching parts # Decorates exposure values with matching parts
# #
@ -37,7 +37,7 @@ module Dry
# @param value [Object] exposure value # @param value [Object] exposure value
# @param options [Hash] exposure options # @param options [Hash] exposure options
# #
# @return [Dry::View::Part] decorated value # @return [Hanami::View::Part] decorated value
# #
# @api private # @api private
def call(name, value, **options) def call(name, value, **options)

View File

@ -3,7 +3,7 @@
require "pathname" require "pathname"
require "dry/core/cache" require "dry/core/cache"
module Dry module Hanami
class View class View
# @api private # @api private
class Path class Path

View File

@ -2,7 +2,7 @@
require "dry/equalizer" require "dry/equalizer"
module Dry module Hanami
class View class View
# @api private # @api private
class RenderEnvironment class RenderEnvironment

View File

@ -2,7 +2,7 @@
require "dry/inflector" require "dry/inflector"
module Dry module Hanami
class View class View
# @api private # @api private
class RenderEnvironmentMissing class RenderEnvironmentMissing

View File

@ -2,7 +2,7 @@
require "dry/equalizer" require "dry/equalizer"
module Dry module Hanami
class View class View
# Output of a View rendering # Output of a View rendering
# #
@ -19,7 +19,7 @@ module Dry
# Returns the hash of locals used to render the view # Returns the hash of locals used to render the view
# #
# @return [Hash[<Symbol, Dry::View::Part>] locals hash # @return [Hash[<Symbol, Hanami::View::Part>] locals hash
# #
# @api public # @api public
attr_reader :locals attr_reader :locals
@ -34,7 +34,7 @@ module Dry
# #
# @param name [Symbol] local key # @param name [Symbol] local key
# #
# @return [Dry::View::Part] # @return [Hanami::View::Part]
# #
# @api public # @api public
def [](name) def [](name)

View File

@ -5,7 +5,7 @@ require "dry/equalizer"
require_relative "errors" require_relative "errors"
require_relative "tilt" require_relative "tilt"
module Dry module Hanami
class View class View
# @api private # @api private
class Renderer class Renderer

View File

@ -4,7 +4,7 @@ require "dry/equalizer"
require "dry/core/constants" require "dry/core/constants"
require_relative "render_environment_missing" require_relative "render_environment_missing"
module Dry module Hanami
class View class View
# Evaluation context for templates (including layouts and partials) and # Evaluation context for templates (including layouts and partials) and
# provides a place to encapsulate view-specific behaviour alongside a # provides a place to encapsulate view-specific behaviour alongside a

View File

@ -4,7 +4,7 @@ require "dry/core/cache"
require "dry/equalizer" require "dry/equalizer"
require_relative "scope" require_relative "scope"
module Dry module Hanami
class View class View
# Builds scope objects via matching classes # Builds scope objects via matching classes
# #
@ -43,7 +43,7 @@ module Dry
# @param name [Symbol, Class] scope name # @param name [Symbol, Class] scope name
# @param locals [Hash<Symbol, Object>] locals hash # @param locals [Hash<Symbol, Object>] locals hash
# #
# @return [Dry::View::Scope] # @return [Hanami::View::Scope]
# #
# @api private # @api private
def call(name = nil, locals) # rubocop:disable Style/OptionalArguments def call(name = nil, locals) # rubocop:disable Style/OptionalArguments

View File

@ -3,7 +3,7 @@
require "dry/core/cache" require "dry/core/cache"
require "tilt" require "tilt"
module Dry module Hanami
class View class View
# @api private # @api private
module Tilt module Tilt

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true # frozen_string_literal: true
module Dry module Hanami
class View class View
module Tilt module Tilt
module ERB module ERB
def self.requirements def self.requirements
["dry/view/tilt/erbse", <<~ERROR] ["hanami/view/tilt/erbse", <<~ERROR]
dry-view requires erbse for full compatibility when rendering .erb templates (e.g. implicitly capturing block content when yielding) hanami-view requires erbse for full compatibility when rendering .erb templates (e.g. implicitly capturing block content when yielding)
To ignore this and use another engine for .erb templates, deregister this adapter before calling your views: To ignore this and use another engine for .erb templates, deregister this adapter before calling your views:
Dry::View::Tilt.deregister_adapter(:erb) Hanami::View::Tilt.deregister_adapter(:erb)
ERROR ERROR
end end

View File

@ -3,7 +3,7 @@
require "tilt/template" require "tilt/template"
require "erbse" require "erbse"
module Dry module Hanami
class View class View
module Tilt module Tilt
# Tilt template class copied from cells-erb gem # Tilt template class copied from cells-erb gem

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true # frozen_string_literal: true
module Dry module Hanami
class View class View
module Tilt module Tilt
module Haml module Haml
def self.requirements def self.requirements
["hamlit/block", <<~ERROR] ["hamlit/block", <<~ERROR]
dry-view requires hamlit-block for full compatibility when rendering .haml templates (e.g. implicitly capturing block content when yielding) hanami-view requires hamlit-block for full compatibility when rendering .haml templates (e.g. implicitly capturing block content when yielding)
To ignore this and use another engine for .haml templates, dereigster this adapter before calling your views: To ignore this and use another engine for .haml templates, dereigster this adapter before calling your views:
Dry::View::Tilt.deregister_adatper(:haml) Hanami::View::Tilt.deregister_adatper(:haml)
ERROR ERROR
end end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
module Dry module Hanami
class View class View
# @api private # @api private
VERSION = "0.7.0" VERSION = "0.7.0"

View File

@ -1,4 +1,4 @@
name: dry-view name: hanami-view
codacy_id: fe8a45d76d8b45f6a680a29c48b43a99 codacy_id: fe8a45d76d8b45f6a680a29c48b43a99
gemspec: gemspec:
authors: ["Tim Riley", "Piotr Solnica"] authors: ["Tim Riley", "Piotr Solnica"]

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
require "dry/view/part" require "hanami/view/part"
RSpec.describe "Context" do RSpec.describe "Context" do
it "Provides decorated attributes for use in templates and parts" do it "Provides decorated attributes for use in templates and parts" do
@ -13,7 +13,7 @@ RSpec.describe "Context" do
end end
end end
class Context < Dry::View::Context class Context < Hanami::View::Context
attr_reader :assets attr_reader :assets
decorate :assets decorate :assets
@ -24,7 +24,7 @@ RSpec.describe "Context" do
end end
module Parts module Parts
class Assets < Dry::View::Part class Assets < Hanami::View::Part
def image_tag(path) def image_tag(path)
<<~HTML <<~HTML
<img src="#{value[path]}"> <img src="#{value[path]}">
@ -32,7 +32,7 @@ RSpec.describe "Context" do
end end
end end
class User < Dry::View::Part class User < Hanami::View::Part
def image_tag def image_tag
value[:image_url] || context.assets.image_tag("default.png") value[:image_url] || context.assets.image_tag("default.png")
end end
@ -40,7 +40,7 @@ RSpec.describe "Context" do
end end
end end
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/context") config.paths = FIXTURES_PATH.join("integration/context")
config.template = "decorated_attributes" config.template = "decorated_attributes"
config.part_namespace = Test::Parts config.part_namespace = Test::Parts

View File

@ -1,14 +1,14 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
require "dry/view/part" require "hanami/view/part"
RSpec.describe "exposures" do RSpec.describe "exposures" do
let(:context) { let(:context) {
Class.new(Dry::View::Context) do Class.new(Hanami::View::Context) do
def title def title
"dry-view rocks!" "hanami-view rocks!"
end end
def assets def assets
@ -18,7 +18,7 @@ RSpec.describe "exposures" do
} }
it "uses exposures with blocks to build view locals" do it "uses exposures with blocks to build view locals" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -37,12 +37,12 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
it "gives the exposure blocks access to the view instance" do it "gives the exposure blocks access to the view instance" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -68,12 +68,12 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>My friend Jane</td><td>jane@doe.org</td></tr><tr><td>My friend Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>My friend Jane</td><td>jane@doe.org</td></tr><tr><td>My friend Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
it "supports instance methods as exposures" do it "supports instance methods as exposures" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -96,12 +96,12 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
it "passes matching input data if no proc or instance method is available" do it "passes matching input data if no proc or instance method is available" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -116,12 +116,12 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
it "using default values" do it "using default values" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -131,12 +131,12 @@ RSpec.describe "exposures" do
end.new end.new
expect(view.(context: context).to_s).to eql( expect(view.(context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>John</td><td>john@william.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>John</td><td>john@william.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
it "having default values but passing nil as value for exposure" do it "having default values but passing nil as value for exposure" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "greeting" config.template = "greeting"
@ -146,12 +146,12 @@ RSpec.describe "exposures" do
end.new end.new
expect(view.(greeting: nil, context: context).to_s).to eql( expect(view.(greeting: nil, context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><p></p></body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><p></p></body></html>"
) )
end end
it "allows exposures to depend on each other" do it "allows exposures to depend on each other" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count" config.template = "users_with_count"
@ -170,20 +170,20 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>'
) )
end end
it "wraps exposures in view parts before they are supplied as dependencies" do it "wraps exposures in view parts before they are supplied as dependencies" do
module Test module Test
class UserPart < Dry::View::Part class UserPart < Hanami::View::Part
def display_name def display_name
"User: #{value[:name]}" "User: #{value[:name]}"
end end
end end
end end
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count" config.template = "users_with_count"
@ -207,17 +207,17 @@ RSpec.describe "exposures" do
rendered = view.(users: users, context: context) rendered = view.(users: users, context: context)
expect(rendered[:users]).to be_a(Dry::View::Part) expect(rendered[:users]).to be_a(Hanami::View::Part)
expect(rendered[:users][0]).to be_a(Test::UserPart) expect(rendered[:users][0]).to be_a(Test::UserPart)
expect(rendered[:users][0].value).to eq(name: "Jane", email: "jane@doe.org") expect(rendered[:users][0].value).to eq(name: "Jane", email: "jane@doe.org")
expect(rendered[:article]).to be_a(Dry::View::Part) expect(rendered[:article]).to be_a(Hanami::View::Part)
expect(rendered[:article].to_s).to eq "Great article from User: Jane" expect(rendered[:article].to_s).to eq "Great article from User: Jane"
end end
it "allows exposures to depend on each other while still using keywords args to access input data" do it "allows exposures to depend on each other while still using keywords args to access input data" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "greeting" config.template = "greeting"
@ -232,13 +232,13 @@ RSpec.describe "exposures" do
end end
end.new end.new
expect(view.(greeting: "From dry-view internals", context: context).to_s).to eql( expect(view.(greeting: "From hanami-view internals", context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><p>Hello From dry-view internals</p></body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><p>Hello From hanami-view internals</p></body></html>"
) )
end end
it "supports default values for keyword arguments" do it "supports default values for keyword arguments" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "greeting" config.template = "greeting"
@ -254,12 +254,12 @@ RSpec.describe "exposures" do
end.new end.new
expect(view.(context: context).to_s).to eql( expect(view.(context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><p>Hello From the defaults</p></body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><p>Hello From the defaults</p></body></html>"
) )
end end
it "only passes keywords arguments that are needed in the block and allows for default values" do it "only passes keywords arguments that are needed in the block and allows for default values" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "edit" config.template = "edit"
@ -275,12 +275,12 @@ RSpec.describe "exposures" do
end.new end.new
expect(view.(id: 1, context: context).to_s).to eql( expect(view.(id: 1, context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><h1>Edit</h1><p>No Errors</p><p>Beautiful 1</p></body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><h1>Edit</h1><p>No Errors</p><p>Beautiful 1</p></body></html>"
) )
end end
it "supports defining multiple exposures at once" do it "supports defining multiple exposures at once" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count" config.template = "users_with_count"
@ -301,12 +301,12 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, context: context).to_s).to eql( expect(view.(users: users, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>'
) )
end end
it "allows exposures to be hidden from the view" do it "allows exposures to be hidden from the view" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count" config.template = "users_with_count"
@ -331,7 +331,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context} input = {users: users, context: context}
expect(view.(**input).to_s).to eql( expect(view.(**input).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users</div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users</div></body></html>'
) )
expect(view.(**input).locals).to include(:users, :users_count) expect(view.(**input).locals).to include(:users, :users_count)
@ -339,7 +339,7 @@ RSpec.describe "exposures" do
end end
it "inherit exposures from parent class" do it "inherit exposures from parent class" do
parent = Class.new(Dry::View) do parent = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count_inherit" config.template = "users_with_count_inherit"
@ -370,7 +370,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context} input = {users: users, context: context}
expect(child.(**input).to_s).to eql( expect(child.(**input).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users</div><div class="inherit">Child expose</div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users</div><div class="inherit">Child expose</div></body></html>'
) )
expect(child.(**input).locals).to include(:users, :users_count, :child_expose) expect(child.(**input).locals).to include(:users, :users_count, :child_expose)
@ -378,7 +378,7 @@ RSpec.describe "exposures" do
end end
it "inherit exposures from parent class and allow to override them" do it "inherit exposures from parent class and allow to override them" do
parent = Class.new(Dry::View) do parent = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users_with_count_inherit" config.template = "users_with_count_inherit"
@ -413,7 +413,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context} input = {users: users, context: context}
expect(child.(**input).to_s).to eql( expect(child.(**input).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users overrided</div><div class="inherit">Child expose</div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users overrided</div><div class="inherit">Child expose</div></body></html>'
) )
expect(child.(**input).locals).to include(:users, :users_count, :child_expose) expect(child.(**input).locals).to include(:users, :users_count, :child_expose)
@ -421,7 +421,7 @@ RSpec.describe "exposures" do
end end
it "makes exposures available to layout" do it "makes exposures available to layout" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app_with_users" config.layout = "app_with_users"
config.template = "users" config.template = "users"
@ -438,7 +438,7 @@ RSpec.describe "exposures" do
] ]
expect(view.(users: users, users_count: users.size, context: context).to_s).to eql( expect(view.(users: users, users_count: users.size, context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><p>2 users</p><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><p>2 users</p><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/core/inflector" require "dry/core/inflector"
require "dry/view/scope_builder" require "hanami/view/scope_builder"
RSpec.describe "Part / Decorated attributes" do RSpec.describe "Part / Decorated attributes" do
let(:article_class) { let(:article_class) {
@ -60,30 +60,30 @@ RSpec.describe "Part / Decorated attributes" do
} }
let(:render_env) { let(:render_env) {
Dry::View::RenderEnvironment.new( Hanami::View::RenderEnvironment.new(
renderer: Dry::View::Renderer.new([Dry::View::Path.new(FIXTURES_PATH)], format: :html), renderer: Hanami::View::Renderer.new([Hanami::View::Path.new(FIXTURES_PATH)], format: :html),
inflector: Dry::Inflector.new, inflector: Dry::Inflector.new,
context: Dry::View::Context.new, context: Hanami::View::Context.new,
scope_builder: Dry::View::ScopeBuilder.new, scope_builder: Hanami::View::ScopeBuilder.new,
part_builder: part_builder part_builder: part_builder
) )
} }
describe "using default part builder" do describe "using default part builder" do
let(:part_builder) { Dry::View::PartBuilder.new } let(:part_builder) { Hanami::View::PartBuilder.new }
describe "decorating without options" do describe "decorating without options" do
describe "multiple declarations" do describe "multiple declarations" do
let(:article_part_class) { let(:article_part_class) {
Class.new(Dry::View::Part) do Class.new(Hanami::View::Part) do
decorate :author decorate :author
decorate :comments decorate :comments
end end
} }
it "decorates attributes with the standard Dry::View::Part class" do it "decorates attributes with the standard Hanami::View::Part class" do
expect(article_part.author).to be_a Dry::View::Part expect(article_part.author).to be_a Hanami::View::Part
expect(article_part.comments[0]).to be_a Dry::View::Part expect(article_part.comments[0]).to be_a Hanami::View::Part
end end
context "falsey values" do context "falsey values" do
@ -97,14 +97,14 @@ RSpec.describe "Part / Decorated attributes" do
describe "single declaration" do describe "single declaration" do
let(:article_part_class) { let(:article_part_class) {
Class.new(Dry::View::Part) do Class.new(Hanami::View::Part) do
decorate :author, :comments decorate :author, :comments
end end
} }
it "decorates attributes with the standard Dry::View::Part class" do it "decorates attributes with the standard Hanami::View::Part class" do
expect(article_part.author).to be_a Dry::View::Part expect(article_part.author).to be_a Hanami::View::Part
expect(article_part.comments[0]).to be_a Dry::View::Part expect(article_part.comments[0]).to be_a Hanami::View::Part
end end
context "falsey values" do context "falsey values" do
@ -120,16 +120,16 @@ RSpec.describe "Part / Decorated attributes" do
describe "decorating with part class specified" do describe "decorating with part class specified" do
before do before do
module Test module Test
class AuthorPart < Dry::View::Part class AuthorPart < Hanami::View::Part
end end
class CommentPart < Dry::View::Part class CommentPart < Hanami::View::Part
end end
end end
end end
let(:article_part_class) { let(:article_part_class) {
Class.new(Dry::View::Part) do Class.new(Hanami::View::Part) do
decorate :author, as: Test::AuthorPart decorate :author, as: Test::AuthorPart
decorate :comments, as: Test::CommentPart decorate :comments, as: Test::CommentPart
end end
@ -152,14 +152,14 @@ RSpec.describe "Part / Decorated attributes" do
describe "using custom part builder" do describe "using custom part builder" do
let(:article_part_class) { let(:article_part_class) {
Class.new(Dry::View::Part) do Class.new(Hanami::View::Part) do
decorate :author decorate :author
decorate :comments decorate :comments
end end
} }
let(:part_builder) { let(:part_builder) {
Class.new(Dry::View::PartBuilder) do Class.new(Hanami::View::PartBuilder) do
def part_class(name:, **options) def part_class(name:, **options)
part_name = Dry::Core::Inflector.camelize(name) part_name = Dry::Core::Inflector.camelize(name)
@ -174,10 +174,10 @@ RSpec.describe "Part / Decorated attributes" do
before do before do
module Test module Test
class AuthorPart < Dry::View::Part class AuthorPart < Hanami::View::Part
end end
class CommentPart < Dry::View::Part class CommentPart < Hanami::View::Part
decorate :author decorate :author
end end
end end

View File

@ -3,7 +3,7 @@
RSpec.describe "part builder" do RSpec.describe "part builder" do
before do before do
module Test module Test
class Custom < Dry::View::Part class Custom < Hanami::View::Part
def to_s def to_s
"Custom part wrapping #{_value}" "Custom part wrapping #{_value}"
end end
@ -11,7 +11,7 @@ RSpec.describe "part builder" do
CustomPart = Custom CustomPart = Custom
class CustomArrayPart < Dry::View::Part class CustomArrayPart < Hanami::View::Part
def each(&block) def each(&block)
(_value * 2).each(&block) (_value * 2).each(&block)
end end
@ -21,7 +21,7 @@ RSpec.describe "part builder" do
describe "default decorator" do describe "default decorator" do
it "looks up classes from a part namespace" do it "looks up classes from a part namespace" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil config.layout = nil
config.template = "decorated_parts" config.template = "decorated_parts"
@ -38,7 +38,7 @@ RSpec.describe "part builder" do
end end
it "supports wrapping array memebers in custom part classes provided to exposure :as option" do it "supports wrapping array memebers in custom part classes provided to exposure :as option" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil config.layout = nil
config.template = "decorated_parts" config.template = "decorated_parts"
@ -54,7 +54,7 @@ RSpec.describe "part builder" do
end end
it "supports wrapping an array and its members in custom part classes provided to exposure :as option as a hash" do it "supports wrapping an array and its members in custom part classes provided to exposure :as option as a hash" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil config.layout = nil
config.template = "decorated_parts" config.template = "decorated_parts"
@ -72,13 +72,13 @@ RSpec.describe "part builder" do
describe "custom decorator and part classes" do describe "custom decorator and part classes" do
it "supports wrapping in custom parts based on exposure names" do it "supports wrapping in custom parts based on exposure names" do
part_builder = Class.new(Dry::View::PartBuilder) do part_builder = Class.new(Hanami::View::PartBuilder) do
def part_class(name:, **options) def part_class(name:, **options)
name == :custom ? Test::CustomPart : super name == :custom ? Test::CustomPart : super
end end
end end
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.part_builder = part_builder config.part_builder = part_builder
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil config.layout = nil

View File

@ -1,18 +1,18 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/part" require "hanami/view/part"
require "dry/view/scope" require "hanami/view/scope"
RSpec.describe "Scopes" do RSpec.describe "Scopes" do
let(:base_view) { let(:base_view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/scopes") config.paths = FIXTURES_PATH.join("integration/scopes")
end end
} }
specify "Custom scope for a view" do specify "Custom scope for a view" do
module Test module Test
class ControllerScope < Dry::View::Scope class ControllerScope < Hanami::View::Scope
def hello def hello
"Hello #{_locals[:text]}!" "Hello #{_locals[:text]}!"
end end
@ -41,7 +41,7 @@ RSpec.describe "Scopes" do
specify "Rendering a partial implicitly via a custom named scope" do specify "Rendering a partial implicitly via a custom named scope" do
module Test::Scopes module Test::Scopes
class Greeting < Dry::View::Scope class Greeting < Hanami::View::Scope
def greeting def greeting
_locals[:greeting].upcase + "!" _locals[:greeting].upcase + "!"
end end
@ -60,7 +60,7 @@ RSpec.describe "Scopes" do
specify "Rendering a partial implicitly via a custom named scope (provided via a class)" do specify "Rendering a partial implicitly via a custom named scope (provided via a class)" do
module Test::Scopes module Test::Scopes
class Greeting < Dry::View::Scope class Greeting < Hanami::View::Scope
def greeting def greeting
_locals[:greeting].upcase + "!" _locals[:greeting].upcase + "!"
end end
@ -87,7 +87,7 @@ RSpec.describe "Scopes" do
specify "Rendering a partial explicitly via a custom named scope" do specify "Rendering a partial explicitly via a custom named scope" do
module Test::Scopes module Test::Scopes
class Greeting < Dry::View::Scope class Greeting < Hanami::View::Scope
def greeting def greeting
_locals[:greeting].upcase + "!" _locals[:greeting].upcase + "!"
end end
@ -106,7 +106,7 @@ RSpec.describe "Scopes" do
specify "Custom named scope providing defaults for missing locals" do specify "Custom named scope providing defaults for missing locals" do
module Test::Scopes module Test::Scopes
class Greeting < Dry::View::Scope class Greeting < Hanami::View::Scope
def greeting def greeting
_locals.fetch(:greeting) { "Howdy" } _locals.fetch(:greeting) { "Howdy" }
end end
@ -125,7 +125,7 @@ RSpec.describe "Scopes" do
specify "Creating a custom scope from a view part" do specify "Creating a custom scope from a view part" do
module Test::Parts module Test::Parts
class Message < Dry::View::Part class Message < Hanami::View::Part
def greeting def greeting
scope(:greeting, greeting: value[:text]).render scope(:greeting, greeting: value[:text]).render
end end
@ -133,7 +133,7 @@ RSpec.describe "Scopes" do
end end
module Test::Scopes module Test::Scopes
class Greeting < Dry::View::Scope class Greeting < Hanami::View::Scope
def greeting def greeting
_locals[:greeting] + "!" _locals[:greeting] + "!"
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "Template engines / erb (using erbse as default engine)" do RSpec.describe "Template engines / erb (using erbse as default engine)" do
let(:base_view) { let(:base_view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/template_engines/erbse") config.paths = FIXTURES_PATH.join("integration/template_engines/erbse")
end end
} }
@ -20,7 +20,7 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
end end
it "supports context methods that yield" do it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do context = Class.new(Hanami::View::Context) do
def wrapper def wrapper
"<wrapper>#{yield}</wrapper>" "<wrapper>#{yield}</wrapper>"
end end
@ -41,16 +41,16 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
@loaded_features = $LOADED_FEATURES.dup @loaded_features = $LOADED_FEATURES.dup
$LOAD_PATH.reject! { |path| path =~ /erbse/ } $LOAD_PATH.reject! { |path| path =~ /erbse/ }
$LOADED_FEATURES.reject! { |path| path =~ %r{erbse|dry/view/tilt/erbse} } $LOADED_FEATURES.reject! { |path| path =~ %r{erbse|hanami/view/tilt/erbse} }
Dry::View::Tilt.cache.clear Hanami::View::Tilt.cache.clear
Dry::View::Renderer.cache.clear Hanami::View::Renderer.cache.clear
end end
after do after do
$LOAD_PATH.replace @load_path $LOAD_PATH.replace @load_path
$LOADED_FEATURES.replace @loaded_features $LOADED_FEATURES.replace @loaded_features
Dry::View::Tilt.register_adapter :erb, Dry::View::Tilt::ERB Hanami::View::Tilt.register_adapter :erb, Hanami::View::Tilt::ERB
end end
it "raises an error explaining the erbse requirement" do it "raises an error explaining the erbse requirement" do
@ -58,7 +58,7 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
config.template = "render_and_yield" config.template = "render_and_yield"
end.new end.new
expect { view.() }.to raise_error(LoadError, /dry-view requires erbse/m) expect { view.() }.to raise_error(LoadError, /hanami-view requires erbse/m)
end end
it "allows deregistering the adapter to avoid the load error and accept rendering via a less-compatible erb engine" do it "allows deregistering the adapter to avoid the load error and accept rendering via a less-compatible erb engine" do
@ -66,7 +66,7 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
config.template = "plain_erb" config.template = "plain_erb"
end.new end.new
Dry::View::Tilt.deregister_adapter :erb Hanami::View::Tilt.deregister_adapter :erb
expect { view.() }.not_to raise_error expect { view.() }.not_to raise_error
expect(view.().to_s.strip).to eq "Hello" expect(view.().to_s.strip).to eq "Hello"

View File

@ -4,12 +4,12 @@ require "erubi"
require "erubi/capture_end" require "erubi/capture_end"
require "tilt/erubi" require "tilt/erubi"
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "Template engines / erb (using erubi via an explict engine mapping)" do RSpec.describe "Template engines / erb (using erubi via an explict engine mapping)" do
let(:base_view) { let(:base_view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/template_engines/erubi") config.paths = FIXTURES_PATH.join("integration/template_engines/erubi")
config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate} config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate}
config.renderer_options = {engine_class: Erubi::CaptureEndEngine} config.renderer_options = {engine_class: Erubi::CaptureEndEngine}
@ -25,7 +25,7 @@ RSpec.describe "Template engines / erb (using erubi via an explict engine mappin
end end
it "supports context methods that yield" do it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do context = Class.new(Hanami::View::Context) do
def wrapper def wrapper
"<wrapper>#{yield}</wrapper>" "<wrapper>#{yield}</wrapper>"
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "Template engines / haml (using hamlit-block as default engine)" do RSpec.describe "Template engines / haml (using hamlit-block as default engine)" do
let(:base_view) { let(:base_view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/template_engines/hamlit") config.paths = FIXTURES_PATH.join("integration/template_engines/hamlit")
end end
} }
@ -20,7 +20,7 @@ RSpec.describe "Template engines / haml (using hamlit-block as default engine)"
end end
it "supports methods that yield" do it "supports methods that yield" do
context = Class.new(Dry::View::Context) do context = Class.new(Hanami::View::Context) do
def wrapper def wrapper
"<wrapper>#{yield}</wrapper>" "<wrapper>#{yield}</wrapper>"
end end
@ -43,8 +43,8 @@ RSpec.describe "Template engines / haml (using hamlit-block as default engine)"
$LOAD_PATH.reject! { |path| path =~ /hamlit-block/ } $LOAD_PATH.reject! { |path| path =~ /hamlit-block/ }
$LOADED_FEATURES.reject! { |path| path =~ /hamlit-block/ } $LOADED_FEATURES.reject! { |path| path =~ /hamlit-block/ }
Dry::View::Tilt.cache.clear Hanami::View::Tilt.cache.clear
Dry::View::Renderer.cache.clear Hanami::View::Renderer.cache.clear
end end
after do after do
@ -57,7 +57,7 @@ RSpec.describe "Template engines / haml (using hamlit-block as default engine)"
config.template = "render_and_yield" config.template = "render_and_yield"
end.new end.new
expect { view.() }.to raise_error(LoadError, /dry-view requires hamlit-block/m) expect { view.() }.to raise_error(LoadError, /hanami-view requires hamlit-block/m)
end end
end end
end end

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
require "slim" require "slim"
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "Template engines / slim" do RSpec.describe "Template engines / slim" do
let(:base_view) { let(:base_view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/template_engines/slim") config.paths = FIXTURES_PATH.join("integration/template_engines/slim")
end end
} }
@ -20,7 +20,7 @@ RSpec.describe "Template engines / slim" do
end end
it "supports context methods that yield" do it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do context = Class.new(Hanami::View::Context) do
def wrapper def wrapper
"<wrapper>#{yield}</wrapper>" "<wrapper>#{yield}</wrapper>"
end end

View File

@ -2,12 +2,12 @@
RSpec.describe "Testing / parts" do RSpec.describe "Testing / parts" do
let(:part_class) { let(:part_class) {
Class.new(Dry::View::Part) do Class.new(Hanami::View::Part) do
end end
} }
specify "Parts can be unit tested without name or rendering (for testing methods that don't require them)" do specify "Parts can be unit tested without name or rendering (for testing methods that don't require them)" do
part_class = Class.new(Dry::View::Part) do part_class = Class.new(Hanami::View::Part) do
def breaking_news_title def breaking_news_title
title + "!" title + "!"
end end
@ -21,12 +21,12 @@ RSpec.describe "Testing / parts" do
end end
specify "Parts can be unit tested with a rendering from a view class" do specify "Parts can be unit tested with a rendering from a view class" do
view_class = Class.new(Dry::View) do view_class = Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/testing") config.paths = FIXTURES_PATH.join("integration/testing")
config.template = "view" config.template = "view"
end end
part_class = Class.new(Dry::View::Part) do part_class = Class.new(Hanami::View::Part) do
def feature_box def feature_box
render(:feature_box) render(:feature_box)
end end

View File

@ -1,22 +1,22 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "View / errors" do RSpec.describe "View / errors" do
specify "Raising an error when paths are not configured" do specify "Raising an error when paths are not configured" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.template = "hello" config.template = "hello"
end.new end.new
expect { view.() }.to raise_error(Dry::View::UndefinedConfigError, "no +paths+ configured") expect { view.() }.to raise_error(Hanami::View::UndefinedConfigError, "no +paths+ configured")
end end
specify "Raising an error when template is not configured" do specify "Raising an error when template is not configured" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/errors") config.paths = FIXTURES_PATH.join("integration/errors")
end.new end.new
expect { view.() }.to raise_error(Dry::View::UndefinedConfigError, "no +template+ configured") expect { view.() }.to raise_error(Hanami::View::UndefinedConfigError, "no +template+ configured")
end end
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/context" require "hanami/view/context"
RSpec.describe "View / exposures" do RSpec.describe "View / exposures" do
specify "exposures have access to context" do specify "exposures have access to context" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting" config.template = "greeting"
@ -14,7 +14,7 @@ RSpec.describe "View / exposures" do
end end
end.new end.new
context = Class.new(Dry::View::Context) do context = Class.new(Hanami::View::Context) do
def name def name
"Jane" "Jane"
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view" require "hanami/view"
require "dry/view/part" require "hanami/view/part"
RSpec.describe "View / locals" do RSpec.describe "View / locals" do
specify "locals are decorated with parts by default" do specify "locals are decorated with parts by default" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting" config.template = "greeting"
@ -14,11 +14,11 @@ RSpec.describe "View / locals" do
local = view.(greeting: "Hello").locals[:greeting] local = view.(greeting: "Hello").locals[:greeting]
expect(local).to be_a(Dry::View::Part) expect(local).to be_a(Hanami::View::Part)
end end
specify "locals are not decorated if their exposure is marked as `decorate: false`" do specify "locals are not decorated if their exposure is marked as `decorate: false`" do
view = Class.new(Dry::View) do view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting" config.template = "greeting"

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "dry-view" do RSpec.describe "hanami-view" do
let(:view_class) do let(:view_class) do
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "users" config.template = "users"
@ -18,9 +18,9 @@ RSpec.describe "dry-view" do
end end
let(:context) { let(:context) {
Class.new(Dry::View::Context) do Class.new(Hanami::View::Context) do
def title def title
"dry-view rocks!" "hanami-view rocks!"
end end
def assets def assets
@ -33,7 +33,7 @@ RSpec.describe "dry-view" do
view = view_class.new view = view_class.new
expect(view.(context: context).to_s).to eql( expect(view.(context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
) )
end end
@ -51,7 +51,7 @@ RSpec.describe "dry-view" do
view = view_class.new view = view_class.new
expect(view.(context: context, format: "txt").to_s.strip).to eql( expect(view.(context: context, format: "txt").to_s.strip).to eql(
"# dry-view rocks!\n\n\n* Jane (jane@doe.org)\n\n* Joe (joe@doe.org)" "# hanami-view rocks!\n\n\n* Jane (jane@doe.org)\n\n* Joe (joe@doe.org)"
) )
end end
@ -61,7 +61,7 @@ RSpec.describe "dry-view" do
end.new end.new
expect(view.(context: context).to_s).to eq( expect(view.(context: context).to_s).to eq(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><h1>OVERRIDE</h1><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><h1>OVERRIDE</h1><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div></body></html>'
) )
end end
@ -71,7 +71,7 @@ RSpec.describe "dry-view" do
end.new end.new
expect(view.(context: context).to_s).to eq( expect(view.(context: context).to_s).to eq(
'<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><div class="box"><h2>Nombre</h2>Jane</div><div class="box"><h2>Nombre</h2>Joe</div></div></body></html>' '<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><div class="users"><div class="box"><h2>Nombre</h2>Jane</div><div class="box"><h2>Nombre</h2>Joe</div></div></body></html>'
) )
end end
@ -81,13 +81,13 @@ RSpec.describe "dry-view" do
end.new end.new
expect(view.(context: context).to_s).to eq( expect(view.(context: context).to_s).to eq(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body>ç</body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body>ç</body></html>"
) )
end end
describe "inheritance" do describe "inheritance" do
let(:parent_view) do let(:parent_view) do
klass = Class.new(Dry::View) klass = Class.new(Hanami::View)
klass.setting :paths, SPEC_ROOT.join("fixtures/templates") klass.setting :paths, SPEC_ROOT.join("fixtures/templates")
klass.setting :layout, "app" klass.setting :layout, "app"
@ -115,7 +115,7 @@ RSpec.describe "dry-view" do
end.new end.new
expect(view.(context: context).to_s).to eql( expect(view.(context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ol><li>one</li><li>two</li></ol></body></html>" "<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><ol><li>one</li><li>two</li></ol></body></html>"
) )
end end
end end

View File

@ -9,7 +9,7 @@ SPEC_ROOT = Pathname(__FILE__).dirname
FIXTURES_PATH = SPEC_ROOT.join("fixtures") FIXTURES_PATH = SPEC_ROOT.join("fixtures")
require "slim" require "slim"
require "dry/view" require "hanami/view"
module Test module Test
def self.remove_constants def self.remove_constants
@ -29,12 +29,12 @@ RSpec.configure do |config|
config.after do config.after do
[ [
Dry::View, Hanami::View,
Dry::View::PartBuilder, Hanami::View::PartBuilder,
Dry::View::Path, Hanami::View::Path,
Dry::View::Renderer, Hanami::View::Renderer,
Dry::View::ScopeBuilder, Hanami::View::ScopeBuilder,
Dry::View::Tilt Hanami::View::Tilt
].each do |klass| ].each do |klass|
klass.cache.clear klass.cache.clear
end end

View File

@ -1,13 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/context" require "hanami/view/context"
require "dry/view/part" require "hanami/view/part"
require "dry/view/part_builder" require "hanami/view/part_builder"
require "dry/view/scope_builder" require "hanami/view/scope_builder"
RSpec.describe Dry::View::Context do RSpec.describe Hanami::View::Context do
let(:context_class) { let(:context_class) {
Class.new(Dry::View::Context) do Class.new(Hanami::View::Context) do
attr_reader :assets, :routes attr_reader :assets, :routes
decorate :assets, :routes decorate :assets, :routes
@ -25,12 +25,12 @@ RSpec.describe Dry::View::Context do
let(:routes) { double(:routes) } let(:routes) { double(:routes) }
let(:render_env) { let(:render_env) {
Dry::View::RenderEnvironment.new( Hanami::View::RenderEnvironment.new(
inflector: Dry::Inflector.new, inflector: Dry::Inflector.new,
renderer: double(:renderer), renderer: double(:renderer),
context: Dry::View::Context.new, context: Hanami::View::Context.new,
part_builder: Dry::View::PartBuilder.new, part_builder: Hanami::View::PartBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new scope_builder: Hanami::View::ScopeBuilder.new
) )
} }
@ -49,7 +49,7 @@ RSpec.describe Dry::View::Context do
describe "attribute readers" do describe "attribute readers" do
it "provides attributes decorated in view parts" do it "provides attributes decorated in view parts" do
expect(context.assets).to be_a Dry::View::Part expect(context.assets).to be_a Hanami::View::Part
expect(context.assets.value).to eql assets expect(context.assets.value).to eql assets
end end
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/decorated_attributes" require "hanami/view/decorated_attributes"
RSpec.describe Dry::View::DecoratedAttributes do RSpec.describe Hanami::View::DecoratedAttributes do
subject(:decoratable) { subject(:decoratable) {
Test::Decoratable = Struct.new(:attr_1, :attr_2, :_render_env) do Test::Decoratable = Struct.new(:attr_1, :attr_2, :_render_env) do
include Dry::View::DecoratedAttributes include Hanami::View::DecoratedAttributes
decorate :attr_1, as: :my_value decorate :attr_1, as: :my_value
decorate :attr_2 decorate :attr_2
@ -51,6 +51,6 @@ RSpec.describe Dry::View::DecoratedAttributes do
it "prepends a single module to provide the decorated attribute readers" do it "prepends a single module to provide the decorated attribute readers" do
expect(decoratable.class.ancestors.map(&:name).grep(/Test::Decoratable::DecoratedAttributes/).length).to eq 1 expect(decoratable.class.ancestors.map(&:name).grep(/Test::Decoratable::DecoratedAttributes/).length).to eq 1
expect(decoratable.class.ancestors[0].inspect).to eq "#<Dry::View::DecoratedAttributes::Attributes[:attr_1, :attr_2, :invalid_attr]>" expect(decoratable.class.ancestors[0].inspect).to eq "#<Hanami::View::DecoratedAttributes::Attributes[:attr_1, :attr_2, :invalid_attr]>"
end end
end end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Dry::View::Exposure do RSpec.describe Hanami::View::Exposure do
subject(:exposure) { described_class.new(:hello, proc, object, **options) } subject(:exposure) { described_class.new(:hello, proc, object, **options) }
let(:proc) { -> _input { "hi" } } let(:proc) { -> _input { "hi" } }

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Dry::View::Exposures do RSpec.describe Hanami::View::Exposures do
subject(:exposures) { described_class.new } subject(:exposures) { described_class.new }
describe "#exposures" do describe "#exposures" do

View File

@ -1,17 +1,17 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/scope_builder" require "hanami/view/scope_builder"
RSpec.describe Dry::View::PartBuilder do RSpec.describe Hanami::View::PartBuilder do
subject(:part_builder) { render_env.part_builder } subject(:part_builder) { render_env.part_builder }
let(:render_env) { let(:render_env) {
Dry::View::RenderEnvironment.new( Hanami::View::RenderEnvironment.new(
renderer: Dry::View::Renderer.new([FIXTURES_PATH], format: :html), renderer: Hanami::View::Renderer.new([FIXTURES_PATH], format: :html),
inflector: Dry::Inflector.new, inflector: Dry::Inflector.new,
context: Dry::View::Context.new, context: Hanami::View::Context.new,
scope_builder: Dry::View::ScopeBuilder.new, scope_builder: Hanami::View::ScopeBuilder.new,
part_builder: Dry::View::PartBuilder.new(namespace: namespace) part_builder: Hanami::View::PartBuilder.new(namespace: namespace)
) )
} }
@ -27,7 +27,7 @@ RSpec.describe Dry::View::PartBuilder do
let(:options) { {} } let(:options) { {} }
shared_examples "a view part" do shared_examples "a view part" do
let(:part_class) { Dry::View::Part } let(:part_class) { Hanami::View::Part }
it "returns a part" do it "returns a part" do
expect(part).to be_a part_class expect(part).to be_a part_class
@ -43,8 +43,8 @@ RSpec.describe Dry::View::PartBuilder do
end end
shared_examples "a view part collection" do shared_examples "a view part collection" do
let(:collection_part_class) { Dry::View::Part } let(:collection_part_class) { Hanami::View::Part }
let(:item_part_class) { Dry::View::Part } let(:item_part_class) { Hanami::View::Part }
it "returns a part wrapping the collection" do it "returns a part wrapping the collection" do
expect(part).to be_a collection_part_class expect(part).to be_a collection_part_class
@ -75,7 +75,7 @@ RSpec.describe Dry::View::PartBuilder do
describe "explicit part class provided via as: option" do describe "explicit part class provided via as: option" do
before do before do
Test::UserPart = Class.new(Dry::View::Part) Test::UserPart = Class.new(Hanami::View::Part)
end end
let(:options) { {as: Test::UserPart} } let(:options) { {as: Test::UserPart} }
@ -100,7 +100,7 @@ RSpec.describe Dry::View::PartBuilder do
describe "explicit part class provided via as: option" do describe "explicit part class provided via as: option" do
before do before do
Test::UserPart = Class.new(Dry::View::Part) Test::UserPart = Class.new(Hanami::View::Part)
end end
let(:options) { {as: Test::UserPart} } let(:options) { {as: Test::UserPart} }
@ -112,7 +112,7 @@ RSpec.describe Dry::View::PartBuilder do
describe "explicit collection part class provided via as: option" do describe "explicit collection part class provided via as: option" do
before do before do
Test::UserCollectionPart = Class.new(Dry::View::Part) Test::UserCollectionPart = Class.new(Hanami::View::Part)
end end
let(:options) { {as: [Test::UserCollectionPart]} } let(:options) { {as: [Test::UserCollectionPart]} }
@ -128,23 +128,23 @@ RSpec.describe Dry::View::PartBuilder do
before do before do
module Test module Test
module Parts module Parts
class Users < Dry::View::Part class Users < Hanami::View::Part
end end
class UserCollection < Dry::View::Part class UserCollection < Hanami::View::Part
end end
class User < Dry::View::Part class User < Hanami::View::Part
decorate :profile decorate :profile
end end
class AdminUser < Dry::View::Part class AdminUser < Hanami::View::Part
end end
module UserModule module UserModule
end end
class Profile < Dry::View::Part class Profile < Hanami::View::Part
end end
end end
end end
@ -171,11 +171,11 @@ RSpec.describe Dry::View::PartBuilder do
end end
end end
describe "alternative name provided via :as option, when matched constant is not a class inheriting from Dry::View::Part" do describe "alternative name provided via :as option, when matched constant is not a class inheriting from Hanami::View::Part" do
let(:options) { {as: :user_module} } let(:options) { {as: :user_module} }
it_behaves_like "a view part" do it_behaves_like "a view part" do
let(:part_class) { Dry::View::Part } let(:part_class) { Hanami::View::Part }
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/scope_builder" require "hanami/view/scope_builder"
require "dry/view/render_environment_missing" require "hanami/view/render_environment_missing"
RSpec::Matchers.define :scope do |locals| RSpec::Matchers.define :scope do |locals|
match do |actual| match do |actual|
@ -9,16 +9,16 @@ RSpec::Matchers.define :scope do |locals|
end end
end end
RSpec.describe Dry::View::Part do RSpec.describe Hanami::View::Part do
let(:name) { :user } let(:name) { :user }
let(:value) { double(:value) } let(:value) { double(:value) }
let(:render_env) { let(:render_env) {
Dry::View::RenderEnvironment.new( Hanami::View::RenderEnvironment.new(
renderer: renderer, renderer: renderer,
inflector: Dry::Inflector.new, inflector: Dry::Inflector.new,
context: Dry::View::Context.new, context: Hanami::View::Context.new,
scope_builder: Dry::View::ScopeBuilder.new, scope_builder: Hanami::View::ScopeBuilder.new,
part_builder: Dry::View::ScopeBuilder.new part_builder: Hanami::View::ScopeBuilder.new
) )
} }
let(:renderer) { spy(:renderer, format: :xml) } let(:renderer) { spy(:renderer, format: :xml) }
@ -68,7 +68,7 @@ RSpec.describe Dry::View::Part do
describe "#inspect" do describe "#inspect" do
it "includes the clsas name, name, and value only" do it "includes the clsas name, name, and value only" do
expect(part.inspect).to eq "#<Dry::View::Part name=:user value=#<Double :value>>" expect(part.inspect).to eq "#<Hanami::View::Part name=:user value=#<Double :value>>"
end end
end end
@ -124,19 +124,19 @@ RSpec.describe Dry::View::Part do
describe "#format" do describe "#format" do
it "raises an error" do it "raises an error" do
expect { part.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { part.render(:info) }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
describe "#render" do describe "#render" do
it "raises an error" do it "raises an error" do
expect { part.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { part.render(:info) }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
describe "#scope" do describe "#scope" do
it "raises an error" do it "raises an error" do
expect { part.scope(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { part.scope(:info) }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
end end
@ -145,7 +145,7 @@ RSpec.describe Dry::View::Part do
describe "#_name" do describe "#_name" do
context "when class has a name" do context "when class has a name" do
before do before do
Test::MyPart = Class.new(Dry::View::Part) Test::MyPart = Class.new(Hanami::View::Part)
end end
subject(:part) { subject(:part) {
@ -159,7 +159,7 @@ RSpec.describe Dry::View::Part do
context "when class is anonymous" do context "when class is anonymous" do
subject(:part) { subject(:part) {
Class.new(Dry::View::Part).new(value: value) Class.new(Hanami::View::Part).new(value: value)
} }
it "defaults to 'part'" do it "defaults to 'part'" do

View File

@ -1,22 +1,22 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/render_environment" require "hanami/view/render_environment"
require "dry/inflector" require "dry/inflector"
require "dry/view/context" require "hanami/view/context"
require "dry/view/part_builder" require "hanami/view/part_builder"
require "dry/view/scope_builder" require "hanami/view/scope_builder"
RSpec.describe Dry::View::RenderEnvironment do RSpec.describe Hanami::View::RenderEnvironment do
subject(:render_env) { described_class.new(**options) } subject(:render_env) { described_class.new(**options) }
let(:options) { let(:options) {
{ {
inflector: Dry::Inflector.new, inflector: Dry::Inflector.new,
renderer: Dry::View::Renderer.new([Dry::View::Path.new(FIXTURES_PATH)], format: :html), renderer: Hanami::View::Renderer.new([Hanami::View::Path.new(FIXTURES_PATH)], format: :html),
context: Dry::View::Context.new, context: Hanami::View::Context.new,
part_builder: Dry::View::PartBuilder.new, part_builder: Hanami::View::PartBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new scope_builder: Hanami::View::ScopeBuilder.new
} }
} }

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/rendered" require "hanami/view/rendered"
RSpec.describe Dry::View::Rendered do RSpec.describe Hanami::View::Rendered do
subject(:rendered) { subject(:rendered) {
described_class.new( described_class.new(
output: "rendered template output", output: "rendered template output",

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/path" require "hanami/view/path"
require "dry/view/renderer" require "hanami/view/renderer"
RSpec.describe Dry::View::Renderer do RSpec.describe Hanami::View::Renderer do
subject(:renderer) do subject(:renderer) do
Dry::View::Renderer.new( Hanami::View::Renderer.new(
[Dry::View::Path.new(SPEC_ROOT.join("fixtures/templates"))], [Hanami::View::Path.new(SPEC_ROOT.join("fixtures/templates"))],
format: "html", format: "html",
default_encoding: "utf-8" default_encoding: "utf-8"
) )
@ -22,13 +22,13 @@ RSpec.describe Dry::View::Renderer do
it "does not include `shared/` subdirectory under root when looking up templates" do it "does not include `shared/` subdirectory under root when looking up templates" do
expect { expect {
renderer.template(:_shared_hello, scope) renderer.template(:_shared_hello, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_shared_hello/) }.to raise_error(Hanami::View::TemplateNotFoundError, /_shared_hello/)
end end
it "raises error when template cannot be found" do it "raises error when template cannot be found" do
expect { expect {
renderer.template(:missing_template, scope) renderer.template(:missing_template, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /missing_template/) }.to raise_error(Hanami::View::TemplateNotFoundError, /missing_template/)
end end
end end
@ -56,7 +56,7 @@ RSpec.describe Dry::View::Renderer do
it "raises error when partial cannot be found" do it "raises error when partial cannot be found" do
expect { expect {
renderer.partial(:missing_partial, scope) renderer.partial(:missing_partial, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_missing_partial/) }.to raise_error(Hanami::View::TemplateNotFoundError, /_missing_partial/)
end end
end end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "dry/view/scope_builder" require "hanami/view/scope_builder"
RSpec.describe Dry::View::Scope do RSpec.describe Hanami::View::Scope do
let(:locals) { {} } let(:locals) { {} }
context "with a render environment" do context "with a render environment" do
@ -96,19 +96,19 @@ RSpec.describe Dry::View::Scope do
describe "#render" do describe "#render" do
it "raises an error" do it "raises an error" do
expect { scope.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { scope.render(:info) }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
describe "#scope" do describe "#scope" do
it "raises an error" do it "raises an error" do
expect { scope.scope(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { scope.scope(:info) }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
describe "#_context" do describe "#_context" do
it "raises an error" do it "raises an error" do
expect { scope._context }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError) expect { scope._context }.to raise_error(Hanami::View::RenderEnvironmentMissing::MissingEnvironmentError)
end end
end end
end end

View File

@ -2,9 +2,9 @@
require "tilt/erubi" require "tilt/erubi"
RSpec.describe Dry::View do RSpec.describe Hanami::View do
subject(:view) { subject(:view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app" config.layout = "app"
config.template = "user" config.template = "user"
@ -20,7 +20,7 @@ RSpec.describe Dry::View do
} }
let(:context) do let(:context) do
Class.new(Dry::View::Context) do Class.new(Hanami::View::Context) do
def title def title
"Test" "Test"
end end
@ -37,7 +37,7 @@ RSpec.describe Dry::View do
describe "renderer options" do describe "renderer options" do
subject(:view) { subject(:view) {
Class.new(Dry::View) do Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates") config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "view_renderer_options" config.template = "view_renderer_options"
config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate} config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate}
@ -64,7 +64,7 @@ RSpec.describe Dry::View do
end end
subject(:context) { subject(:context) {
Class.new(Dry::View::Context) do Class.new(Hanami::View::Context) do
def form(action:, &blk) def form(action:, &blk)
Test::Form.new(action, &blk) Test::Form.new(action, &blk)
end end