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:
TargetRubyVersion: 2.4
Exclude:

View File

@ -1,21 +1,21 @@
[gem]: https://rubygems.org/gems/dry-view
[actions]: https://github.com/dry-rb/dry-view/actions
[codacy]: https://www.codacy.com/gh/dry-rb/dry-view
[gem]: https://rubygems.org/gems/hanami-view
[actions]: https://github.com/hanami/view/actions
[codacy]: https://www.codacy.com/gh/hanami/view
[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]
[![CI Status](https://github.com/dry-rb/dry-view/workflows/ci/badge.svg)][actions]
[![Gem Version](https://badge.fury.io/rb/hanami-view.svg)][gem]
[![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/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
* [User documentation](http://dry-rb.org/gems/dry-view)
* [API documentation](http://rubydoc.info/gems/dry-view)
* [User documentation](http://dry-rb.org/gems/hanami-view)
* [API documentation](http://rubydoc.info/gems/hanami-view)
## Supported Ruby versions

View File

@ -3,7 +3,7 @@
require "pathname"
require "ostruct"
require "benchmark/ips"
require "dry/view"
require "hanami/view"
require "action_view"
require "action_controller"
@ -29,7 +29,7 @@ class UsersController < ActionController::Base
end
end
class DryView < Dry::View
class HanamiView < Hanami::View
config.paths = TEMPLATES_PATHS
config.layout = "app"
config.template = "users"
@ -39,16 +39,16 @@ class DryView < Dry::View
end
action_controller = UsersController.new
dry_view = DryView.new
hanami_view = HanamiView.new
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
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
Benchmark.ips do |x|
@ -56,8 +56,8 @@ Benchmark.ips do |x|
1000.times { action_controller.index }
end
x.report("dry-view") do
1000.times { dry_view.(TEMPLATE_LOCALS).to_s }
x.report("hanami-view") do
1000.times { hanami_view.(TEMPLATE_LOCALS).to_s }
end
x.compare!

View File

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

View File

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

View File

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

View File

@ -1,13 +1,13 @@
---
title: Configuration
layout: gem-single
name: dry-view
name: hanami-view
---
You can configure your views via class-level `config`. Basic configuration looks like this:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.paths = [File.join(__dir__, "templates")]
config.layout = "application"
config.template = "my_view"
@ -40,7 +40,7 @@ In an app with many views, its helpful to use inheritance to share common set
```ruby
module MyApp
class View < Dry::View
class View < Hanami::View
# Set common configuration in the shared base view class
config.paths = [File.join(__dir__, "templates")]
config.layout = "application"
@ -61,7 +61,7 @@ end
## 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.
- **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
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.
@ -15,19 +15,19 @@ A context object is helpful in holding any behaviour or data you don't want to p
## Defining a context
Context classes must inherit from `Dry::View::Context`
Context classes must inherit from `Hanami::View::Context`
```ruby
class MyContext < Dry::View::Context
class MyContext < Hanami::View::Context
end
```
## 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
class MyContext < Dry::View::Context
class MyContext < Hanami::View::Context
attr_reader :assets
def initialize(assets:, **args)
@ -41,13 +41,13 @@ class MyContext < Dry::View::Context
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
# Require the auto-injector module for your app's container
require "my_app/import"
class MyContext < Dry::View::Context
class MyContext < Hanami::View::Context
include MyApp::Import["assets"]
def asset_path(asset_name)
@ -61,7 +61,7 @@ end
The default context can be `configured` for a view:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.default_context = MyContext.new
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:
```ruby
class MyContext < Dry::View::Context
class MyContext < Hanami::View::Context
decorate :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:
```ruby
class MyContext < Dry::View::Context
class MyContext < Hanami::View::Context
decorate :navigation_items, as: :menu_items
# ...

View File

@ -1,7 +1,7 @@
---
title: Exposures
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).
@ -9,7 +9,7 @@ Define _exposures_ within your view to declare and prepare the values to be pass
An exposure can take a block:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
expose :users do
user_repo.listing
end
@ -19,7 +19,7 @@ end
Or refer to an instance method:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
expose :users
private
@ -33,7 +33,7 @@ end
Or allow a matching value from the input data to pass through to the view:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
# With no matching instance method, passes the `users:` argument provided to
# `#call` straight to the template
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`:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
expose :users do |page:|
user_repo.listing(page: page)
end
@ -55,7 +55,7 @@ end
The same applies to instance methods acting as exposures:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
expose :users
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):
```ruby
class MyView < Dry::View
class MyView < Hanami::View
expose :users do |page: 1|
user_repo.listing(page: page)
end
@ -81,7 +81,7 @@ end
If your exposure passes through input data directly, use the `default:` option:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
# With no matching instance method, passes the `users:` argument to `#call`
# straight to the template
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.
```ruby
class MyView < Dry::View::Controller
class MyView < Hanami::View::Controller
expose :users do |page:|
user_repo.listing(page: page)
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:
```ruby
class MyView < Dry::View::Controller
class MyView < Hanami::View::Controller
private_expose :user_listing do
user_repo.listing
end

View File

@ -2,7 +2,7 @@
title: Introduction
layout: gem-single
type: gem
name: dry-view
name: hanami-view
sections:
- configuration
- injecting-dependencies
@ -14,20 +14,20 @@ sections:
- 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 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 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)
- 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))
- 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. hanami-view fits perfectly with [dry-system](/gems/dry-system), [dry-container](/gems/dry-container), and [dry-auto_inject](/gems/dry-auto_inject))
## 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
- [**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
require "dry/view"
class ArticleView < Dry::View
class ArticleView < Hanami::View
config.paths = [File.join(__dir__, "templates")]
config.part_namespace = Parts
config.layout = "application"
@ -82,7 +82,7 @@ Define a [part](docs::parts) to provide view-specific behavior around the expose
```ruby
module Parts
class Article < Dry::View::Part
class Article < Hanami::View::Part
def byline_text
authors.map(&:name).join(", ")
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>
```
`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
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.
@ -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.
```ruby
class MyView < Dry::View
class MyView < Hanami::View
attr_reader :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 "my_app/import"
class MyView < Dry::View
class MyView < Hanami::View
include MyApp::Import["user_repo"]
expose :users do

View File

@ -1,22 +1,22 @@
---
title: Parts
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.
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.
## 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
module Parts
class User < Dry::View::Part
class User < Hanami::View::Part
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.
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
@ -47,7 +47,7 @@ For example, from a template:
Or when defining a custom part class:
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def display_name
# `name` and `email` are methods on the decorated user value
"#{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`):
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def name
value.name.upcase
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:
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def info_box
render(:info_box)
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`):
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def info_box
scope(:info_box, size: :large).render
end
@ -124,7 +124,7 @@ In your part classes, you can access the [context object](docs::context) as `#_c
For example:
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def avatar_url
# asset_path is a method defined on the context object (in this case,
# 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:
```ruby
class UserPart < Dry::View::Part
class UserPart < Hanami::View::Part
decorate :address
end
```
@ -146,7 +146,7 @@ end
You can pass the same options to `decorate` as you do to [exposures](docs::exposures), for example:
```ruby
class UserPart < Dry::View::Part
class UserPart < Hanami::View::Part
decorate :address, as: :location
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.
```ruby
class User < Dry::View::Part
class User < Hanami::View::Part
def bio_html
@bio_html ||= rich_text_renderer.render(bio)
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:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.part_builder = MyPartBuilder
end
```
@ -203,4 +203,4 @@ Your part builder must conform to the following interface:
- `#for_render_env(render_env)`
- `#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
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.
@ -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`:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.scope_namespace = Scopes
end
```
Each scope class must inherit from `Dry::View::Scope`:
Each scope class must inherit from `Hanami::View::Scope`:
```ruby
module Scopes
class MediaPlayer < Dry::View::Scope
class MediaPlayer < Hanami::View::Scope
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.
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
@ -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:
```ruby
class MediaPlayer < Dry::View::Scope
class MediaPlayer < Hanami::View::Scope
def audio_player_html
render(:audio_player)
end
@ -91,7 +91,7 @@ For example, from a template:
Or from a custom scope class:
```ruby
class MediaPlayer < Dry::View::Scope
class MediaPlayer < Hanami::View::Scope
def display_title
# `item` is a local
"#{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:
```ruby
class MediaPlayer < Dry::View::Scope
class MediaPlayer < Hanami::View::Scope
def show_artwork?
locals.fetch(:show_artwork, true)
end
@ -120,7 +120,7 @@ Scopes also delegate missing methods to the context object (provided there is no
For example:
```ruby
class MediaPlayer < Dry::View::Scope
class MediaPlayer < Hanami::View::Scope
def image_urls
# item is a local, and asset_path is a method defined on the context object
[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:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.template = "my_view"
config.scope = Scopes::MyView
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:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.template = "my_view"
config.scope_namespace = Scopes
config.scope = :my_view
@ -160,7 +160,7 @@ end
To fully customize scope lookup and initialization, you can provide a replacement scope builder:
```ruby
class MyView < Dry::View
class MyView < Hanami::View
config.scope_builder = MyScopeBuilder
end
```
@ -171,4 +171,4 @@ Your scope builder must conform to the following interface:
- `#for_render_env(render_env)`
- `#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
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.
@ -18,9 +18,9 @@ An example is `index.html.slim`, which would be found for a view controller with
## 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:
@ -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:
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)
3. The [context object](docs::context)

View File

@ -1,10 +1,10 @@
---
title: Testing
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
@ -13,7 +13,7 @@ To test a view object in full, initialize it, passing in any [dependencies](docs
Given this view:
```ruby
class ArticleView < Dry::View
class ArticleView < Hanami::View
config.template = "article"
attr_reader :repo
@ -82,7 +82,7 @@ To test simple [part](docs::parts) behavior, initialize a part and make your exp
```ruby
module Parts
class Article < Dry::View::Part
class Article < Hanami::View::Part
def byline
"By #{author_name}"
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`:
```ruby
class ArticleView < Dry::View
class ArticleView < Hanami::View
config.template = "article"
config.part_namespace = Parts
# ...
end
module Parts
class Article < Dry::View::Part
class Article < Hanami::View::Part
def author_details_html
render(:author_details, author: author)
end

View File

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

View File

@ -1,4 +1,4 @@
# dry-view example dry-system/sinatra app
# hanami-view example dry-system/sinatra app
## Setup
@ -12,7 +12,7 @@ To see the rendered views, run `bundle exec rackup` and visit http://localhost:9
## 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`
- `lib/example_app/view.rb`
@ -20,4 +20,4 @@ The following files/folders are specific to the dry-view integration:
- `lib/example_app/views/`
- `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
require "dry/view"
require "hanami/view"
require "slim"
require "example_app/container"
module ExampleApp
class View < Dry::View
class View < Hanami::View
config.paths = Container.root.join("web/templates")
config.layout = "application"
end

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
# dry-view example Rails app
# hanami-view example Rails app
## Setup
@ -18,14 +18,14 @@ To see the rendered views, run `./bin/rails server` and visit http://localhost:3
## 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`
- `app/views/`
- `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

View File

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

View File

@ -1,8 +1,8 @@
# 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)
if url_helpers.respond_to?(name)
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.
Bundler.require(*Rails.groups)
module DryViewExample
module HanamiViewExample
class Application < Rails::Application
config.load_defaults 5.2
# dry-view setup
# hanami-view setup
Rails.application.config.autoload_paths << Rails.root.join("app/views")
# Remove heinous monkey patch
Dry::View::Part.undef_method :to_param
Hanami::View::Part.undef_method :to_param
end
end

View File

@ -1,29 +1,28 @@
# frozen_string_literal: true
# this file is managed by dry-rb/devtools project
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'dry/view/version'
require 'hanami/view/version'
Gem::Specification.new do |spec|
spec.name = 'dry-view'
spec.name = 'hanami-view'
spec.authors = ["Tim Riley", "Piotr Solnica"]
spec.email = ["tim@icelab.com.au", "piotr.solnica@gmail.com"]
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.description = spec.summary
spec.homepage = 'https://dry-rb.org/gems/dry-view'
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-view.gemspec", "lib/**/*"]
spec.homepage = 'https://dry-rb.org/gems/hanami-view'
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "hanami-view.gemspec", "lib/**/*"]
spec.bindir = 'bin'
spec.executables = []
spec.require_paths = ['lib']
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['source_code_uri'] = 'https://github.com/dry-rb/dry-view'
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-view/issues'
spec.metadata['changelog_uri'] = 'https://github.com/hanami/view/blob/master/CHANGELOG.md'
spec.metadata['source_code_uri'] = 'https://github.com/hanami/view'
spec.metadata['bug_tracker_uri'] = 'https://github.com/hanami/view/issues'
spec.required_ruby_version = ">= 2.4.0"

View File

@ -1,3 +1,3 @@
# 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/scope_builder"
# A collection of next-generation Ruby libraries, helping you to write clear,
# 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
module Hanami
# A standalone, template-based view rendering system that offers everything
# you need to write well-factored view code.
#
@ -102,7 +98,7 @@ module Dry
#
# @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
# @!scope class
setting :scope
@ -111,11 +107,11 @@ module Dry
# 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`
#
# Defaults to a frozen instance of `Dry::View::Context`.
# Defaults to a frozen instance of `Hanami::View::Context`.
#
# @see View#call
#
# @param context [Dry::View::Context] context object
# @param context [Hanami::View::Context] context object
# @api public
# @!scope class
setting :default_context, Context.new.freeze

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
require "dry/equalizer"
module Dry
module Hanami
class View
# Output of a View rendering
#
@ -19,7 +19,7 @@ module Dry
# 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
attr_reader :locals
@ -34,7 +34,7 @@ module Dry
#
# @param name [Symbol] local key
#
# @return [Dry::View::Part]
# @return [Hanami::View::Part]
#
# @api public
def [](name)

View File

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

View File

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

View File

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

View File

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

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true
module Dry
module Hanami
class View
module Tilt
module ERB
def self.requirements
["dry/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/tilt/erbse", <<~ERROR]
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:
Dry::View::Tilt.deregister_adapter(:erb)
Hanami::View::Tilt.deregister_adapter(:erb)
ERROR
end

View File

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

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true
module Dry
module Hanami
class View
module Tilt
module Haml
def self.requirements
["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:
Dry::View::Tilt.deregister_adatper(:haml)
Hanami::View::Tilt.deregister_adatper(:haml)
ERROR
end

View File

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

View File

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

View File

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

View File

@ -1,14 +1,14 @@
# frozen_string_literal: true
require "dry/view"
require "dry/view/context"
require "dry/view/part"
require "hanami/view"
require "hanami/view/context"
require "hanami/view/part"
RSpec.describe "exposures" do
let(:context) {
Class.new(Dry::View::Context) do
Class.new(Hanami::View::Context) do
def title
"dry-view rocks!"
"hanami-view rocks!"
end
def assets
@ -18,7 +18,7 @@ RSpec.describe "exposures" 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.layout = "app"
config.template = "users"
@ -37,12 +37,12 @@ RSpec.describe "exposures" do
]
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
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.layout = "app"
config.template = "users"
@ -68,12 +68,12 @@ RSpec.describe "exposures" do
]
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
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.layout = "app"
config.template = "users"
@ -96,12 +96,12 @@ RSpec.describe "exposures" do
]
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
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.layout = "app"
config.template = "users"
@ -116,12 +116,12 @@ RSpec.describe "exposures" do
]
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
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.layout = "app"
config.template = "users"
@ -131,12 +131,12 @@ RSpec.describe "exposures" do
end.new
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
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.layout = "app"
config.template = "greeting"
@ -146,12 +146,12 @@ RSpec.describe "exposures" do
end.new
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
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.layout = "app"
config.template = "users_with_count"
@ -170,20 +170,20 @@ RSpec.describe "exposures" do
]
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
it "wraps exposures in view parts before they are supplied as dependencies" do
module Test
class UserPart < Dry::View::Part
class UserPart < Hanami::View::Part
def display_name
"User: #{value[:name]}"
end
end
end
view = Class.new(Dry::View) do
view = Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count"
@ -207,17 +207,17 @@ RSpec.describe "exposures" do
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].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"
end
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.layout = "app"
config.template = "greeting"
@ -232,13 +232,13 @@ RSpec.describe "exposures" do
end
end.new
expect(view.(greeting: "From dry-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>"
expect(view.(greeting: "From hanami-view internals", context: context).to_s).to eql(
"<!DOCTYPE html><html><head><title>hanami-view rocks!</title></head><body><p>Hello From hanami-view internals</p></body></html>"
)
end
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.layout = "app"
config.template = "greeting"
@ -254,12 +254,12 @@ RSpec.describe "exposures" do
end.new
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
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.layout = "app"
config.template = "edit"
@ -275,12 +275,12 @@ RSpec.describe "exposures" do
end.new
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
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.layout = "app"
config.template = "users_with_count"
@ -301,12 +301,12 @@ RSpec.describe "exposures" do
]
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
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.layout = "app"
config.template = "users_with_count"
@ -331,7 +331,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context}
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)
@ -339,7 +339,7 @@ RSpec.describe "exposures" do
end
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.layout = "app"
config.template = "users_with_count_inherit"
@ -370,7 +370,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context}
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)
@ -378,7 +378,7 @@ RSpec.describe "exposures" do
end
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.layout = "app"
config.template = "users_with_count_inherit"
@ -413,7 +413,7 @@ RSpec.describe "exposures" do
input = {users: users, context: context}
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)
@ -421,7 +421,7 @@ RSpec.describe "exposures" do
end
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.layout = "app_with_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(
'<!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

View File

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

View File

@ -3,7 +3,7 @@
RSpec.describe "part builder" do
before do
module Test
class Custom < Dry::View::Part
class Custom < Hanami::View::Part
def to_s
"Custom part wrapping #{_value}"
end
@ -11,7 +11,7 @@ RSpec.describe "part builder" do
CustomPart = Custom
class CustomArrayPart < Dry::View::Part
class CustomArrayPart < Hanami::View::Part
def each(&block)
(_value * 2).each(&block)
end
@ -21,7 +21,7 @@ RSpec.describe "part builder" do
describe "default decorator" 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.layout = nil
config.template = "decorated_parts"
@ -38,7 +38,7 @@ RSpec.describe "part builder" do
end
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.layout = nil
config.template = "decorated_parts"
@ -54,7 +54,7 @@ RSpec.describe "part builder" do
end
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.layout = nil
config.template = "decorated_parts"
@ -72,13 +72,13 @@ RSpec.describe "part builder" do
describe "custom decorator and part classes" 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)
name == :custom ? Test::CustomPart : super
end
end
view = Class.new(Dry::View) do
view = Class.new(Hanami::View) do
config.part_builder = part_builder
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil

View File

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

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
require "dry/view"
require "dry/view/context"
require "hanami/view"
require "hanami/view/context"
RSpec.describe "Template engines / erb (using erbse as default engine)" do
let(:base_view) {
Class.new(Dry::View) do
Class.new(Hanami::View) do
config.paths = FIXTURES_PATH.join("integration/template_engines/erbse")
end
}
@ -20,7 +20,7 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
end
it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do
context = Class.new(Hanami::View::Context) do
def wrapper
"<wrapper>#{yield}</wrapper>"
end
@ -41,16 +41,16 @@ RSpec.describe "Template engines / erb (using erbse as default engine)" do
@loaded_features = $LOADED_FEATURES.dup
$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
Dry::View::Renderer.cache.clear
Hanami::View::Tilt.cache.clear
Hanami::View::Renderer.cache.clear
end
after do
$LOAD_PATH.replace @load_path
$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
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"
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
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"
end.new
Dry::View::Tilt.deregister_adapter :erb
Hanami::View::Tilt.deregister_adapter :erb
expect { view.() }.not_to raise_error
expect(view.().to_s.strip).to eq "Hello"

View File

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

View File

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

View File

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

View File

@ -2,12 +2,12 @@
RSpec.describe "Testing / parts" do
let(:part_class) {
Class.new(Dry::View::Part) do
Class.new(Hanami::View::Part) do
end
}
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
title + "!"
end
@ -21,12 +21,12 @@ RSpec.describe "Testing / parts" do
end
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.template = "view"
end
part_class = Class.new(Dry::View::Part) do
part_class = Class.new(Hanami::View::Part) do
def feature_box
render(:feature_box)
end

View File

@ -1,22 +1,22 @@
# frozen_string_literal: true
require "dry/view"
require "dry/view/context"
require "hanami/view"
require "hanami/view/context"
RSpec.describe "View / errors" 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"
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
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")
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

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
require "dry/view"
require "dry/view/context"
require "hanami/view"
require "hanami/view/context"
RSpec.describe "View / exposures" 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.template = "greeting"
@ -14,7 +14,7 @@ RSpec.describe "View / exposures" do
end
end.new
context = Class.new(Dry::View::Context) do
context = Class.new(Hanami::View::Context) do
def name
"Jane"
end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
require "dry/view"
require "dry/view/part"
require "hanami/view"
require "hanami/view/part"
RSpec.describe "View / locals" 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.template = "greeting"
@ -14,11 +14,11 @@ RSpec.describe "View / locals" do
local = view.(greeting: "Hello").locals[:greeting]
expect(local).to be_a(Dry::View::Part)
expect(local).to be_a(Hanami::View::Part)
end
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.template = "greeting"

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
RSpec.describe "dry-view" do
RSpec.describe "hanami-view" do
let(:view_class) do
Class.new(Dry::View) do
Class.new(Hanami::View) do
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
@ -18,9 +18,9 @@ RSpec.describe "dry-view" do
end
let(:context) {
Class.new(Dry::View::Context) do
Class.new(Hanami::View::Context) do
def title
"dry-view rocks!"
"hanami-view rocks!"
end
def assets
@ -33,7 +33,7 @@ RSpec.describe "dry-view" do
view = view_class.new
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
@ -51,7 +51,7 @@ RSpec.describe "dry-view" do
view = view_class.new
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
@ -61,7 +61,7 @@ RSpec.describe "dry-view" do
end.new
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
@ -71,7 +71,7 @@ RSpec.describe "dry-view" do
end.new
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
@ -81,13 +81,13 @@ RSpec.describe "dry-view" do
end.new
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
describe "inheritance" 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 :layout, "app"
@ -115,7 +115,7 @@ RSpec.describe "dry-view" do
end.new
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

View File

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

View File

@ -1,13 +1,13 @@
# frozen_string_literal: true
require "dry/view/context"
require "dry/view/part"
require "dry/view/part_builder"
require "dry/view/scope_builder"
require "hanami/view/context"
require "hanami/view/part"
require "hanami/view/part_builder"
require "hanami/view/scope_builder"
RSpec.describe Dry::View::Context do
RSpec.describe Hanami::View::Context do
let(:context_class) {
Class.new(Dry::View::Context) do
Class.new(Hanami::View::Context) do
attr_reader :assets, :routes
decorate :assets, :routes
@ -25,12 +25,12 @@ RSpec.describe Dry::View::Context do
let(:routes) { double(:routes) }
let(:render_env) {
Dry::View::RenderEnvironment.new(
Hanami::View::RenderEnvironment.new(
inflector: Dry::Inflector.new,
renderer: double(:renderer),
context: Dry::View::Context.new,
part_builder: Dry::View::PartBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new
context: Hanami::View::Context.new,
part_builder: Hanami::View::PartBuilder.new,
scope_builder: Hanami::View::ScopeBuilder.new
)
}
@ -49,7 +49,7 @@ RSpec.describe Dry::View::Context do
describe "attribute readers" 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
end
end

View File

@ -1,11 +1,11 @@
# 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) {
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_2
@ -51,6 +51,6 @@ RSpec.describe Dry::View::DecoratedAttributes 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[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

View File

@ -1,6 +1,6 @@
# 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) }
let(:proc) { -> _input { "hi" } }

View File

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

View File

@ -1,17 +1,17 @@
# 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 }
let(:render_env) {
Dry::View::RenderEnvironment.new(
renderer: Dry::View::Renderer.new([FIXTURES_PATH], format: :html),
Hanami::View::RenderEnvironment.new(
renderer: Hanami::View::Renderer.new([FIXTURES_PATH], format: :html),
inflector: Dry::Inflector.new,
context: Dry::View::Context.new,
scope_builder: Dry::View::ScopeBuilder.new,
part_builder: Dry::View::PartBuilder.new(namespace: namespace)
context: Hanami::View::Context.new,
scope_builder: Hanami::View::ScopeBuilder.new,
part_builder: Hanami::View::PartBuilder.new(namespace: namespace)
)
}
@ -27,7 +27,7 @@ RSpec.describe Dry::View::PartBuilder do
let(:options) { {} }
shared_examples "a view part" do
let(:part_class) { Dry::View::Part }
let(:part_class) { Hanami::View::Part }
it "returns a part" do
expect(part).to be_a part_class
@ -43,8 +43,8 @@ RSpec.describe Dry::View::PartBuilder do
end
shared_examples "a view part collection" do
let(:collection_part_class) { Dry::View::Part }
let(:item_part_class) { Dry::View::Part }
let(:collection_part_class) { Hanami::View::Part }
let(:item_part_class) { Hanami::View::Part }
it "returns a part wrapping the collection" do
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
before do
Test::UserPart = Class.new(Dry::View::Part)
Test::UserPart = Class.new(Hanami::View::Part)
end
let(:options) { {as: Test::UserPart} }
@ -100,7 +100,7 @@ RSpec.describe Dry::View::PartBuilder do
describe "explicit part class provided via as: option" do
before do
Test::UserPart = Class.new(Dry::View::Part)
Test::UserPart = Class.new(Hanami::View::Part)
end
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
before do
Test::UserCollectionPart = Class.new(Dry::View::Part)
Test::UserCollectionPart = Class.new(Hanami::View::Part)
end
let(:options) { {as: [Test::UserCollectionPart]} }
@ -128,23 +128,23 @@ RSpec.describe Dry::View::PartBuilder do
before do
module Test
module Parts
class Users < Dry::View::Part
class Users < Hanami::View::Part
end
class UserCollection < Dry::View::Part
class UserCollection < Hanami::View::Part
end
class User < Dry::View::Part
class User < Hanami::View::Part
decorate :profile
end
class AdminUser < Dry::View::Part
class AdminUser < Hanami::View::Part
end
module UserModule
end
class Profile < Dry::View::Part
class Profile < Hanami::View::Part
end
end
end
@ -171,11 +171,11 @@ RSpec.describe Dry::View::PartBuilder do
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} }
it_behaves_like "a view part" do
let(:part_class) { Dry::View::Part }
let(:part_class) { Hanami::View::Part }
end
end

View File

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

View File

@ -1,22 +1,22 @@
# frozen_string_literal: true
require "dry/view/render_environment"
require "hanami/view/render_environment"
require "dry/inflector"
require "dry/view/context"
require "dry/view/part_builder"
require "dry/view/scope_builder"
require "hanami/view/context"
require "hanami/view/part_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) }
let(:options) {
{
inflector: Dry::Inflector.new,
renderer: Dry::View::Renderer.new([Dry::View::Path.new(FIXTURES_PATH)], format: :html),
context: Dry::View::Context.new,
part_builder: Dry::View::PartBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new
renderer: Hanami::View::Renderer.new([Hanami::View::Path.new(FIXTURES_PATH)], format: :html),
context: Hanami::View::Context.new,
part_builder: Hanami::View::PartBuilder.new,
scope_builder: Hanami::View::ScopeBuilder.new
}
}

View File

@ -1,8 +1,8 @@
# 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) {
described_class.new(
output: "rendered template output",

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true
require "dry/view/path"
require "dry/view/renderer"
require "hanami/view/path"
require "hanami/view/renderer"
RSpec.describe Dry::View::Renderer do
RSpec.describe Hanami::View::Renderer do
subject(:renderer) do
Dry::View::Renderer.new(
[Dry::View::Path.new(SPEC_ROOT.join("fixtures/templates"))],
Hanami::View::Renderer.new(
[Hanami::View::Path.new(SPEC_ROOT.join("fixtures/templates"))],
format: "html",
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
expect {
renderer.template(:_shared_hello, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_shared_hello/)
}.to raise_error(Hanami::View::TemplateNotFoundError, /_shared_hello/)
end
it "raises error when template cannot be found" do
expect {
renderer.template(:missing_template, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /missing_template/)
}.to raise_error(Hanami::View::TemplateNotFoundError, /missing_template/)
end
end
@ -56,7 +56,7 @@ RSpec.describe Dry::View::Renderer do
it "raises error when partial cannot be found" do
expect {
renderer.partial(:missing_partial, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_missing_partial/)
}.to raise_error(Hanami::View::TemplateNotFoundError, /_missing_partial/)
end
end

View File

@ -1,8 +1,8 @@
# 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) { {} }
context "with a render environment" do
@ -96,19 +96,19 @@ RSpec.describe Dry::View::Scope do
describe "#render" 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
describe "#scope" 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
describe "#_context" 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

View File

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