Fix Rubocop issues

This commit is contained in:
Tim Riley 2020-03-13 23:06:56 +11:00
parent 209a3706a5
commit cb479c9d5e
No known key found for this signature in database
GPG Key ID: 747ABA1282E88BC9
86 changed files with 986 additions and 1021 deletions

32
Gemfile
View File

@ -1,34 +1,34 @@
# frozen_string_literal: true
source 'https://rubygems.org'
source "https://rubygems.org"
eval_gemfile 'Gemfile.devtools'
eval_gemfile "Gemfile.devtools"
gemspec
group :tools do
gem 'hotch'
gem 'pry-byebug', platform: :mri
gem "hotch"
gem "pry-byebug", platform: :mri
end
group :test do
gem 'rack', '>= 2.0.6'
gem "rack", ">= 2.0.6"
gem 'erbse'
gem 'erubi'
gem 'hamlit'
gem 'hamlit-block'
gem 'slim', '~> 4.0'
gem "erbse"
gem "erubi"
gem "hamlit"
gem "hamlit-block"
gem "slim", "~> 4.0"
end
group :benchmarks do
gem 'benchmark-ips'
gem 'actionview'
gem 'actionpack'
gem "actionpack"
gem "actionview"
gem "benchmark-ips"
end
group :docs do
gem 'yard'
gem 'yard-junk'
gem 'redcarpet', platforms: :mri
gem "redcarpet", platforms: :mri
gem "yard"
gem "yard-junk"
end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'bundler/gem_tasks'
require "bundler/gem_tasks"
require 'rspec/core/rake_task'
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task default: [:spec]

View File

@ -1,23 +1,25 @@
# frozen_string_literal: true
require 'pathname'
require 'ostruct'
require 'benchmark/ips'
require 'dry/view'
require 'action_view'
require 'action_controller'
require "pathname"
require "ostruct"
require "benchmark/ips"
require "dry/view"
require "action_view"
require "action_controller"
TEMPLATES_PATHS = Pathname(__FILE__).dirname.join('templates')
TEMPLATES_PATHS = Pathname(__FILE__).dirname.join("templates")
TEMPLATE_LOCALS = { users: [
OpenStruct.new(name: 'Jane', email: 'Jane@example.com'),
OpenStruct.new(name: 'Teresa', email: 'teresa@example.com')
] }
TEMPLATE_LOCALS = {
users: [
OpenStruct.new(name: "Jane", email: "Jane@example.com"),
OpenStruct.new(name: "Teresa", email: "teresa@example.com")
]
}.freeze
ActionController::Base.view_paths = TEMPLATES_PATHS
class UsersController < ActionController::Base
layout 'app'
layout "app"
attr_reader :users
@ -29,8 +31,8 @@ end
class DryView < Dry::View
config.paths = TEMPLATES_PATHS
config.layout = 'app'
config.template = 'users'
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users
@ -39,7 +41,10 @@ end
action_controller = UsersController.new
dry_view = DryView.new
if (action_controller_output = action_controller.index) != (dry_view_output = dry_view.(TEMPLATE_LOCALS).to_s)
action_controller_output = action_controller.index
dry_view_output = dry_view.(TEMPLATE_LOCALS).to_s
if action_controller_output != dry_view_output
puts "Output doesn't match:"
puts
puts "ActionView:\n\n#{action_controller_output}\n"
@ -47,11 +52,11 @@ if (action_controller_output = action_controller.index) != (dry_view_output = dr
end
Benchmark.ips do |x|
x.report('action_controller') do
x.report("action_controller") do
1000.times { action_controller.index }
end
x.report('dry-view') do
x.report("dry-view") do
1000.times { dry_view.(TEMPLATE_LOCALS).to_s }
end

View File

@ -1,21 +1,23 @@
# frozen_string_literal: true
require 'hotch'
require 'pathname'
require 'ostruct'
require 'dry/view'
require "hotch"
require "pathname"
require "ostruct"
require "dry/view"
TEMPLATES_PATHS = Pathname(__FILE__).dirname.join('templates')
TEMPLATES_PATHS = Pathname(__FILE__).dirname.join("templates")
TEMPLATE_LOCALS = { users: [
OpenStruct.new(name: 'Jane', email: 'Jane@example.com'),
OpenStruct.new(name: 'Teresa', email: 'teresa@example.com')
] }
TEMPLATE_LOCALS = {
users: [
OpenStruct.new(name: "Jane", email: "Jane@example.com"),
OpenStruct.new(name: "Teresa", email: "teresa@example.com")
]
}.freeze
class View < Dry::View
config.paths = TEMPLATES_PATHS
config.layout = 'app'
config.template = 'users'
config.layout = "app"
config.template = "users"
expose :users
end

View File

@ -1,8 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'dry-view'
require "bundler/setup"
require "dry-view"
require 'pry'
require "pry"
Pry.start

View File

@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative 'setup_helpers'
require_relative "setup_helpers"
Setup.execute 'bundle'
Setup.execute "bundle"

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'open3'
require "open3"
module Setup
module_function
@ -18,7 +18,7 @@ module Setup
status = wait_thr.value
end
if !status.success?
unless status.success?
puts "Failed to run #{cmd}"
puts err
exit 1

View File

@ -1,9 +1,9 @@
# frozen_string_literal: true
source 'https://rubygems.org'
source "https://rubygems.org"
gem 'byebug'
gem 'dry-view', path: '../..'
gem 'dry-web'
gem 'sinatra'
gem 'slim'
gem "byebug"
gem "dry-view", path: "../.."
gem "dry-web"
gem "sinatra"
gem "slim"

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
require_relative './system/boot'
require 'example_app/web'
require_relative "./system/boot"
require "example_app/web"
run ExampleApp::Web

View File

@ -1,18 +1,18 @@
# frozen_string_literal: true
require 'ostruct'
require "ostruct"
module ExampleApp
Article = Struct.new(:slug, :title)
class ArticleRepo
ARTICLES = [
{slug: 'together-breakfast', title: 'Together Breakfast'},
{slug: 'cat-fingers', title: 'Cat Fingers'},
{slug: "together-breakfast", title: "Together Breakfast"},
{slug: "cat-fingers", title: "Cat Fingers"}
].freeze
def by_slug!(slug)
if (article = ARTICLES.detect { |a| a[:slug] == slug})
if (article = ARTICLES.detect { |a| a[:slug] == slug })
Article.new(*article.values)
else
raise "Article with slug +#{slug}+ not found"

View File

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

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require_relative '../view'
require 'dry/view/context'
require_relative "../view"
require "dry/view/context"
module ExampleApp
class View

View File

@ -1,15 +1,15 @@
# frozen_string_literal: true
require 'example_app/import'
require 'example_app/view'
require "example_app/import"
require "example_app/view"
module ExampleApp
module Views
module Articles
class Index < View
include Import['article_repo']
include Import["article_repo"]
config.template = 'articles/index'
config.template = "articles/index"
expose :articles do
article_repo.listing
@ -18,4 +18,3 @@ module ExampleApp
end
end
end

View File

@ -1,15 +1,15 @@
# frozen_string_literal: true
require 'example_app/import'
require 'example_app/view'
require "example_app/import"
require "example_app/view"
module ExampleApp
module Views
module Articles
class Show < View
include Import['article_repo']
include Import["article_repo"]
config.template = 'articles/show'
config.template = "articles/show"
expose :article do |slug:|
article_repo.by_slug!(slug)
@ -18,4 +18,3 @@ module ExampleApp
end
end
end

View File

@ -1,37 +1,37 @@
# frozen_string_literal: true
require 'sinatra/base'
require 'byebug'
require "sinatra/base"
require "byebug"
module ExampleApp
class Web < Sinatra::Base
get '/' do
redirect '/articles'
get "/" do
redirect "/articles"
end
get '/articles' do
render_view 'articles.index'
get "/articles" do
render_view "articles.index"
end
get '/articles/:slug' do |slug|
render_view 'articles.show', slug: slug
get "/articles/:slug" do |slug|
render_view "articles.show", slug: slug
end
helpers do
def render_view(identifier, with: {}, **input)
container["views.#{identifier}"].(
context: view_context(**with),
**input,
**input
).to_s
end
def view_context(**options)
container['view.context'].with(view_context_options(**options))
container["view.context"].with(view_context_options(**options))
end
def view_context_options(**overrides)
{
request: request,
request: request
}.merge(overrides)
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require_relative 'example_app/container'
require_relative "example_app/container"
container = ExampleApp::Container
container.finalize!

View File

@ -1,17 +1,17 @@
# frozen_string_literal: true
require 'dry/web/container'
require 'dry/system/components'
require "dry/web/container"
require "dry/system/components"
module ExampleApp
class Container < Dry::Web::Container
configure do
config.name = :example_app
config.log_levels = %i[test development production].map { |e| [e, Logger::DEBUG] }.to_h
config.default_namespace = 'example_app'
config.default_namespace = "example_app"
config.auto_register = %w[lib/example_app]
end
load_paths! 'lib'
load_paths! "lib"
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require_relative 'container'
require_relative "container"
module ExampleApp
Import = Container.injector

View File

@ -1,21 +1,21 @@
# frozen_string_literal: true
source 'https://rubygems.org'
source "https://rubygems.org"
ruby '2.6.0'
ruby "2.6.0"
gem 'rails', '~> 5.2.2'
gem 'sqlite3'
gem 'puma', '~> 3.11'
gem "puma", "~> 3.11"
gem "rails", "~> 5.2.2"
gem "sqlite3"
gem 'dry-view', path: '../..'
gem 'slim'
gem "dry-view", path: "../.."
gem "slim"
group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem "byebug", platforms: %i[mri mingw x64_mingw]
end
group :development do
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
gem "listen", ">= 3.0.5", "< 3.2"
gem "web-console", ">= 3.3.0"
end

View File

@ -3,6 +3,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application'
require_relative "config/application"
Rails.application.load_tasks

View File

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

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/view/context'
require "dry/view/context"
class ApplicationViewContext < Dry::View::Context
def method_missing(name, *args, &block)
@ -16,7 +16,9 @@ class ApplicationViewContext < Dry::View::Context
private
def respond_to_missing?(name, include_private = false)
url_helpers.respond_to?(name, include_private) || helpers.respond_to?(name, include_private) || super
url_helpers.respond_to?(name, include_private) ||
helpers.respond_to?(name, include_private) ||
super
end
def url_helpers

View File

@ -3,7 +3,7 @@
module Views
module Articles
class Index < ApplicationView
config.template = 'articles/index'
config.template = "articles/index"
expose :articles
end

View File

@ -3,7 +3,7 @@
module Views
module Articles
class Show < ApplicationView
config.template = 'articles/show'
config.template = "articles/show"
expose :article
end

View File

@ -1,5 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
load Gem.bin_path('bundler', 'bundle')
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
load Gem.bin_path("bundler", "bundle")

View File

@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'
APP_PATH = File.expand_path("../config/application", __dir__)
require_relative "../config/boot"
require "rails/commands"

View File

@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative '../config/boot'
require 'rake'
require_relative "../config/boot"
require "rake"
Rake.application.run

View File

@ -1,38 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
# puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml')
# cp 'config/database.yml.sample', 'config/database.yml'
# end
puts "\n== Preparing database =="
system! 'bin/rails db:setup'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
system! 'bin/rails restart'
end

View File

@ -1,33 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
chdir APP_ROOT do
# This script is a way to update your development environment automatically.
# Add necessary update steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
puts "\n== Updating database =="
system! 'bin/rails db:migrate'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
system! 'bin/rails restart'
end

View File

@ -1,13 +1,13 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
APP_ROOT = File.expand_path('..', __dir__)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
begin
exec 'yarnpkg', *ARGV
exec "yarnpkg", *ARGV
rescue Errno::ENOENT
$stderr.puts 'Yarn executable was not detected in the system.'
$stderr.puts 'Download Yarn at https://yarnpkg.com/en/docs/install'
warn "Yarn executable was not detected in the system."
warn "Download Yarn at https://yarnpkg.com/en/docs/install"
exit 1
end
end

View File

@ -2,6 +2,6 @@
# This file is used by Rack-based servers to start the application.
require_relative 'config/environment'
require_relative "config/environment"
run Rails.application

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true
require_relative 'boot'
require_relative "boot"
require 'rails'
require 'active_model/railtie'
require 'active_record/railtie'
require 'action_controller/railtie'
require 'action_view/railtie'
require "rails"
require "active_model/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_view/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
@ -17,7 +17,7 @@ module DryViewExample
config.load_defaults 5.2
# dry-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
Dry::View::Part.undef_method :to_param

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
require "bundler/setup" # Set up gems listed in the Gemfile.

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
# Load the Rails application.
require_relative 'application'
require_relative "application"
# Initialize the Rails application.
Rails.application.initialize!

View File

@ -16,12 +16,12 @@ Rails.application.configure do
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp', 'caching-dev.txt').exist?
if Rails.root.join("tmp", "caching-dev.txt").exist?
config.action_controller.perform_caching = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
"Cache-Control" => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
@ -38,7 +38,6 @@ Rails.application.configure do
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true

View File

@ -22,7 +22,7 @@ Rails.application.configure do
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
@ -39,7 +39,7 @@ Rails.application.configure do
config.log_level = :debug
# Prepend all log lines with the following tags.
config.log_tags = [ :request_id ]
config.log_tags = [:request_id]
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
@ -62,7 +62,7 @@ Rails.application.configure do
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV['RAILS_LOG_TO_STDOUT'].present?
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)

View File

@ -17,7 +17,7 @@ Rails.application.configure do
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.

View File

@ -6,16 +6,16 @@
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch('PORT') { 3000 }
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch('RAILS_ENV') { 'development' }
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together

View File

@ -2,5 +2,5 @@
Rails.application.routes.draw do
resources :articles, only: %i[index show]
root to: 'articles#index'
root to: "articles#index"
end

View File

@ -12,12 +12,10 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_01_16_013956) do
create_table 'articles', force: :cascade do |t|
t.string 'title'
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
ActiveRecord::Schema.define(version: 20_190_116_013_956) do
create_table "articles", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end

View File

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

View File

@ -1,19 +1,19 @@
# frozen_string_literal: true
require 'dry/configurable'
require 'dry/core/cache'
require 'dry/equalizer'
require 'dry/inflector'
require "dry/configurable"
require "dry/core/cache"
require "dry/equalizer"
require "dry/inflector"
require_relative 'view/context'
require_relative 'view/exposures'
require_relative 'view/errors'
require_relative 'view/part_builder'
require_relative 'view/path'
require_relative 'view/render_environment'
require_relative 'view/rendered'
require_relative 'view/renderer'
require_relative 'view/scope_builder'
require_relative "view/context"
require_relative "view/exposures"
require_relative "view/errors"
require_relative "view/part_builder"
require_relative "view/path"
require_relative "view/render_environment"
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
@ -35,7 +35,7 @@ module Dry
# @api public
class View
# @api private
DEFAULT_RENDERER_OPTIONS = { default_encoding: 'utf-8' }.freeze
DEFAULT_RENDERER_OPTIONS = {default_encoding: "utf-8"}.freeze
include Dry::Equalizer(:config, :exposures)
@ -92,7 +92,7 @@ module Dry
# @param dir [String] directory name
# @api public
# @!scope class
setting :layouts_dir, 'layouts'
setting :layouts_dir, "layouts"
# @overload config.scope=(scope_class)
# Set the scope class to use when rendering the view's template.
@ -230,8 +230,10 @@ module Dry
# @!macro [new] exposure_options
# @param options [Hash] the exposure's options
# @option options [Boolean] :layout expose this value to the layout (defaults to false)
# @option options [Boolean] :decorate decorate this value in a matching Part (defaults to true)
# @option options [Symbol, Class] :as an alternative name or class to use when finding a matching Part
# @option options [Boolean] :decorate decorate this value in a matching Part (defaults to
# true)
# @option options [Symbol, Class] :as an alternative name or class to use when finding a
# matching Part
# @overload expose(name, **options, &block)
# Define a value to be passed to the template. The return value of the
@ -315,7 +317,8 @@ module Dry
#
# @param name [Symbol] name for the exposure
# @macro exposure_options
# @option options [Boolean] :default a default value to provide if there is no matching input data
# @option options [Boolean] :default a default value to provide if there is no matching
# input data
#
# @overload expose(*names, **options)
# Define multiple values to pass through from the input data (when there
@ -326,7 +329,8 @@ module Dry
#
# @param names [Symbol] names for the exposures
# @macro exposure_options
# @option options [Boolean] :default a default value to provide if there is no matching input data
# @option options [Boolean] :default a default value to provide if there is no matching
# input data
#
# @see https://dry-rb.org/gems/dry-view/exposures/
#
@ -411,7 +415,7 @@ module Dry
config.paths,
format: format,
engine_mapping: config.renderer_engine_mapping,
**config.renderer_options,
**config.renderer_options
)
}
end
@ -467,7 +471,10 @@ module Dry
if layout?
layout_env = self.class.layout_env(format: format, context: context)
output = env.template(self.class.layout_path, layout_env.scope(config.scope, layout_locals(locals))) { output }
output = env.template(
self.class.layout_path,
layout_env.scope(config.scope, layout_locals(locals))
) { output }
end
Rendered.new(output: output, locals: locals)
@ -477,8 +484,8 @@ module Dry
# @api private
def ensure_config
raise UndefinedConfigError.new(:paths) unless Array(config.paths).any?
raise UndefinedConfigError.new(:template) unless config.template
raise UndefinedConfigError, :paths unless Array(config.paths).any?
raise UndefinedConfigError, :template unless config.template
end
# @api private
@ -501,7 +508,7 @@ module Dry
# @api private
def layout?
!!config.layout
!!config.layout # rubocop:disable Style/DoubleNegation
end
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'dry/equalizer'
require_relative 'decorated_attributes'
require "dry/equalizer"
require_relative "decorated_attributes"
module Dry
class View
@ -43,7 +43,7 @@ module Dry
# @api private
def for_render_env(render_env)
return self if render_env == self._render_env
return self if render_env == _render_env
self.class.new(**_options.merge(render_env: render_env))
end
@ -72,7 +72,7 @@ module Dry
def with(**new_options)
self.class.new(
render_env: _render_env,
**_options.merge(new_options),
**_options.merge(new_options)
)
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'set'
require "set"
module Dry
class View
@ -27,7 +27,8 @@ module Dry
#
# @param names [Array<Symbol>] the attribute names
# @param options [Hash] the options to pass to the Part Builder
# @option options [Symbol, Class] :as an alternative name or class to use when finding a matching Part
# @option options [Symbol, Class] :as an alternative name or class to use when finding a
# matching Part
#
# @api public
def decorate(*names, **options)

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry-equalizer'
require "dry-equalizer"
module Dry
class View
@ -10,8 +10,8 @@ module Dry
class Exposure
include Dry::Equalizer(:name, :proc, :object, :options)
EXPOSURE_DEPENDENCY_PARAMETER_TYPES = [:req, :opt].freeze
INPUT_PARAMETER_TYPES = [:key, :keyreq, :keyrest].freeze
EXPOSURE_DEPENDENCY_PARAMETER_TYPES = %i[req opt].freeze
INPUT_PARAMETER_TYPES = %i[key keyreq keyrest].freeze
attr_reader :name
attr_reader :proc

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'tsort'
require 'dry/equalizer'
require 'dry/view/exposure'
require "tsort"
require "dry/equalizer"
require "dry/view/exposure"
module Dry
class View
@ -46,8 +46,9 @@ module Dry
end
def call(input)
# rubocop:disable Style/MultilineBlockChain
tsort.each_with_object({}) { |name, memo|
next unless exposure = self[name]
next unless (exposure = self[name])
value = exposure.(input, memo)
value = yield(value, exposure) if block_given?
@ -56,6 +57,7 @@ module Dry
}.each_with_object({}) { |(name, value), memo|
memo[name] = value unless self[name].private?
}
# rubocop:enable Style/MultilineBlockChain
end
private

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'dry/equalizer'
require_relative 'decorated_attributes'
require_relative 'render_environment_missing'
require "dry/equalizer"
require_relative "decorated_attributes"
require_relative "render_environment_missing"
module Dry
class View
@ -60,7 +60,7 @@ module Dry
#
# @api private
def self.part_name(inflector)
name ? inflector.underscore(inflector.demodulize(name)) : 'part'
name ? inflector.underscore(inflector.demodulize(name)) : "part"
end
# Returns a new Part instance
@ -70,7 +70,11 @@ module Dry
# @param render_env [RenderEnvironment] render environment
#
# @api public
def initialize(render_env: RenderEnvironmentMissing.new, name: self.class.part_name(render_env.inflector), value:)
def initialize(
render_env: RenderEnvironmentMissing.new,
name: self.class.part_name(render_env.inflector),
value:
)
@_name = name
@_value = value
@_render_env = render_env
@ -115,15 +119,18 @@ module Dry
# itself responds to `#render`.
#
# @param partial_name [Symbol, String] partial name
# @param as [Symbol] the name for the Part to assume in the partial's locals. Default's to the Part's `_name`.
# @param as [Symbol] the name for the Part to assume in the partial's locals. Defaults to
# the Part's `_name`.
# @param locals [Hash<Symbol, Object>] other locals to provide the partial
#
# @return [String] rendered partial
#
# @api public
# rubocop:disable Naming/UncommunicativeMethodParamName
def _render(partial_name, as: _name, **locals, &block)
_render_env.partial(partial_name, _render_env.scope({ as => self }.merge(locals)), &block)
_render_env.partial(partial_name, _render_env.scope({as => self}.merge(locals)), &block)
end
# rubocop:enable Naming/UncommunicativeMethodParamName
# Builds a new scope with the part included in its locals.
#
@ -133,14 +140,15 @@ module Dry
# A convenience alias for `#_scope`. Is available unless the value
# itself responds to `#scope`.
#
# @param scope_name [Symbol, nil] scope name, used by the scope builder to determine the scope class
# @param scope_name [Symbol, nil] scope name, used by the scope builder to determine the
# scope class
# @param locals [Hash<Symbol, Object>] other locals to provide the partial
#
# @return [Dry::View::Scope] scope
#
# @api public
def _scope(scope_name = nil, **locals)
_render_env.scope(scope_name, { _name => self }.merge(locals))
_render_env.scope(scope_name, {_name => self}.merge(locals))
end
# Returns a string representation of the value
@ -168,12 +176,12 @@ module Dry
# @param options[Hash<Symbol, Object>] other options to provide when initializing the new part
#
# @api public
def new(klass = (self.class), name: (_name), value: (_value), **options)
def new(klass = self.class, name: _name, value: _value, **options)
klass.new(
name: name,
value: value,
render_env: _render_env,
**options,
**options
)
end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'dry/core/cache'
require 'dry/equalizer'
require_relative 'part'
require "dry/core/cache"
require "dry/equalizer"
require_relative "part"
module Dry
class View
@ -54,7 +54,7 @@ module Dry
klass.new(
name: name,
value: value,
render_env: render_env,
render_env: render_env
)
end
@ -69,11 +69,13 @@ module Dry
build_part(name, arr, **options.merge(as: collection_as))
end
# rubocop:disable Lint/UnusedMethodArgument
def collection_options(name:, **options)
collection_as = options[:as].is_a?(Array) ? options[:as].first : nil
options.merge(as: collection_as)
end
# rubocop:enable Lint/UnusedMethodArgument
def collection_item_options(name:, **options)
singular_name = inflector.singularize(name).to_sym
@ -90,7 +92,7 @@ module Dry
options.merge(
name: singular_name,
as: singular_as,
as: singular_as
)
end
@ -106,6 +108,7 @@ module Dry
end
end
# rubocop:disable Metrics/PerceivedComplexity
def resolve_part_class(name:, fallback_class:)
return fallback_class unless namespace
@ -114,7 +117,7 @@ module Dry
# Give autoloaders a chance to act
begin
klass = namespace.const_get(name)
rescue NameError
rescue NameError # rubocop:disable Lint/HandleExceptions
end
if !klass && namespace.const_defined?(name, false)
@ -127,6 +130,7 @@ module Dry
fallback_class
end
end
# rubocop:enable Metrics/PerceivedComplexity
def inflector
render_env.inflector

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'pathname'
require 'dry/core/cache'
require "pathname"
require "dry/core/cache"
module Dry
class View
@ -61,7 +61,7 @@ module Dry
end
def lookup_in_parent_dir(name, format, child_dirs:)
!root? && chdir('..').lookup(name, format, child_dirs: child_dirs, parent_dir: true)
!root? && chdir("..").lookup(name, format, child_dirs: child_dirs, parent_dir: true)
end
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/equalizer'
require "dry/equalizer"
module Dry
class View
@ -12,7 +12,7 @@ module Dry
inflector: config.inflector,
context: context,
scope_builder: config.scope_builder.new(namespace: config.scope_namespace),
part_builder: config.part_builder.new(namespace: config.part_namespace),
part_builder: config.part_builder.new(namespace: config.part_namespace)
)
end
@ -36,7 +36,7 @@ module Dry
part_builder.(name, value, **options)
end
def scope(name = nil, locals)
def scope(name = nil, locals) # rubocop:disable Style/OptionalArguments
scope_builder.(name, locals)
end
@ -54,7 +54,7 @@ module Dry
inflector: inflector,
context: context,
scope_builder: scope_builder,
part_builder: part_builder,
part_builder: part_builder
)
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/inflector'
require "dry/inflector"
module Dry
class View
@ -8,7 +8,7 @@ module Dry
class RenderEnvironmentMissing
class MissingEnvironmentError < StandardError
def message
'a +render_env+ must be provided'
"a +render_env+ must be provided"
end
end
@ -20,19 +20,19 @@ module Dry
raise MissingEnvironmentError
end
def part(name, value, **options)
def part(_name, _value, **_options)
raise MissingEnvironmentError
end
def scope(name = nil, locals)
def scope(_name = nil, _locals) # rubocop:disable Style/OptionalArguments
raise MissingEnvironmentError
end
def template(name, scope, &block)
def template(_name, _scope)
raise MissingEnvironmentError
end
def partial(name, scope, &block)
def partial(_name, _scope)
raise MissingEnvironmentError
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/equalizer'
require "dry/equalizer"
module Dry
class View

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true
require 'dry/core/cache'
require 'dry/equalizer'
require_relative 'errors'
require_relative 'tilt'
require "dry/core/cache"
require "dry/equalizer"
require_relative "errors"
require_relative "tilt"
module Dry
class View
# @api private
class Renderer
PARTIAL_PREFIX = '_'
PATH_DELIMITER = '/'
PARTIAL_PREFIX = "_"
PATH_DELIMITER = "/"
extend Dry::Core::Cache

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'dry/equalizer'
require 'dry/core/constants'
require_relative 'render_environment_missing'
require "dry/equalizer"
require "dry/core/constants"
require_relative "render_environment_missing"
module Dry
class View
@ -59,7 +59,11 @@ module Dry
# @return [Scope]
#
# @api public
def initialize(name: nil, locals: Dry::Core::Constants::EMPTY_HASH, render_env: RenderEnvironmentMissing.new)
def initialize(
name: nil,
locals: Dry::Core::Constants::EMPTY_HASH,
render_env: RenderEnvironmentMissing.new
)
@_name = name
@_locals = locals
@_render_env = render_env
@ -83,9 +87,14 @@ module Dry
# @api public
def render(partial_name = nil, **locals, &block)
partial_name ||= _name
raise ArgumentError, '+partial_name+ must be provided for unnamed scopes' unless partial_name
partial_name = _inflector.underscore(_inflector.demodulize(partial_name.to_s)) if partial_name.is_a?(Class)
unless partial_name
raise ArgumentError, "+partial_name+ must be provided for unnamed scopes"
end
if partial_name.is_a?(Class)
partial_name = _inflector.underscore(_inflector.demodulize(partial_name.to_s))
end
_render_env.partial(partial_name, _render_scope(locals), &block)
end
@ -153,7 +162,10 @@ module Dry
end
def respond_to_missing?(name, include_private = false)
_locals.key?(name) || _render_env.context.respond_to?(name) || CONVENIENCE_METHODS.include?(name) || super
_locals.key?(name) ||
_render_env.context.respond_to?(name) ||
CONVENIENCE_METHODS.include?(name) ||
super
end
def _render_scope(**locals)
@ -163,7 +175,7 @@ module Dry
self.class.new(
# FIXME: what about `name`?
locals: locals,
render_env: _render_env,
render_env: _render_env
)
end
end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'dry/core/cache'
require 'dry/equalizer'
require_relative 'scope'
require "dry/core/cache"
require "dry/equalizer"
require_relative "scope"
module Dry
class View
@ -46,11 +46,11 @@ module Dry
# @return [Dry::View::Scope]
#
# @api private
def call(name = nil, locals)
def call(name = nil, locals) # rubocop:disable Style/OptionalArguments
scope_class(name).new(
name: name,
locals: locals,
render_env: render_env,
render_env: render_env
)
end
@ -76,7 +76,7 @@ module Dry
# Give autoloaders a chance to act
begin
klass = namespace.const_get(name)
rescue NameError
rescue NameError # rubocop:disable Lint/HandleExceptions
end
if !klass && namespace.const_defined?(name, false)

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'dry/core/cache'
require 'tilt'
require "dry/core/cache"
require "tilt"
module Dry
class View
@ -11,7 +11,7 @@ module Dry
class << self
def [](path, mapping, **options)
ext = File.extname(path).sub(%r{^.}, '').to_sym
ext = File.extname(path).sub(/^./, "").to_sym
activate_adapter ext
with_mapping(mapping).new(path, **options)
@ -74,5 +74,5 @@ module Dry
end
end
require_relative 'tilt/erb'
require_relative 'tilt/haml'
require_relative "tilt/erb"
require_relative "tilt/haml"

View File

@ -5,7 +5,7 @@ module Dry
module Tilt
module ERB
def self.requirements
['dry/view/tilt/erbse', <<~ERROR]
["dry/view/tilt/erbse", <<~ERROR]
dry-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:
@ -15,7 +15,7 @@ module Dry
end
def self.activate
Tilt.default_mapping.register ErbseTemplate, 'erb'
Tilt.default_mapping.register ErbseTemplate, "erb"
self
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'tilt/template'
require 'erbse'
require "tilt/template"
require "erbse"
module Dry
class View
@ -12,7 +12,7 @@ module Dry
@template = ::Erbse::Engine.new
end
def precompiled_template(locals)
def precompiled_template(_locals)
@template.call(data)
end
end

View File

@ -5,7 +5,7 @@ module Dry
module Tilt
module Haml
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)
To ignore this and use another engine for .haml templates, dereigster this adapter before calling your views:

View File

@ -3,6 +3,6 @@
module Dry
class View
# @api private
VERSION = '0.7.0'
VERSION = "0.7.0"
end
end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/context'
require 'dry/view/part'
require "dry/view"
require "dry/view/context"
require "dry/view/part"
RSpec.describe 'Context' do
it 'Provides decorated attributes for use in templates and parts' do
RSpec.describe "Context" do
it "Provides decorated attributes for use in templates and parts" do
module Test
class Assets
def [](path)
@ -34,15 +34,15 @@ RSpec.describe 'Context' do
class User < Dry::View::Part
def image_tag
value[:image_url] || context.assets.image_tag('default.png')
value[:image_url] || context.assets.image_tag("default.png")
end
end
end
end
view = Class.new(Dry::View) do
config.paths = FIXTURES_PATH.join('integration/context')
config.template = 'decorated_attributes'
config.paths = FIXTURES_PATH.join("integration/context")
config.template = "decorated_attributes"
config.part_namespace = Test::Parts
expose :user
@ -51,11 +51,11 @@ RSpec.describe 'Context' do
context = Test::Context.new(assets: Test::Assets.new)
output = view.(
user: { image_url: nil },
context: context,
user: {image_url: nil},
context: context
).to_s
expect(output.gsub("\n", '')).to eq <<~HTML.gsub("\n", '')
expect(output.gsub("\n", "")).to eq <<~HTML.gsub("\n", "")
<img src="hashed/path/to/hello.png">
<div class="user">
<img src="hashed/path/to/default.png">

View File

@ -1,14 +1,14 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/context'
require 'dry/view/part'
require "dry/view"
require "dry/view/context"
require "dry/view/part"
RSpec.describe 'exposures' do
RSpec.describe "exposures" do
let(:context) {
Class.new(Dry::View::Context) do
def title
'dry-view rocks!'
"dry-view rocks!"
end
def assets
@ -17,11 +17,11 @@ RSpec.describe 'exposures' do
end.new
}
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users do |users:|
@ -32,8 +32,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -41,18 +41,18 @@ RSpec.describe 'exposures' do
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
attr_reader :prefix
def initialize
super
@prefix = 'My friend '
@prefix = "My friend "
end
expose :users do |users:|
@ -63,8 +63,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -72,11 +72,11 @@ RSpec.describe 'exposures' do
)
end
it 'supports instance methods as exposures' do
it "supports instance methods as exposures" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users
@ -91,8 +91,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -100,19 +100,19 @@ RSpec.describe 'exposures' do
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -120,14 +120,14 @@ RSpec.describe 'exposures' do
)
end
it 'using default values' do
it "using default values" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users, default: [{ name: 'John', email: 'john@william.org' }]
expose :users, default: [{name: "John", email: "john@william.org"}]
end.new
expect(view.(context: context).to_s).to eql(
@ -135,26 +135,26 @@ RSpec.describe 'exposures' do
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "greeting"
config.default_format = :html
expose :greeting, default: 'Hello Dry-rb'
expose :greeting, default: "Hello Dry-rb"
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>dry-view rocks!</title></head><body><p></p></body></html>"
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count"
config.default_format = :html
expose :users
@ -165,8 +165,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -174,7 +174,7 @@ RSpec.describe 'exposures' do
)
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
class UserPart < Dry::View::Part
def display_name
@ -184,9 +184,9 @@ RSpec.describe 'exposures' do
end
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count"
config.default_format = :html
expose :users, as: Test::UserPart
@ -201,8 +201,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
rendered = view.(users: users, context: context)
@ -210,17 +210,17 @@ RSpec.describe 'exposures' do
expect(rendered[:users]).to be_a(Dry::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[:users][0].value).to eq(name: "Jane", email: "jane@doe.org")
expect(rendered[:article]).to be_a(Dry::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
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "greeting"
config.default_format = :html
expose :greeting do |prefix, greeting:|
@ -228,41 +228,41 @@ RSpec.describe 'exposures' do
end
expose :prefix do
'Hello'
"Hello"
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 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>"
)
end
it 'supports default values for keyword arguments' do
it "supports default values for keyword arguments" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "greeting"
config.default_format = :html
expose :greeting do |prefix, greeting: 'From the defaults'|
expose :greeting do |prefix, greeting: "From the defaults"|
"#{prefix} #{greeting}"
end
expose :prefix do
'Hello'
"Hello"
end
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>dry-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
it "only passes keywords arguments that are needed in the block and allows for default values" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'edit'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "edit"
config.default_format = :html
expose :pretty_id do |id:|
@ -275,15 +275,15 @@ 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>dry-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
it "supports defining multiple exposures at once" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count"
config.default_format = :html
expose :users, :users_count
@ -296,8 +296,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, context: context).to_s).to eql(
@ -305,15 +305,15 @@ RSpec.describe 'exposures' do
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count"
config.default_format = :html
private_expose :prefix do
'COUNT: '
"COUNT: "
end
expose :users
@ -324,11 +324,11 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
input = { users: users, context: context }
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>'
@ -338,15 +338,15 @@ RSpec.describe 'exposures' do
expect(view.(input).locals).not_to include(:prefix)
end
it 'inherit exposures from parent class' do
it "inherit exposures from parent class" do
parent = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count_inherit'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count_inherit"
config.default_format = :html
private_expose :prefix do
'COUNT: '
"COUNT: "
end
expose :users
@ -358,16 +358,16 @@ RSpec.describe 'exposures' do
child = Class.new(parent) do
expose :child_expose do
'Child expose'
"Child expose"
end
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
input = { users: users, context: context }
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>'
@ -377,15 +377,15 @@ RSpec.describe 'exposures' do
expect(child.(input).locals).not_to include(:prefix)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users_with_count_inherit'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users_with_count_inherit"
config.default_format = :html
private_expose :prefix do
'COUNT: '
"COUNT: "
end
expose :users
@ -397,7 +397,7 @@ RSpec.describe 'exposures' do
child = Class.new(parent) do
expose :child_expose do
'Child expose'
"Child expose"
end
expose :users_count do |prefix, users:|
@ -406,11 +406,11 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
input = { users: users, context: context }
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>'
@ -420,11 +420,11 @@ RSpec.describe 'exposures' do
expect(child.(input).locals).not_to include(:prefix)
end
it 'makes exposures available to layout' do
it "makes exposures available to layout" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app_with_users'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app_with_users"
config.template = "users"
config.default_format = :html
expose :users_count, layout: true
@ -433,8 +433,8 @@ RSpec.describe 'exposures' do
end.new
users = [
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
expect(view.(users: users, users_count: users.size, context: context).to_s).to eql(

View File

@ -1,9 +1,9 @@
# frozen_string_literal: true
require 'dry/core/inflector'
require 'dry/view/scope_builder'
require "dry/core/inflector"
require "dry/view/scope_builder"
RSpec.describe 'Part / Decorated attributes' do
RSpec.describe "Part / Decorated attributes" do
let(:article_class) {
Class.new do
attr_reader :title, :author, :comments
@ -37,16 +37,16 @@ RSpec.describe 'Part / Decorated attributes' do
end
}
let (:author) {
author_class.new(name: 'Jane Doe')
let(:author) {
author_class.new(name: "Jane Doe")
}
let(:article) {
article_class.new(
title: 'Hello world',
title: "Hello world",
author: author,
comments: [
comment_class.new(author: author_class.new(name: 'Sue Smith'), body: 'Great article')
comment_class.new(author: author_class.new(name: "Sue Smith"), body: "Great article")
]
)
}
@ -55,7 +55,7 @@ RSpec.describe 'Part / Decorated attributes' do
article_part_class.new(
name: :article,
value: article,
render_env: render_env,
render_env: render_env
)
}
@ -65,15 +65,15 @@ RSpec.describe 'Part / Decorated attributes' do
inflector: Dry::Inflector.new,
context: Dry::View::Context.new,
scope_builder: Dry::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 }
describe 'decorating without options' do
describe 'multiple declarations' do
describe "decorating without options" do
describe "multiple declarations" do
let(:article_part_class) {
Class.new(Dry::View::Part) do
decorate :author
@ -81,43 +81,43 @@ RSpec.describe 'Part / Decorated attributes' do
end
}
it 'decorates attributes with the standard Dry::View::Part class' do
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
end
context 'falsey values' do
context "falsey values" do
let(:author) { nil }
it 'does not decorate the attributes' do
it "does not decorate the attributes" do
expect(article_part.author).to be_nil
end
end
end
describe 'single declaration' do
describe "single declaration" do
let(:article_part_class) {
Class.new(Dry::View::Part) do
decorate :author, :comments
end
}
it 'decorates attributes with the standard Dry::View::Part class' do
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
end
context 'falsey values' do
context "falsey values" do
let(:author) { nil }
it 'does not decorate the attributes' do
it "does not decorate the attributes" do
expect(article_part.author).to be_nil
end
end
end
end
describe 'decorating with part class specified' do
describe "decorating with part class specified" do
before do
module Test
class AuthorPart < Dry::View::Part
@ -135,22 +135,22 @@ RSpec.describe 'Part / Decorated attributes' do
end
}
it 'deorates attributes with the specified part class' do
it "deorates attributes with the specified part class" do
expect(article_part.author).to be_a Test::AuthorPart
expect(article_part.comments[0]).to be_a Test::CommentPart
end
context 'falsey values' do
context "falsey values" do
let(:author) { nil }
it 'does not decorate the attributes' do
it "does not decorate the attributes" do
expect(article_part.author).to be_nil
end
end
end
end
describe 'using custom part builder' do
describe "using custom part builder" do
let(:article_part_class) {
Class.new(Dry::View::Part) do
decorate :author
@ -183,16 +183,16 @@ RSpec.describe 'Part / Decorated attributes' do
end
end
it 'deorates attributes using the custom part builder' do
it "deorates attributes using the custom part builder" do
expect(article_part.author).to be_a Test::AuthorPart
expect(article_part.comments[0]).to be_a Test::CommentPart
expect(article_part.comments[0].author).to be_a Test::AuthorPart
end
context 'falsey values' do
context "falsey values" do
let(:author) { nil }
it 'does not decorate the attributes' do
it "does not decorate the attributes" do
expect(article_part.author).to be_nil
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
RSpec.describe 'part builder' do
RSpec.describe "part builder" do
before do
module Test
class Custom < Dry::View::Part
@ -19,12 +19,12 @@ RSpec.describe 'part builder' do
end
end
describe 'default decorator' do
it 'looks up classes from a part namespace' do
describe "default decorator" do
it "looks up classes from a part namespace" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil
config.template = 'decorated_parts'
config.template = "decorated_parts"
config.part_namespace = Test
expose :customs
@ -32,46 +32,46 @@ RSpec.describe 'part builder' do
expose :ordinary
end.new
expect(view.(customs: ['many things'], custom: 'custom thing', ordinary: 'ordinary thing').to_s).to eql(
'<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>'
expect(view.(customs: ["many things"], custom: "custom thing", ordinary: "ordinary thing").to_s).to eql(
"<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>"
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil
config.template = 'decorated_parts'
config.template = "decorated_parts"
expose :customs, as: Test::CustomPart
expose :custom, as: Test::CustomPart
expose :ordinary
end.new
expect(view.(customs: ['many things'], custom: 'custom thing', ordinary: 'ordinary thing').to_s).to eql(
'<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>'
expect(view.(customs: ["many things"], custom: "custom thing", ordinary: "ordinary thing").to_s).to eql(
"<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>"
)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil
config.template = 'decorated_parts'
config.template = "decorated_parts"
expose :customs, as: [Test::CustomArrayPart, Test::CustomPart]
expose :custom, as: Test::CustomPart
expose :ordinary
end.new
expect(view.(customs: ['many things'], custom: 'custom thing', ordinary: 'ordinary thing').to_s).to eql(
'<p>Custom part wrapping many things</p><p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>'
expect(view.(customs: ["many things"], custom: "custom thing", ordinary: "ordinary thing").to_s).to eql(
"<p>Custom part wrapping many things</p><p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>"
)
end
end
describe 'custom decorator and part classes' do
it 'supports wrapping in custom parts based on exposure names' 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
def part_class(name:, **options)
name == :custom ? Test::CustomPart : super
@ -80,15 +80,15 @@ RSpec.describe 'part builder' do
view = Class.new(Dry::View) do
config.part_builder = part_builder
config.paths = SPEC_ROOT.join('fixtures/templates')
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = nil
config.template = 'decorated_parts'
config.template = "decorated_parts"
expose :customs, :custom, :ordinary
end.new
expect(view.(customs: ['many things'], custom: 'custom thing', ordinary: 'ordinary thing').to_s).to eql(
'<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>'
expect(view.(customs: ["many things"], custom: "custom thing", ordinary: "ordinary thing").to_s).to eql(
"<p>Custom part wrapping many things</p><p>Custom part wrapping custom thing</p><p>ordinary thing</p>"
)
end
end

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true
require 'dry/view/part'
require 'dry/view/scope'
require "dry/view/part"
require "dry/view/scope"
RSpec.describe 'Scopes' do
RSpec.describe "Scopes" do
let(:base_view) {
Class.new(Dry::View) do
config.paths = FIXTURES_PATH.join('integration/scopes')
config.paths = FIXTURES_PATH.join("integration/scopes")
end
}
specify 'Custom scope for a view' do
specify "Custom scope for a view" do
module Test
class ControllerScope < Dry::View::Scope
def hello
@ -20,110 +20,110 @@ RSpec.describe 'Scopes' do
end
view = Class.new(base_view) do
config.template = 'custom_view_scope'
config.template = "custom_view_scope"
config.scope = Test::ControllerScope
expose :text
end.new
expect(view.(text: 'world').to_s).to eq 'Hello world!'
expect(view.(text: "world").to_s).to eq "Hello world!"
end
specify 'Rendering a partial via an anonymous scope' do
specify "Rendering a partial via an anonymous scope" do
view = Class.new(base_view) do
config.template = 'anonymous_scope'
config.template = "anonymous_scope"
expose :text
end.new
expect(view.(text: 'Hello').to_s).to eq 'Greeting: Hello'
expect(view.(text: "Hello").to_s).to eq "Greeting: Hello"
end
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
class Greeting < Dry::View::Scope
def greeting
_locals[:greeting].upcase + '!'
_locals[:greeting].upcase + "!"
end
end
end
view = Class.new(base_view) do
config.scope_namespace = Test::Scopes
config.template = 'named_scope_with_implicit_render'
config.template = "named_scope_with_implicit_render"
expose :text
end.new
expect(view.(text: 'Hello').to_s).to eq 'Greeting: HELLO!'
expect(view.(text: "Hello").to_s).to eq "Greeting: HELLO!"
end
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
class Greeting < Dry::View::Scope
def greeting
_locals[:greeting].upcase + '!'
_locals[:greeting].upcase + "!"
end
end
end
view = Class.new(base_view) do
config.scope_namespace = Test::Scopes
config.template = 'class_named_scope_with_implicit_render'
config.template = "class_named_scope_with_implicit_render"
expose :text
end.new
expect(view.(text: 'Hello').to_s).to eq 'Greeting: HELLO!'
expect(view.(text: "Hello").to_s).to eq "Greeting: HELLO!"
end
specify 'Raising an error when an unnamed partial cannot be rendered implicitly' do
specify "Raising an error when an unnamed partial cannot be rendered implicitly" do
view = Class.new(base_view) do
config.template = 'unnamed_named_scope_with_implicit_render'
config.template = "unnamed_named_scope_with_implicit_render"
end.new
expect { view.().to_s }.to raise_error ArgumentError, '+partial_name+ must be provided for unnamed scopes'
expect { view.().to_s }.to raise_error ArgumentError, "+partial_name+ must be provided for unnamed scopes"
end
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
class Greeting < Dry::View::Scope
def greeting
_locals[:greeting].upcase + '!'
_locals[:greeting].upcase + "!"
end
end
end
view = Class.new(base_view) do
config.scope_namespace = Test::Scopes
config.template = 'named_scope_with_explicit_render'
config.template = "named_scope_with_explicit_render"
expose :text
end.new
expect(view.(text: 'Hello').to_s).to eq 'Holler: HELLO!'
expect(view.(text: "Hello").to_s).to eq "Holler: HELLO!"
end
specify 'Custom named scope providing defaults for missing locals' do
specify "Custom named scope providing defaults for missing locals" do
module Test::Scopes
class Greeting < Dry::View::Scope
def greeting
_locals.fetch(:greeting) { 'Howdy' }
_locals.fetch(:greeting) { "Howdy" }
end
end
end
view = Class.new(base_view) do
config.scope_namespace = Test::Scopes
config.template = 'named_scope_with_defaults'
config.template = "named_scope_with_defaults"
expose :text
end.new
expect(view.().to_s).to eq 'Greeting: Howdy'
expect(view.().to_s).to eq "Greeting: Howdy"
end
specify 'Creating a custom scope from a view part' do
specify "Creating a custom scope from a view part" do
module Test::Parts
class Message < Dry::View::Part
def greeting
@ -135,7 +135,7 @@ RSpec.describe 'Scopes' do
module Test::Scopes
class Greeting < Dry::View::Scope
def greeting
_locals[:greeting] + '!'
_locals[:greeting] + "!"
end
end
end
@ -143,11 +143,11 @@ RSpec.describe 'Scopes' do
view = Class.new(base_view) do
config.part_namespace = Test::Parts
config.scope_namespace = Test::Scopes
config.template = 'scope_from_part'
config.template = "scope_from_part"
expose :message
end.new
expect(view.(message: { text: 'Hello from a part' }).to_s).to eq 'Greeting: Hello from a part!'
expect(view.(message: {text: "Hello from a part"}).to_s).to eq "Greeting: Hello from a part!"
end
end

View File

@ -1,25 +1,25 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/context'
require "dry/view"
require "dry/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) {
Class.new(Dry::View) do
config.paths = FIXTURES_PATH.join('integration/template_engines/erbse')
config.paths = FIXTURES_PATH.join("integration/template_engines/erbse")
end
}
context 'with erbse available' do
it 'supports partials that yield' do
context "with erbse available" do
it "supports partials that yield" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper> Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper> Yielded</wrapper>"
end
it 'supports context methods that yield' do
it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do
def wrapper
"<wrapper>#{yield}</wrapper>"
@ -28,19 +28,19 @@ RSpec.describe 'Template engines / erb (using erbse as default engine)' do
view = Class.new(base_view) do
config.default_context = context
config.template = 'method_with_yield'
config.template = "method_with_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper> Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper> Yielded</wrapper>"
end
end
context 'with erbse not available' do
context "with erbse not available" do
before do
@load_path = $LOAD_PATH.dup
@loaded_features = $LOADED_FEATURES.dup
$LOAD_PATH.reject! { |path| path =~ %r{erbse} }
$LOAD_PATH.reject! { |path| path =~ /erbse/ }
$LOADED_FEATURES.reject! { |path| path =~ %r{erbse|dry/view/tilt/erbse} }
Dry::View::Tilt.cache.clear
@ -53,23 +53,23 @@ RSpec.describe 'Template engines / erb (using erbse as default engine)' do
Dry::View::Tilt.register_adapter :erb, Dry::View::Tilt::ERB
end
it 'raises an error explaining the erbse requirement' do
it "raises an error explaining the erbse requirement" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect { view.() }.to raise_error(LoadError, %r{dry-view requires erbse}m)
expect { view.() }.to raise_error(LoadError, /dry-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
it "allows deregistering the adapter to avoid the load error and accept rendering via a less-compatible erb engine" do
view = Class.new(base_view) do
config.template = 'plain_erb'
config.template = "plain_erb"
end.new
Dry::View::Tilt.deregister_adapter :erb
expect { view.() }.not_to raise_error
expect(view.().to_s.strip).to eq 'Hello'
expect(view.().to_s.strip).to eq "Hello"
end
end
end

View File

@ -1,30 +1,30 @@
# frozen_string_literal: true
require 'erubi'
require 'erubi/capture_end'
require 'tilt/erubi'
require "erubi"
require "erubi/capture_end"
require "tilt/erubi"
require 'dry/view'
require 'dry/view/context'
require "dry/view"
require "dry/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) {
Class.new(Dry::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 }
config.paths = FIXTURES_PATH.join("integration/template_engines/erubi")
config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate}
config.renderer_options = {engine_class: Erubi::CaptureEndEngine}
end
}
it 'supports partials that yield' do
it "supports partials that yield" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper>Yielded</wrapper>"
end
it 'supports context methods that yield' do
it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do
def wrapper
"<wrapper>#{yield}</wrapper>"
@ -33,9 +33,9 @@ RSpec.describe 'Template engines / erb (using erubi via an explict engine mappin
view = Class.new(base_view) do
config.default_context = context
config.template = 'method_with_yield'
config.template = "method_with_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper>Yielded</wrapper>"
end
end

View File

@ -1,41 +1,41 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/context'
require "dry/view"
require "dry/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) {
Class.new(Dry::View) do
config.paths = FIXTURES_PATH.join('integration/template_engines/hamlit')
config.paths = FIXTURES_PATH.join("integration/template_engines/hamlit")
end
}
context 'with hamlit-block available' do
it 'supports partials that yield' do
context "with hamlit-block available" do
it "supports partials that yield" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper>Yielded</wrapper>"
end
it 'supports methods that yield' do
it "supports methods that yield" do
context = Class.new(Dry::View::Context) do
def wrapper(&block)
def wrapper
"<wrapper>#{yield}</wrapper>"
end
end.new
view = Class.new(base_view) do
config.default_context = context
config.template = 'method_with_yield'
config.template = "method_with_yield"
end.new
expect(view.().to_s.gsub(/\n\s*/m, '')).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s.gsub(/\n\s*/m, "")).to eq "<wrapper>Yielded</wrapper>"
end
end
context 'with hamlit-block not available' do
context "with hamlit-block not available" do
before do
@load_path = $LOAD_PATH.dup
@loaded_features = $LOADED_FEATURES.dup
@ -52,12 +52,12 @@ RSpec.describe 'Template engines / haml (using hamlit-block as default engine)'
$LOADED_FEATURES.replace @loaded_features
end
it 'raises an error explaining the hamlit-block requirement' do
it "raises an error explaining the hamlit-block requirement" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect { view.() }.to raise_error(LoadError, %r{dry-view requires hamlit-block}m)
expect { view.() }.to raise_error(LoadError, /dry-view requires hamlit-block/m)
end
end
end

View File

@ -1,25 +1,25 @@
# frozen_string_literal: true
require 'slim'
require 'dry/view'
require 'dry/view/context'
require "slim"
require "dry/view"
require "dry/view/context"
RSpec.describe 'Template engines / slim' do
RSpec.describe "Template engines / slim" do
let(:base_view) {
Class.new(Dry::View) do
config.paths = FIXTURES_PATH.join('integration/template_engines/slim')
config.paths = FIXTURES_PATH.join("integration/template_engines/slim")
end
}
it 'supports partials that yield' do
it "supports partials that yield" do
view = Class.new(base_view) do
config.template = 'render_and_yield'
config.template = "render_and_yield"
end.new
expect(view.().to_s).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s).to eq "<wrapper>Yielded</wrapper>"
end
it 'supports context methods that yield' do
it "supports context methods that yield" do
context = Class.new(Dry::View::Context) do
def wrapper
"<wrapper>#{yield}</wrapper>"
@ -28,9 +28,9 @@ RSpec.describe 'Template engines / slim' do
view = Class.new(base_view) do
config.default_context = context
config.template = 'method_with_yield'
config.template = "method_with_yield"
end.new
expect(view.().to_s).to eq '<wrapper>Yielded</wrapper>'
expect(view.().to_s).to eq "<wrapper>Yielded</wrapper>"
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
RSpec.describe 'Testing / parts' do
RSpec.describe "Testing / parts" do
let(:part_class) {
Class.new(Dry::View::Part) do
end
@ -9,21 +9,21 @@ RSpec.describe 'Testing / parts' 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
def breaking_news_title
title + '!'
title + "!"
end
end
article = Struct.new(:title).new('Giant Hand Threatens Beach City')
article = Struct.new(:title).new("Giant Hand Threatens Beach City")
article_part = part_class.new(value: article)
expect(article_part.breaking_news_title).to eq 'Giant Hand Threatens Beach City!'
expect(article_part.breaking_news_title).to eq "Giant Hand Threatens Beach City!"
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
config.paths = FIXTURES_PATH.join('integration/testing')
config.template = 'view'
config.paths = FIXTURES_PATH.join("integration/testing")
config.template = "view"
end
part_class = Class.new(Dry::View::Part) do
@ -32,12 +32,12 @@ RSpec.describe 'Testing / parts' do
end
end
article = Struct.new(:title).new('A Guide to Beach City Funland')
article = Struct.new(:title).new("A Guide to Beach City Funland")
article_part = part_class.new(
name: :article,
value: article,
render_env: view_class.template_env,
render_env: view_class.template_env
)
expect(article_part.feature_box).to eq %(

View File

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

View File

@ -1,13 +1,13 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/context'
require "dry/view"
require "dry/view/context"
RSpec.describe 'View / exposures' do
specify 'exposures have access to context' do
RSpec.describe "View / exposures" do
specify "exposures have access to context" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting"
expose :greeting do |greeting:, context:|
"#{greeting}, #{context.name}"
@ -16,12 +16,12 @@ RSpec.describe 'View / exposures' do
context = Class.new(Dry::View::Context) do
def name
'Jane'
"Jane"
end
end.new
local = view.(greeting: 'Hello', context: context).locals[:greeting]
local = view.(greeting: "Hello", context: context).locals[:greeting]
expect(local.value).to eq 'Hello, Jane'
expect(local.value).to eq "Hello, Jane"
end
end

View File

@ -1,32 +1,32 @@
# frozen_string_literal: true
require 'dry/view'
require 'dry/view/part'
require "dry/view"
require "dry/view/part"
RSpec.describe 'View / locals' do
specify 'locals are decorated with parts by default' do
RSpec.describe "View / locals" do
specify "locals are decorated with parts by default" do
view = Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting"
expose :greeting
end.new
local = view.(greeting: 'Hello').locals[:greeting]
local = view.(greeting: "Hello").locals[:greeting]
expect(local).to be_a(Dry::View::Part)
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
config.paths = SPEC_ROOT.join('fixtures/templates')
config.template = 'greeting'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "greeting"
expose :greeting, decorate: false
end.new
local = view.(greeting: 'Hello').locals[:greeting]
local = view.(greeting: "Hello").locals[:greeting]
expect(local).to eq 'Hello'
expect(local).to eq "Hello"
end
end

View File

@ -1,19 +1,17 @@
# frozen_string_literal: true
# coding: utf-8
RSpec.describe 'dry-view' do
RSpec.describe "dry-view" do
let(:view_class) do
Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'users'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "users"
config.default_format = :html
expose :users do
[
{ name: 'Jane', email: 'jane@doe.org' },
{ name: 'Joe', email: 'joe@doe.org' }
{name: "Jane", email: "jane@doe.org"},
{name: "Joe", email: "joe@doe.org"}
]
end
end
@ -22,7 +20,7 @@ RSpec.describe 'dry-view' do
let(:context) {
Class.new(Dry::View::Context) do
def title
'dry-view rocks!'
"dry-view rocks!"
end
def assets
@ -31,7 +29,7 @@ RSpec.describe 'dry-view' do
end.new
}
it 'renders within a layout and makes the provided context available everywhere' do
it "renders within a layout and makes the provided context available everywhere" do
view = view_class.new
expect(view.(context: context).to_s).to eql(
@ -39,7 +37,7 @@ RSpec.describe 'dry-view' do
)
end
it 'renders without a layout' do
it "renders without a layout" do
view = Class.new(view_class) do
config.layout = false
end.new
@ -49,18 +47,18 @@ RSpec.describe 'dry-view' do
)
end
it 'renders a view with an alternative format and engine' do
it "renders a view with an alternative format and engine" do
view = view_class.new
# FIXME: there should be a "\n\n" before "* Jane", but this is missing due to https://github.com/apotonick/erbse/issues/10
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!* Jane (jane@doe.org)\n* Joe (joe@doe.org)"
)
end
it 'renders a view with a template on another view path' do
it "renders a view with a template on another view path" do
view = Class.new(view_class) do
config.paths = [SPEC_ROOT.join('fixtures/templates_override')] + Array(config.paths)
config.paths = [SPEC_ROOT.join("fixtures/templates_override")] + Array(config.paths)
end.new
expect(view.(context: context).to_s).to eq(
@ -68,9 +66,9 @@ RSpec.describe 'dry-view' do
)
end
it 'renders a view that passes arguments to partials' do
it "renders a view that passes arguments to partials" do
view = Class.new(view_class) do
config.template = 'parts_with_args'
config.template = "parts_with_args"
end.new
expect(view.(context: context).to_s).to eq(
@ -78,47 +76,47 @@ RSpec.describe 'dry-view' do
)
end
it 'renders using utf-8 by default' do
it "renders using utf-8 by default" do
view = Class.new(view_class) do
config.template = 'utf8'
config.template = "utf8"
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>dry-view rocks!</title></head><body>ç</body></html>"
)
end
describe 'inheritance' do
describe "inheritance" do
let(:parent_view) do
klass = Class.new(Dry::View)
klass.setting :paths, SPEC_ROOT.join('fixtures/templates')
klass.setting :layout, 'app'
klass.setting :formats, { html: :slim }
klass.setting :paths, SPEC_ROOT.join("fixtures/templates")
klass.setting :layout, "app"
klass.setting :formats, html: :slim
klass
end
let(:child_view) do
Class.new(parent_view) do
config.template = 'tasks'
config.template = "tasks"
end
end
it 'renders within a parent class layout using provided context' do
it "renders within a parent class layout using provided context" do
view = Class.new(view_class) do
config.template = 'tasks'
config.template = "tasks"
expose :tasks do
[
{ title: 'one' },
{ title: 'two' },
{title: "one"},
{title: "two"}
]
end
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>dry-view rocks!</title></head><body><ol><li>one</li><li>two</li></ol></body></html>"
)
end
end

View File

@ -1,15 +1,15 @@
# frozen_string_literal: true
require_relative 'support/coverage'
require_relative "support/coverage"
begin
require 'pry-byebug'
require "pry-byebug"
rescue LoadError; end
SPEC_ROOT = Pathname(__FILE__).dirname
FIXTURES_PATH = SPEC_ROOT.join('fixtures')
FIXTURES_PATH = SPEC_ROOT.join("fixtures")
require 'slim'
require 'dry/view'
require "slim"
require "dry/view"
module Test
def self.remove_constants
@ -34,7 +34,7 @@ RSpec.configure do |config|
Dry::View::Path,
Dry::View::Renderer,
Dry::View::ScopeBuilder,
Dry::View::Tilt,
Dry::View::Tilt
].each do |klass|
klass.cache.clear
end

View File

@ -1,9 +1,9 @@
# frozen_string_literal: true
require 'dry/view/context'
require 'dry/view/part'
require 'dry/view/part_builder'
require 'dry/view/scope_builder'
require "dry/view/context"
require "dry/view/part"
require "dry/view/part_builder"
require "dry/view/scope_builder"
RSpec.describe Dry::View::Context do
let(:context_class) {
@ -30,38 +30,38 @@ RSpec.describe Dry::View::Context do
renderer: double(:renderer),
context: Dry::View::Context.new,
part_builder: Dry::View::PartBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new,
scope_builder: Dry::View::ScopeBuilder.new
)
}
subject(:context) { context_class.new(assets: assets, routes: routes) }
describe 'attribute readers' do
it 'provides access to its attributes' do
describe "attribute readers" do
it "provides access to its attributes" do
expect(context.assets).to eql assets
end
end
context 'with render environment' do
context "with render environment" do
subject(:context) {
context_class.new(assets: assets, routes: routes).for_render_env(render_env)
}
describe 'attribute readers' do
it 'provides attributes decorated in view parts' 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.value).to eql assets
end
end
end
describe '#with' do
it 'returns a copy of the context with extra options' do
describe "#with" do
it "returns a copy of the context with extra options" do
another_option = double(:another_option)
new_context = context.with(another_option: another_option)
expect(new_context).to be_a(context.class)
expect(new_context._options).to eq({ assets: context.assets, routes: routes, another_option: another_option })
expect(new_context._options).to eq(assets: context.assets, routes: routes, another_option: another_option)
end
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/view/decorated_attributes'
require "dry/view/decorated_attributes"
RSpec.describe Dry::View::DecoratedAttributes do
subject(:decoratable) {
@ -19,38 +19,38 @@ RSpec.describe Dry::View::DecoratedAttributes do
let(:attr_2) { double(:attr_2) }
let(:render_env) { spy(:render_env) }
context 'with render environment' do
it 'returns decorated attributes as parts' do
context "with render environment" do
it "returns decorated attributes as parts" do
decoratable.attr_1
expect(render_env).to have_received(:part).with(:attr_1, attr_1, as: :my_value)
decoratable.attr_2
if RUBY_VERSION >= '2.7'
if RUBY_VERSION >= "2.7"
expect(render_env).to have_received(:part).with(:attr_2, attr_2)
else
expect(render_env).to have_received(:part).with(:attr_2, attr_2, {})
end
end
it 'raises NoMethodError when an invalid attribute is accessed' do
it "raises NoMethodError when an invalid attribute is accessed" do
expect { decoratable.invalid_attr }.to raise_error(NoMethodError)
end
end
context 'without render environment' do
context "without render environment" do
let(:render_env) { nil }
it 'returns attributes without decoration' do
it "returns attributes without decoration" do
expect(decoratable.attr_1).to be attr_1
end
it 'raises NoMethodError when an invalid attribute is accessed' do
it "raises NoMethodError when an invalid attribute is accessed" do
expect { decoratable.invalid_attr }.to raise_error(NoMethodError)
end
end
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[0].inspect).to eq '#<Dry::View::DecoratedAttributes::Attributes[:attr_1, :attr_2, :invalid_attr]>'
expect(decoratable.class.ancestors[0].inspect).to eq "#<Dry::View::DecoratedAttributes::Attributes[:attr_1, :attr_2, :invalid_attr]>"
end
end

View File

@ -3,94 +3,94 @@
RSpec.describe Dry::View::Exposure do
subject(:exposure) { described_class.new(:hello, proc, object, **options) }
let(:proc) { -> input { 'hi' } }
let(:proc) { -> _input { "hi" } }
let(:object) { nil }
let(:options) { {} }
describe 'initialization and attributes' do
describe '#name' do
it 'accepts a name' do
describe "initialization and attributes" do
describe "#name" do
it "accepts a name" do
expect(exposure.name).to eql :hello
end
end
describe '#proc' do
it 'accepts a proc' do
describe "#proc" do
it "accepts a proc" do
expect(exposure.proc).to eql proc
end
it 'allows a nil proc' do
it "allows a nil proc" do
expect(described_class.new(:hello).proc).to be_nil
end
end
describe '#object' do
describe "#object" do
let(:object) { Object.new }
it 'accepts an object' do
it "accepts an object" do
expect(exposure.object).to eq object
end
it 'allows a nil object' do
it "allows a nil object" do
expect(described_class.new(:hello).object).to be_nil
end
end
describe '#decorate?' do
it 'is true by default' do
describe "#decorate?" do
it "is true by default" do
expect(exposure.decorate?).to eq true
end
it 'can be set on initialization' do
it "can be set on initialization" do
expect(described_class.new(:hello, decorate: false).decorate?).to eq false
end
end
describe '#private?' do
it 'is false by default' do
describe "#private?" do
it "is false by default" do
expect(exposure).not_to be_private
end
it 'can be set on initialization' do
it "can be set on initialization" do
expect(described_class.new(:hello, private: true)).to be_private
end
end
describe '#default_value' do
it 'is nil by default' do
describe "#default_value" do
it "is nil by default" do
expect(exposure.default_value).to be_nil
end
it 'can be set on initialization' do
exposuse = described_class.new(:hello, default: 'Hi !')
expect(exposuse.default_value).to eq('Hi !')
it "can be set on initialization" do
exposuse = described_class.new(:hello, default: "Hi !")
expect(exposuse.default_value).to eq("Hi !")
end
end
end
describe '#bind' do
describe "#bind" do
subject(:bound_exposure) { exposure.bind(bind_object) }
let(:bind_object) { Object.new }
it 'returns a new object' do
it "returns a new object" do
expect(bound_exposure).not_to eql exposure
end
it 'retains the bind object' do
it "retains the bind object" do
expect(bound_exposure.object).to eq bind_object
end
context 'proc is set' do
it 'retains the existing proc' do
context "proc is set" do
it "retains the existing proc" do
expect(bound_exposure.proc).to eql proc
end
end
context 'proc is nil' do
context "proc is nil" do
let(:proc) { nil }
context 'matching instance method' do
context "matching instance method" do
let(:bind_object) do
Class.new do
def hello(input)
@ -104,31 +104,31 @@ RSpec.describe Dry::View::Exposure do
end
end
context 'no matching instance method' do
context "no matching instance method" do
let(:object) { Object.new }
it 'leaves proc as nil' do
it "leaves proc as nil" do
expect(bound_exposure.proc).to be_nil
end
end
end
end
describe '#dependency_names' do
context 'proc provided' do
let(:proc) { -> input, foo, bar { 'hi' } }
describe "#dependency_names" do
context "proc provided" do
let(:proc) { -> input, foo, bar { "hi" } } # rubocop:disable Lint/UnusedBlockArgument
it "returns an array of exposure dependencies derived from the proc's argument names" do
expect(exposure.dependency_names).to eql [:input, :foo, :bar]
end
end
context 'matching instance method' do
context "matching instance method" do
let(:proc) { nil }
let(:object) do
Class.new do
def hello(input, bar, baz)
def hello(input, bar, baz) # rubocop:disable Lint/UnusedMethodArgument
"hi there, #{input.fetch(:name)}"
end
end.new
@ -139,73 +139,73 @@ RSpec.describe Dry::View::Exposure do
end
end
context 'proc is nil' do
context "proc is nil" do
let(:proc) { nil }
it 'returns no dependencies' do
it "returns no dependencies" do
expect(exposure.dependency_names).to eql []
end
end
end
describe '#call' do
let(:input) { { name: 'Jane' } }
describe "#call" do
let(:input) { {name: "Jane"} }
context 'proc expects input only' do
context "proc expects input only" do
let(:proc) { -> name: { name } }
it 'sends the input to the proc' do
expect(exposure.(input)).to eql 'Jane'
it "sends the input to the proc" do
expect(exposure.(input)).to eql "Jane"
end
end
context 'proc expects input and dependencies' do
context "proc expects input and dependencies" do
let(:proc) { -> greeting, name: { "#{greeting}, #{name}" } }
let(:locals) { { greeting: 'Hola' } }
let(:locals) { {greeting: "Hola"} }
it 'sends the input and dependency values to the proc' do
expect(exposure.(input, locals)).to eq 'Hola, Jane'
it "sends the input and dependency values to the proc" do
expect(exposure.(input, locals)).to eq "Hola, Jane"
end
end
context 'Default value' do
let(:options) { { default: 'John' } }
context "Default value" do
let(:options) { {default: "John"} }
context 'use default value' do
context "use default value" do
let(:proc) { nil }
it 'use the default value' do
expect(exposure.({})).to eq 'John'
it "use the default value" do
expect(exposure.({})).to eq "John"
end
end
context 'use input value instead of default' do
context "use input value instead of default" do
let(:proc) { nil }
it 'use the default value' do
expect(exposure.({ hello: 'Jane' })).to eq 'Jane'
it "use the default value" do
expect(exposure.(hello: "Jane")).to eq "Jane"
end
end
context 'use input value over default even when input is nil' do
context "use input value over default even when input is nil" do
let(:proc) { nil }
it 'use the default value' do
expect(exposure.({ hello: nil })).to eq nil
it "use the default value" do
expect(exposure.(hello: nil)).to eq nil
end
end
end
context 'proc expects dependencies only' do
context "proc expects dependencies only" do
let(:proc) { -> greeting, farewell { "#{greeting}, #{farewell}" } }
let(:locals) { { greeting: 'Hola', farewell: 'Adios' } }
let(:locals) { {greeting: "Hola", farewell: "Adios"} }
it 'sends the dependency values to the proc' do
expect(exposure.(input, locals)).to eq 'Hola, Adios'
it "sends the dependency values to the proc" do
expect(exposure.(input, locals)).to eq "Hola, Adios"
end
end
context 'proc accesses object instance' do
context "proc accesses object instance" do
let(:proc) { -> name: { "My name is #{name} but call me #{title} #{name}" } }
let(:object) do
@ -215,23 +215,23 @@ RSpec.describe Dry::View::Exposure do
def initialize(title)
@title = title
end
end.new('Dr')
end.new("Dr")
end
it 'makes the instance available as self' do
expect(exposure.(input)).to eq 'My name is Jane but call me Dr Jane'
it "makes the instance available as self" do
expect(exposure.(input)).to eq "My name is Jane but call me Dr Jane"
end
end
context 'no proc' do
context "no proc" do
let(:proc) { nil }
let(:input) { { hello: 'hi there' } }
let(:input) { {hello: "hi there"} }
it 'returns a matching key from the input' do
expect(exposure.(input)).to eq 'hi there'
it "returns a matching key from the input" do
expect(exposure.(input)).to eq "hi there"
end
it 'returns nil when no input key matches' do
it "returns nil when no input key matches" do
expect(exposure.(nothing_matches_here: true)).to be_nil
end
end

View File

@ -3,15 +3,15 @@
RSpec.describe Dry::View::Exposures do
subject(:exposures) { described_class.new }
describe '#exposures' do
it 'is empty by defalut' do
describe "#exposures" do
it "is empty by defalut" do
expect(exposures.exposures).to be_empty
end
end
describe '#add' do
it 'creates and adds an exposure' do
proc = -> **input { 'hi' }
describe "#add" do
it "creates and adds an exposure" do
proc = -> **_input { "hi" }
exposures.add :hello, proc
expect(exposures[:hello].name).to eq :hello
@ -19,13 +19,13 @@ RSpec.describe Dry::View::Exposures do
end
end
describe '#bind' do
describe "#bind" do
subject(:bound_exposures) { exposures.bind(object) }
let(:object) do
Class.new do
def hello(input)
'hi'
def hello(_input)
"hi"
end
end.new
end
@ -34,91 +34,91 @@ RSpec.describe Dry::View::Exposures do
exposures.add(:hello)
end
it 'binds each of the exposures' do
it "binds each of the exposures" do
expect(bound_exposures[:hello].proc).to eq object.method(:hello)
end
it 'returns a new copy of the exposures' do
it "returns a new copy of the exposures" do
expect(exposures.exposures).not_to eql(bound_exposures.exposures)
end
end
describe '#call' do
describe 'in general' do
describe "#call" do
describe "in general" do
before do
exposures.add(:greeting, -> greeting: { greeting.upcase })
exposures.add(:farewell, -> greeting { "#{greeting} and goodbye" })
end
subject(:locals) { exposures.(greeting: 'hello') }
subject(:locals) { exposures.(greeting: "hello") }
it 'returns the values from calling the exposures' do
expect(locals).to eq(greeting: 'HELLO', farewell: 'HELLO and goodbye')
it "returns the values from calling the exposures" do
expect(locals).to eq(greeting: "HELLO", farewell: "HELLO and goodbye")
end
it 'does not include values from private exposures' do
exposures.add(:hidden, -> **input { 'shh' }, private: true)
it "does not include values from private exposures" do
exposures.add(:hidden, -> **_input { "shh" }, private: true)
expect(locals).to include(:greeting, :farewell)
expect(locals).not_to include(:hidden)
end
end
describe 'with block provided' do
describe "with block provided" do
before do
exposures.add(:greeting, -> greeting: { greeting.upcase })
exposures.add(:farewell, -> greeting { "#{greeting} and goodbye" })
end
subject(:locals) {
exposures.(greeting: 'hello') do |value, exposure|
exposures.(greeting: "hello") do |value, exposure|
"#{value} from #{exposure.name}"
end
}
it 'provides values determined from the block' do
it "provides values determined from the block" do
expect(locals).to eq(
greeting: 'HELLO from greeting',
farewell: 'HELLO from greeting and goodbye from farewell',
greeting: "HELLO from greeting",
farewell: "HELLO from greeting and goodbye from farewell"
)
end
end
describe 'with default exposure values' do
describe "with default exposure values" do
it "returns 'default_value' from exposure" do
exposures.add(:name, default: 'John')
exposures.add(:name, default: "John")
locals = exposures.({})
expect(locals).to eq(name: 'John')
expect(locals).to eq(name: "John")
end
it 'returns values from arguments' do
exposures.add(:name, default: 'John')
locals = exposures.(name: 'William')
it "returns values from arguments" do
exposures.add(:name, default: "John")
locals = exposures.(name: "William")
expect(locals).to eq(name: 'William')
expect(locals).to eq(name: "William")
end
it 'returns values from arguments even when value is nil' do
exposures.add(:name, default: 'John')
it "returns values from arguments even when value is nil" do
exposures.add(:name, default: "John")
locals = exposures.(name: nil)
expect(locals).to eq(name: nil)
end
it 'returns value from proc' do
exposures.add(:name, -> name: { name.upcase }, default: 'John')
locals = exposures.(name: 'William')
it "returns value from proc" do
exposures.add(:name, -> name: { name.upcase }, default: "John")
locals = exposures.(name: "William")
expect(locals).to eq(name: 'WILLIAM')
expect(locals).to eq(name: "WILLIAM")
end
end
end
describe '#import' do
it 'imports an exposure to the set' do
describe "#import" do
it "imports an exposure to the set" do
exposures_b = described_class.new
exposures.add(:name, -> name: { name.upcase }, default: 'John')
exposures.add(:name, -> name: { name.upcase }, default: "John")
exposures_b.import(:name, exposures[:name])
expect(exposures_b[:name]).to eq(exposures[:name])

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'dry/view/scope_builder'
require "dry/view/scope_builder"
RSpec.describe Dry::View::PartBuilder do
subject(:part_builder) { render_env.part_builder }
@ -17,7 +17,7 @@ RSpec.describe Dry::View::PartBuilder do
let(:namespace) { nil }
describe '#call' do
describe "#call" do
subject(:part) {
part_builder.(name, value, **options)
}
@ -26,31 +26,31 @@ RSpec.describe Dry::View::PartBuilder do
let(:value) { double(:user) }
let(:options) { {} }
shared_examples 'a view part' do
shared_examples "a view part" do
let(:part_class) { Dry::View::Part }
it 'returns a part' do
it "returns a part" do
expect(part).to be_a part_class
end
it 'wraps the value' do
it "wraps the value" do
expect(part._value).to eq value
end
it 'retains the render environment' do
it "retains the render environment" do
expect(part._render_env).to eql render_env
end
end
shared_examples 'a view part collection' do
shared_examples "a view part collection" do
let(:collection_part_class) { Dry::View::Part }
let(:item_part_class) { Dry::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
end
it 'wraps the collection and its items' do
it "wraps the collection and its items" do
expect(part._value.map(&:_value)).to eq value
end
@ -61,70 +61,70 @@ RSpec.describe Dry::View::PartBuilder do
end
end
context 'without namespace' do
describe 'singular value' do
let(:value) { double('user') }
context "without namespace" do
describe "singular value" do
let(:value) { double("user") }
it_behaves_like 'a view part'
it_behaves_like "a view part"
describe 'alternative name provided via :as option' do
let(:options) { { as: :admin_user } }
describe "alternative name provided via :as option" do
let(:options) { {as: :admin_user} }
it_behaves_like 'a view part'
it_behaves_like "a view part"
end
describe 'explicit part class provided via as: option' do
describe "explicit part class provided via as: option" do
before do
Test::UserPart = Class.new(Dry::View::Part)
end
let(:options) { { as: Test::UserPart } }
let(:options) { {as: Test::UserPart} }
it_behaves_like 'a view part' do
it_behaves_like "a view part" do
let(:part_class) { Test::UserPart }
end
end
end
describe 'array-like value' do
describe "array-like value" do
let(:name) { :users }
let(:value) { [double(:user), double(:user)] }
it_behaves_like 'a view part collection'
it_behaves_like "a view part collection"
describe 'alternative name provided via :as option' do
let(:options) { { as: :admin_user } }
describe "alternative name provided via :as option" do
let(:options) { {as: :admin_user} }
it_behaves_like 'a view part collection'
it_behaves_like "a view part collection"
end
describe 'explicit part class provided via as: option' do
describe "explicit part class provided via as: option" do
before do
Test::UserPart = Class.new(Dry::View::Part)
end
let(:options) { { as: Test::UserPart } }
let(:options) { {as: Test::UserPart} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:item_part_class) { Test::UserPart }
end
end
describe 'explicit collection part class provided via as: option' do
describe "explicit collection part class provided via as: option" do
before do
Test::UserCollectionPart = Class.new(Dry::View::Part)
end
let(:options) { { as: [Test::UserCollectionPart] } }
let(:options) { {as: [Test::UserCollectionPart]} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::UserCollectionPart }
end
end
end
end
context 'with namespace' do
context "with namespace" do
before do
module Test
module Parts
@ -152,100 +152,100 @@ RSpec.describe Dry::View::PartBuilder do
let(:namespace) { Test::Parts }
describe 'singular value' do
let(:value) { double('user', profile: 'profile') }
describe "singular value" do
let(:value) { double("user", profile: "profile") }
it_behaves_like 'a view part' do
it_behaves_like "a view part" do
let(:part_class) { Test::Parts::User }
end
it 'returns decorated attributes in part classes found from the namespace' do
it "returns decorated attributes in part classes found from the namespace" do
expect(part.profile).to be_a Test::Parts::Profile
end
describe 'alternative name provided via :as option' do
let(:options) { { as: :admin_user } }
describe "alternative name provided via :as option" do
let(:options) { {as: :admin_user} }
it_behaves_like 'a view part' do
it_behaves_like "a view part" do
let(:part_class) { Test::Parts::AdminUser }
end
end
describe 'alternative name provided via :as option, when matched constant is not a class inheriting from Dry::View::Part' do
let(:options) { { as: :user_module } }
describe "alternative name provided via :as option, when matched constant is not a class inheriting from Dry::View::Part" do
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 }
end
end
describe 'explicit part class provided via as: option' do
let(:options) { { as: Test::Parts::AdminUser } }
describe "explicit part class provided via as: option" do
let(:options) { {as: Test::Parts::AdminUser} }
it_behaves_like 'a view part' do
it_behaves_like "a view part" do
let(:part_class) { Test::Parts::AdminUser }
end
end
end
describe 'array-like value' do
describe "array-like value" do
let(:name) { :users }
let(:value) { [double(:user), double(:user)] }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::Users }
let(:item_part_class) { Test::Parts::User }
end
describe 'alternative element name provided via :as option' do
let(:options) { { as: :admin_user } }
describe "alternative element name provided via :as option" do
let(:options) { {as: :admin_user} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::Users }
let(:item_part_class) { Test::Parts::AdminUser }
end
end
describe 'alternative collection name provided via :as option' do
let(:options) { { as: [:user_collection] } }
describe "alternative collection name provided via :as option" do
let(:options) { {as: [:user_collection]} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::UserCollection }
let(:item_part_class) { Test::Parts::User }
end
end
describe 'alternative collection and element names provided via :as option' do
let(:options) { { as: [:user_collection, :admin_user] } }
describe "alternative collection and element names provided via :as option" do
let(:options) { {as: [:user_collection, :admin_user]} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::UserCollection }
let(:item_part_class) { Test::Parts::AdminUser }
end
end
describe 'explicit part class provided via as: option' do
let(:options) { { as: Test::Parts::AdminUser } }
describe "explicit part class provided via as: option" do
let(:options) { {as: Test::Parts::AdminUser} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::Users }
let(:item_part_class) { Test::Parts::AdminUser }
end
end
describe 'explicit collection part class provided via as: option' do
let(:options) { { as: [Test::Parts::UserCollection] } }
describe "explicit collection part class provided via as: option" do
let(:options) { {as: [Test::Parts::UserCollection]} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::UserCollection }
let(:item_part_class) { Test::Parts::User }
end
end
describe 'explicit collection and element part classes provided via :as option' do
let(:options) { { as: [Test::Parts::UserCollection, Test::Parts::AdminUser] } }
describe "explicit collection and element part classes provided via :as option" do
let(:options) { {as: [Test::Parts::UserCollection, Test::Parts::AdminUser]} }
it_behaves_like 'a view part collection' do
it_behaves_like "a view part collection" do
let(:collection_part_class) { Test::Parts::UserCollection }
let(:item_part_class) { Test::Parts::AdminUser }
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'dry/view/scope_builder'
require 'dry/view/render_environment_missing'
require "dry/view/scope_builder"
require "dry/view/render_environment_missing"
RSpec::Matchers.define :scope do |locals|
match do |actual|
@ -18,89 +18,89 @@ RSpec.describe Dry::View::Part do
inflector: Dry::Inflector.new,
context: Dry::View::Context.new,
scope_builder: Dry::View::ScopeBuilder.new,
part_builder: Dry::View::ScopeBuilder.new,
part_builder: Dry::View::ScopeBuilder.new
)
}
let(:renderer) { spy(:renderer, format: :xml) }
context 'with a render environment' do
context "with a render environment" do
subject(:part) {
described_class.new(
name: name,
value: value,
render_env: render_env,
render_env: render_env
)
}
describe '#render' do
it 'renders a partial with the part available in its scope' do
describe "#render" do
it "renders a partial with the part available in its scope" do
part.render(:info)
expect(renderer).to have_received(:partial).with(:info, scope(user: part))
end
it 'allows the part to be made available on a different name' do
it "allows the part to be made available on a different name" do
part.render(:info, as: :admin)
expect(renderer).to have_received(:partial).with(:info, scope(admin: part))
end
it 'includes extra locals in the scope' do
part.render(:info, extra_local: 'hello')
expect(renderer).to have_received(:partial).with(:info, scope(user: part, extra_local: 'hello'))
it "includes extra locals in the scope" do
part.render(:info, extra_local: "hello")
expect(renderer).to have_received(:partial).with(:info, scope(user: part, extra_local: "hello"))
end
end
describe '#to_s' do
describe "#to_s" do
before do
allow(value).to receive(:to_s).and_return 'to_s on the value'
allow(value).to receive(:to_s).and_return "to_s on the value"
end
it 'delegates to the wrapped value' do
expect(part.to_s).to eq 'to_s on the value'
it "delegates to the wrapped value" do
expect(part.to_s).to eq "to_s on the value"
end
end
describe '#new' do
it 'preserves render environment' do
new_part = part.new(value: 'new value')
describe "#new" do
it "preserves render environment" do
new_part = part.new(value: "new value")
expect(new_part._render_env).to be part._render_env
end
end
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>>'
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>>"
end
end
describe '#_format' do
describe "#_format" do
it "returns the render environment's format" do
expect(part._format).to eq :xml
end
end
describe '#method_missing' do
let(:value) { double(greeting: 'hello from value') }
describe "#method_missing" do
let(:value) { double(greeting: "hello from value") }
it 'calls a matching method on the value' do
expect(part.greeting).to eq 'hello from value'
it "calls a matching method on the value" do
expect(part.greeting).to eq "hello from value"
end
it 'forwards all arguments to the method' do
it "forwards all arguments to the method" do
blk = -> {}
part.greeting 'args', &blk
part.greeting "args", &blk
expect(value).to have_received(:greeting).with('args', &blk)
expect(value).to have_received(:greeting).with("args", &blk)
end
it 'raises an error if no method matches' do
it "raises an error if no method matches" do
expect { part.farewell }.to raise_error(NoMethodError)
end
end
describe '#respond_to?' do
let(:value) { double(greeting: 'hello from value') }
describe "#respond_to?" do
let(:value) { double(greeting: "hello from value") }
it 'handles convenience methods' do
it "handles convenience methods" do
expect(part).to respond_to(:format)
expect(part).to respond_to(:context)
expect(part).to respond_to(:render)
@ -108,42 +108,42 @@ RSpec.describe Dry::View::Part do
expect(part).to respond_to(:value)
end
it 'handles value methods' do
it "handles value methods" do
expect(part).to respond_to(:greeting)
end
end
end
context 'without a render environment' do
context "without a render environment" do
subject(:part) {
described_class.new(
name: name,
value: value,
value: value
)
}
describe '#format' do
it 'raises an error' do
describe "#format" do
it "raises an error" do
expect { part.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end
describe '#render' do
it 'raises an error' do
describe "#render" do
it "raises an error" do
expect { part.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end
describe '#scope' do
it 'raises an error' do
describe "#scope" do
it "raises an error" do
expect { part.scope(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end
end
context 'without a name provided' do
describe '#_name' do
context 'when class has a name' do
context "without a name provided" do
describe "#_name" do
context "when class has a name" do
before do
Test::MyPart = Class.new(Dry::View::Part)
end
@ -152,18 +152,18 @@ RSpec.describe Dry::View::Part do
Test::MyPart.new(value: value)
}
it 'is inferred from the class name' do
expect(part._name).to eq 'my_part'
it "is inferred from the class name" do
expect(part._name).to eq "my_part"
end
end
context 'when class is anonymous' do
context "when class is anonymous" do
subject(:part) {
Class.new(Dry::View::Part).new(value: value)
}
it "defaults to 'part'" do
expect(part._name).to eq 'part'
expect(part._name).to eq "part"
end
end
end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true
require 'dry/view/render_environment'
require "dry/view/render_environment"
require 'dry/inflector'
require 'dry/view/context'
require 'dry/view/part_builder'
require 'dry/view/scope_builder'
require "dry/inflector"
require "dry/view/context"
require "dry/view/part_builder"
require "dry/view/scope_builder"
RSpec.describe Dry::View::RenderEnvironment do
subject(:render_env) { described_class.new(**options) }
@ -16,18 +16,18 @@ RSpec.describe Dry::View::RenderEnvironment do
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,
scope_builder: Dry::View::ScopeBuilder.new
}
}
describe '#format' do
describe "#format" do
it "returns the renderer's format" do
expect(render_env.format).to eq :html
end
end
describe '#==' do
it 'is equal when its options are equal' do
describe "#==" do
it "is equal when its options are equal" do
expect(render_env).to eq described_class.new(**options)
end
end

View File

@ -1,38 +1,38 @@
# frozen_string_literal: true
require 'dry/view/rendered'
require "dry/view/rendered"
RSpec.describe Dry::View::Rendered do
subject(:rendered) {
described_class.new(
output: 'rendered template output',
output: "rendered template output",
locals: {
user: { name: 'Jane' },
},
user: {name: "Jane"}
}
)
}
describe '#to_s' do
it 'returns the rendered output' do
expect(rendered.to_s).to eq 'rendered template output'
describe "#to_s" do
it "returns the rendered output" do
expect(rendered.to_s).to eq "rendered template output"
end
end
describe '#to_str' do
it 'returns the rendered output' do
expect(rendered.to_str).to eq 'rendered template output'
describe "#to_str" do
it "returns the rendered output" do
expect(rendered.to_str).to eq "rendered template output"
end
end
describe '#locals' do
it 'returns the locals hash' do
expect(rendered.locals).to eql({ user: { name: 'Jane' } })
describe "#locals" do
it "returns the locals hash" do
expect(rendered.locals).to eql(user: {name: "Jane"})
end
end
describe '#[]' do
it 'returns the named local' do
expect(rendered[:user]).to eql(name: 'Jane')
describe "#[]" do
it "returns the named local" do
expect(rendered[:user]).to eql(name: "Jane")
end
end
end

View File

@ -1,68 +1,68 @@
# frozen_string_literal: true
require 'dry/view/path'
require 'dry/view/renderer'
require "dry/view/path"
require "dry/view/renderer"
RSpec.describe Dry::View::Renderer do
subject(:renderer) do
Dry::View::Renderer.new(
[Dry::View::Path.new(SPEC_ROOT.join('fixtures/templates'))],
format: 'html',
default_encoding: 'utf-8'
[Dry::View::Path.new(SPEC_ROOT.join("fixtures/templates"))],
format: "html",
default_encoding: "utf-8"
)
end
let(:scope) { double(:scope) }
describe '#template' do
it 'renders template in current directory' do
expect(renderer.template(:hello, scope)).to eql('<h1>Hello</h1>')
describe "#template" do
it "renders template in current directory" do
expect(renderer.template(:hello, scope)).to eql("<h1>Hello</h1>")
end
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 {
renderer.template(:_shared_hello, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_shared_hello/)
end
it 'raises error when template cannot be found' do
it "raises error when template cannot be found" do
expect {
renderer.template(:missing_template, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /missing_template/)
end
end
describe '#partial' do
it 'renders partial in current directory' do
expect(renderer.partial(:hello, scope)).to eql('<h1>Partial hello</h1>')
describe "#partial" do
it "renders partial in current directory" do
expect(renderer.partial(:hello, scope)).to eql("<h1>Partial hello</h1>")
end
it 'renders partial in shared/ subdirectory under root' do
expect(renderer.chdir('hello').partial(:shared_hello, scope)).to eql('<h1>Hello</h1>')
it "renders partial in shared/ subdirectory under root" do
expect(renderer.chdir("hello").partial(:shared_hello, scope)).to eql("<h1>Hello</h1>")
end
it 'renders partial in shared/ subdirectory when descending from an upper directory' do
expect(renderer.chdir('hello').partial(:shared_hello, scope)).to eql('<h1>Hello</h1>')
it "renders partial in shared/ subdirectory when descending from an upper directory" do
expect(renderer.chdir("hello").partial(:shared_hello, scope)).to eql("<h1>Hello</h1>")
end
it 'renders partial in upper directory' do
expect(renderer.chdir('nested').partial(:hello, scope)).to eql('<h1>Partial hello</h1>')
it "renders partial in upper directory" do
expect(renderer.chdir("nested").partial(:hello, scope)).to eql("<h1>Partial hello</h1>")
end
it 'renders partial in upper shared/ subdirectory' do
expect(renderer.chdir('nested').partial(:shared_hello, scope)).to eql('<h1>Hello</h1>')
it "renders partial in upper shared/ subdirectory" do
expect(renderer.chdir("nested").partial(:shared_hello, scope)).to eql("<h1>Hello</h1>")
end
it 'raises error when partial cannot be found' do
it "raises error when partial cannot be found" do
expect {
renderer.partial(:missing_partial, scope)
}.to raise_error(Dry::View::TemplateNotFoundError, /_missing_partial/)
end
end
describe '#chdir' do
it 'copies options to new renderer instance' do
expect(renderer.chdir('nested').options).to eq(default_encoding: 'utf-8')
describe "#chdir" do
it "copies options to new renderer instance" do
expect(renderer.chdir("nested").options).to eq(default_encoding: "utf-8")
end
end
end

View File

@ -1,113 +1,113 @@
# frozen_string_literal: true
require 'dry/view/scope_builder'
require "dry/view/scope_builder"
RSpec.describe Dry::View::Scope do
let(:locals) { {} }
context 'with a render environment' do
context "with a render environment" do
subject(:scope) {
described_class.new(
locals: locals,
render_env: render_env,
render_env: render_env
)
}
let(:render_env) { spy(:render_env, format: :xml, context: context) }
let(:context) { double(:context) }
describe '#render' do
it 'renders a partial with itself as the scope' do
describe "#render" do
it "renders a partial with itself as the scope" do
scope.render(:info)
expect(render_env).to have_received(:partial).with(:info, scope)
end
it 'renders a partial with provided locals' do
it "renders a partial with provided locals" do
scope_with_locals = described_class.new(
locals: { foo: 'bar' },
render_env: render_env,
locals: {foo: "bar"},
render_env: render_env
)
scope.render(:info, foo: 'bar')
scope.render(:info, foo: "bar")
expect(render_env).to have_received(:partial).with(:info, scope_with_locals)
end
end
describe '#_format' do
describe "#_format" do
it "returns the render environments's format" do
expect(scope._format).to eq :xml
end
end
describe '#_context' do
describe "#_context" do
it "returns the render environment's context" do
expect(scope._context).to be context
end
end
describe '#method_missing' do
describe 'matching locals' do
let(:locals) { { greeting: 'hello from locals' } }
let(:context) { double(:context, greeting: 'hello from context') }
describe "#method_missing" do
describe "matching locals" do
let(:locals) { {greeting: "hello from locals"} }
let(:context) { double(:context, greeting: "hello from context") }
it 'returns a matching value from the locals, in favour of a matching method on the context' do
expect(scope.greeting).to eq 'hello from locals'
it "returns a matching value from the locals, in favour of a matching method on the context" do
expect(scope.greeting).to eq "hello from locals"
end
end
describe 'matching context' do
let(:context) { double(:context, greeting: 'hello from context') }
describe "matching context" do
let(:context) { double(:context, greeting: "hello from context") }
it 'calls the matching method on the context' do
expect(scope.greeting).to eq 'hello from context'
it "calls the matching method on the context" do
expect(scope.greeting).to eq "hello from context"
end
it 'forwards all arguments to the method' do
it "forwards all arguments to the method" do
blk = -> {}
scope.greeting 'args', &blk
scope.greeting "args", &blk
expect(context).to have_received(:greeting).with('args', &blk)
expect(context).to have_received(:greeting).with("args", &blk)
end
end
describe 'matching convenience methods' do
it 'provides #context' do
describe "matching convenience methods" do
it "provides #context" do
expect(scope.context).to be context
end
it 'provides #locals' do
it "provides #locals" do
expect(scope.locals).to be locals
end
end
describe 'no matches' do
it 'raises an error' do
describe "no matches" do
it "raises an error" do
expect { scope.greeting }.to raise_error(NoMethodError)
end
end
end
end
context 'without a render environment' do
context "without a render environment" do
subject(:scope) {
described_class.new(locals: locals)
}
describe '#render' do
it 'raises an error' do
describe "#render" do
it "raises an error" do
expect { scope.render(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end
describe '#scope' do
it 'raises an error' do
describe "#scope" do
it "raises an error" do
expect { scope.scope(:info) }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end
describe '#_context' do
it 'raises an error' do
describe "#_context" do
it "raises an error" do
expect { scope._context }.to raise_error(Dry::View::RenderEnvironmentMissing::MissingEnvironmentError)
end
end

View File

@ -1,20 +1,20 @@
# frozen_string_literal: true
require 'tilt/erubi'
require "tilt/erubi"
RSpec.describe Dry::View do
subject(:view) {
Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.layout = 'app'
config.template = 'user'
config.paths = SPEC_ROOT.join("fixtures/templates")
config.layout = "app"
config.template = "user"
expose :user do
{ name: 'Jane' }
{name: "Jane"}
end
expose :header do
{ title: 'User' }
{title: "User"}
end
end.new
}
@ -22,26 +22,26 @@ RSpec.describe Dry::View do
let(:context) do
Class.new(Dry::View::Context) do
def title
'Test'
"Test"
end
end.new
end
describe '#call' do
it 'renders template within the layout' do
describe "#call" do
it "renders template within the layout" do
expect(view.(context: context).to_s).to eql(
'<!DOCTYPE html><html><head><title>Test</title></head><body><h1>User</h1><p>Jane</p></body></html>'
"<!DOCTYPE html><html><head><title>Test</title></head><body><h1>User</h1><p>Jane</p></body></html>"
)
end
end
describe 'renderer options' do
describe "renderer options" do
subject(:view) {
Class.new(Dry::View) do
config.paths = SPEC_ROOT.join('fixtures/templates')
config.template = 'view_renderer_options'
config.renderer_engine_mapping = { erb: Tilt::ErubiTemplate }
config.renderer_options = { outvar: '@__buf__' }
config.paths = SPEC_ROOT.join("fixtures/templates")
config.template = "view_renderer_options"
config.renderer_engine_mapping = {erb: Tilt::ErubiTemplate}
config.renderer_options = {outvar: "@__buf__"}
end.new
}
@ -49,11 +49,11 @@ RSpec.describe Dry::View do
module Test
class Form
def initialize(action, &block)
@buf = eval('@__buf__', block.binding)
@buf = eval("@__buf__", block.binding, __FILE__, __LINE__)
@buf << "<form action=\"#{action}\" method=\"post\">"
block.(self)
@buf << '</form>'
@buf << "</form>"
end
def text(name)
@ -71,13 +71,13 @@ RSpec.describe Dry::View do
end.new
}
it 'merges configured options with default encoding' do
expect(view.class.config.renderer_options[:outvar]).to eq '@__buf__'
expect(view.class.config.renderer_options[:default_encoding]).to eq 'utf-8'
it "merges configured options with default encoding" do
expect(view.class.config.renderer_options[:outvar]).to eq "@__buf__"
expect(view.class.config.renderer_options[:default_encoding]).to eq "utf-8"
end
it 'are passed to renderer' do
expect(view.(context: context).to_s.gsub(/\n\s*/m, '')).to eq(
it "are passed to renderer" do
expect(view.(context: context).to_s.gsub(/\n\s*/m, "")).to eq(
'<form action="/people" method="post"><input type="text" name="name" /></form>'
)
end