dry_rails 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/app/views/_form.haml +32 -0
- data/app/views/_form_errors.haml +5 -0
- data/app/views/edit.haml +15 -0
- data/app/views/index.haml +62 -0
- data/app/views/new.haml +10 -0
- data/lib/dry/controller.rb +134 -0
- data/lib/dry/resource.rb +100 -0
- data/lib/dry/resource_routes.rb +20 -0
- data/lib/dry/routing_helpers.rb +49 -0
- data/lib/dry/template_resolver.rb +11 -0
- data/lib/dry/version.rb +3 -0
- data/lib/dry.rb +13 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 45e9f1560278be794de82bb4b02b2810eaa2cf0754216b90449179fab98da9f1
|
4
|
+
data.tar.gz: 112c9c2b20d87a231e76213e910c3510404466d22fe527a0727ded5c32b77b6f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d3a39eb7221fd5de5a04fae053a346007d2b0e4024e875ee5eff291587f232bdc43da69abfdc847b3c49fdfecfa32ae8cce359dc7ec78534e29ec5e21600ef8
|
7
|
+
data.tar.gz: 0cc139ffa109deeea728d3fd03b6313eafe6b485690e9a4a5e2132f561ef9f03ccc21a8df9040d67c97782ac4fff56aa76c0026fa8f3a188ddc54b2deedc5816
|
@@ -0,0 +1,32 @@
|
|
1
|
+
= form_for form_arguments(@record), html: { class: 'form' } do |f|
|
2
|
+
%fieldset
|
3
|
+
- if lookup_context.exists?('form_fieldset_before',
|
4
|
+
%W[#{@resource.model_name.route_key}/dry], true)
|
5
|
+
= render "#{@resource.model_name.route_key}/dry/form_fieldset_before"
|
6
|
+
|
7
|
+
- @resource.each_form_fields do |attr, type|
|
8
|
+
%p.field
|
9
|
+
- case type
|
10
|
+
- when Class
|
11
|
+
= f.label attr
|
12
|
+
%br
|
13
|
+
= f.collection_select attr, type.send(:all), :id, :to_s
|
14
|
+
- when Symbol
|
15
|
+
- if type == :check_box
|
16
|
+
= f.send type, attr
|
17
|
+
= f.label attr
|
18
|
+
- else
|
19
|
+
= f.label attr
|
20
|
+
%br
|
21
|
+
- form_control = ['form_field_for',
|
22
|
+
@resource.model_name.singular_route_key,
|
23
|
+
attr].join(?_).to_sym
|
24
|
+
- if respond_to? form_control
|
25
|
+
= send form_control, f
|
26
|
+
- else
|
27
|
+
= f.send type, attr
|
28
|
+
|
29
|
+
- if @record.errors.any?
|
30
|
+
= render "form_errors", record: @record
|
31
|
+
|
32
|
+
%p= f.button
|
data/app/views/edit.haml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
%h1
|
2
|
+
Editing
|
3
|
+
= @resource.singular_name
|
4
|
+
|
5
|
+
|
6
|
+
= render 'form'
|
7
|
+
|
8
|
+
%ul.actions
|
9
|
+
- if @resource.relations?
|
10
|
+
- @resource.relations.each do |relation|
|
11
|
+
- relation = @record.send(relation)
|
12
|
+
%li= link_to relation.model_name.human.pluralize,
|
13
|
+
relation_path(@record, relation)
|
14
|
+
%li
|
15
|
+
= link_to 'Back', collection_path(@resource)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
%h1
|
2
|
+
Listing
|
3
|
+
= @resource.plural_name
|
4
|
+
|
5
|
+
|
6
|
+
- if @collection.empty?
|
7
|
+
%p
|
8
|
+
No
|
9
|
+
= @resource.singular_name
|
10
|
+
found.
|
11
|
+
|
12
|
+
- else
|
13
|
+
%table.list
|
14
|
+
%thead
|
15
|
+
%tr
|
16
|
+
%th
|
17
|
+
= @resource.singular_name.capitalize
|
18
|
+
- @resource.attrs_read.each do |attr|
|
19
|
+
%th= attr.capitalize
|
20
|
+
- if @resource.edit? || @resource.destroy?
|
21
|
+
%th.list-actions
|
22
|
+
Actions
|
23
|
+
|
24
|
+
%tbody
|
25
|
+
- @collection.each do |record|
|
26
|
+
%tr
|
27
|
+
%td
|
28
|
+
- if @resource.show?
|
29
|
+
= link_to record, record_path(record)
|
30
|
+
- else
|
31
|
+
= link_to record, edit_path(record)
|
32
|
+
- @resource.attrs_read.each do |attr|
|
33
|
+
%td
|
34
|
+
- attr_content = ['read_attr_content',
|
35
|
+
@resource.model_name.singular_route_key,
|
36
|
+
attr].join(?_).to_sym
|
37
|
+
- if respond_to? attr_content
|
38
|
+
= send attr_content, record
|
39
|
+
- else
|
40
|
+
= record.send attr
|
41
|
+
- if @resource.edit? || @resource.destroy?
|
42
|
+
%td.list-actions
|
43
|
+
%ul.actions
|
44
|
+
- if @resource.edit?
|
45
|
+
%li= link_to 'Edit', edit_path(record)
|
46
|
+
- if @resource.destroy?
|
47
|
+
%li= link_to 'Destroy', record_path(record), method: :delete,
|
48
|
+
data: { confirm: t('confirmation',
|
49
|
+
default: 'Are you sure?') }
|
50
|
+
- if @resource.relations?
|
51
|
+
- @resource.relations.each do |relation|
|
52
|
+
- relation = record.send(relation)
|
53
|
+
%li= link_to relation.model_name.human.pluralize,
|
54
|
+
relation_path(record, relation)
|
55
|
+
|
56
|
+
|
57
|
+
%ul.actions
|
58
|
+
- if @resource.new?
|
59
|
+
%li
|
60
|
+
= link_to "New #{@resource.singular_name}", new_path(@resource)
|
61
|
+
- if lookup_context.exists?('index_actions_extra', %w[dry], true)
|
62
|
+
= render 'dry/index_actions_extra'
|
data/app/views/new.haml
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
module Dry
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include RoutingHelpers
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :_dry_scope, instance_accessor: false
|
8
|
+
|
9
|
+
class_attribute :_dry_attrs, instance_accessor: false
|
10
|
+
self._dry_attrs = { read: [], write: [], options: {} }
|
11
|
+
|
12
|
+
class_attribute :_dry_nested_relations, instance_accessor: false
|
13
|
+
self._dry_nested_relations = []
|
14
|
+
|
15
|
+
append_view_path TemplateResolver.new
|
16
|
+
|
17
|
+
helper RoutingHelpers
|
18
|
+
|
19
|
+
before_filter :set_resource
|
20
|
+
before_filter :set_collection, only: :index
|
21
|
+
before_filter :set_record, only: %i[show edit update destroy]
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def dry_scope &block
|
26
|
+
self._dry_scope = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def dry_attrs_read *attrs
|
30
|
+
self._dry_attrs[:read] = attrs
|
31
|
+
end
|
32
|
+
|
33
|
+
def dry_attrs_write *attrs
|
34
|
+
self._dry_attrs[:write] = attrs
|
35
|
+
end
|
36
|
+
|
37
|
+
def dry_attrs_options **options
|
38
|
+
self._dry_attrs[:options] = options
|
39
|
+
end
|
40
|
+
|
41
|
+
def dry_nest *relations
|
42
|
+
self._dry_nested_relations.push *relations
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def index
|
47
|
+
end
|
48
|
+
|
49
|
+
def show
|
50
|
+
end
|
51
|
+
|
52
|
+
def new
|
53
|
+
@record = resource_scope.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def edit
|
57
|
+
end
|
58
|
+
|
59
|
+
def create
|
60
|
+
@record = resource_scope.new record_params
|
61
|
+
if @record.save
|
62
|
+
redirect_to collection_path(@resource),
|
63
|
+
notice: "#{model_name.singular.capitalize} was successfully created."
|
64
|
+
else
|
65
|
+
render :new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def update
|
70
|
+
if @record.update record_params
|
71
|
+
redirect_to collection_path(@resource),
|
72
|
+
notice: "#{model_name.singular.capitalize} was successfully updated."
|
73
|
+
else
|
74
|
+
render :edit
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy
|
79
|
+
@record.destroy
|
80
|
+
redirect_to collection_path(@resource),
|
81
|
+
notice: "#{model_name.singular.capitalize} was successfully destroyed."
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def resource
|
87
|
+
@resource ||= Resource.new(controller_name.classify.constantize,
|
88
|
+
attrs_read: self.class._dry_attrs[:read],
|
89
|
+
attrs_write: self.class._dry_attrs[:write],
|
90
|
+
attrs_options: self.class._dry_attrs[:options],
|
91
|
+
relations: self.class._dry_nested_relations,
|
92
|
+
routes: resource_routes
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def resource_routes
|
97
|
+
ResourceRoutes.new(Rails.application.routes.routes, controller_path)
|
98
|
+
.routes
|
99
|
+
end
|
100
|
+
|
101
|
+
def resource_scope
|
102
|
+
if b = self.class._dry_scope
|
103
|
+
instance_exec &b
|
104
|
+
else
|
105
|
+
resource.model
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def model_name
|
110
|
+
resource.model_name
|
111
|
+
end
|
112
|
+
|
113
|
+
def collection
|
114
|
+
resource_scope.order 'created_at ASC'
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_resource
|
118
|
+
resource
|
119
|
+
end
|
120
|
+
|
121
|
+
def set_collection
|
122
|
+
@collection = collection
|
123
|
+
end
|
124
|
+
|
125
|
+
def set_record
|
126
|
+
@record = resource_scope.find params[:id]
|
127
|
+
end
|
128
|
+
|
129
|
+
def record_params
|
130
|
+
params.require(model_name.param_key.to_sym)
|
131
|
+
.permit *self.class._dry_attrs[:write]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/dry/resource.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
module Dry
|
2
|
+
class Resource
|
3
|
+
DEFAULT_OPTIONS = {
|
4
|
+
attrs_read: [],
|
5
|
+
attrs_write: [],
|
6
|
+
attrs_options: {},
|
7
|
+
relations: [],
|
8
|
+
routes: []
|
9
|
+
}
|
10
|
+
|
11
|
+
ATTR_TYPE_TO_FORM_FIELD = {
|
12
|
+
boolean: :check_box,
|
13
|
+
decimal: :number_field,
|
14
|
+
integer: :number_field,
|
15
|
+
string: :text_field,
|
16
|
+
text: :text_area
|
17
|
+
}
|
18
|
+
|
19
|
+
ATTR_RELATION_PATTERN = /_id\z/.freeze
|
20
|
+
|
21
|
+
extend Forwardable
|
22
|
+
def_delegators :@model, :model_name
|
23
|
+
|
24
|
+
attr_reader :model
|
25
|
+
|
26
|
+
def initialize model, options = {}
|
27
|
+
@model = model
|
28
|
+
@options = DEFAULT_OPTIONS.merge options
|
29
|
+
end
|
30
|
+
|
31
|
+
def singular_name
|
32
|
+
model_name.singular
|
33
|
+
end
|
34
|
+
|
35
|
+
def plural_name
|
36
|
+
model_name.plural
|
37
|
+
end
|
38
|
+
|
39
|
+
def relations?
|
40
|
+
@options[:relations].any?
|
41
|
+
end
|
42
|
+
|
43
|
+
def relations
|
44
|
+
@options[:relations]
|
45
|
+
end
|
46
|
+
|
47
|
+
def show?
|
48
|
+
has_route_for? :show
|
49
|
+
end
|
50
|
+
|
51
|
+
def new?
|
52
|
+
has_route_for? :new
|
53
|
+
end
|
54
|
+
|
55
|
+
def edit?
|
56
|
+
has_route_for? :edit
|
57
|
+
end
|
58
|
+
|
59
|
+
def destroy?
|
60
|
+
has_route_for? :destroy
|
61
|
+
end
|
62
|
+
|
63
|
+
def attrs_read
|
64
|
+
@options[:attrs_read]
|
65
|
+
end
|
66
|
+
|
67
|
+
def attrs_write
|
68
|
+
@options[:attrs_write]
|
69
|
+
end
|
70
|
+
|
71
|
+
def attrs_options
|
72
|
+
@options[:attrs_options]
|
73
|
+
end
|
74
|
+
|
75
|
+
def each_form_fields
|
76
|
+
attrs_write.each do |e|
|
77
|
+
if e =~ ATTR_RELATION_PATTERN
|
78
|
+
yield e,
|
79
|
+
@model.reflections[e.to_s.sub ATTR_RELATION_PATTERN, ''].klass
|
80
|
+
else
|
81
|
+
yield e, form_field_for(e)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def has_route_for? action
|
89
|
+
@options[:routes].include? action
|
90
|
+
end
|
91
|
+
|
92
|
+
def form_field_for attr
|
93
|
+
if type = attrs_options[attr]
|
94
|
+
type
|
95
|
+
else
|
96
|
+
ATTR_TYPE_TO_FORM_FIELD[@model.column_types[attr.to_s].type]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dry
|
2
|
+
class ResourceRoutes
|
3
|
+
def initialize routes, path
|
4
|
+
@routes = routes
|
5
|
+
@path = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def routes
|
9
|
+
routes_for_path(@path).each_with_object([]) do |e, m|
|
10
|
+
m << e.defaults[:action].to_sym
|
11
|
+
end.uniq
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def routes_for_path path
|
17
|
+
@routes.select { |e| e.defaults[:controller] == @path }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Dry
|
2
|
+
module RoutingHelpers
|
3
|
+
def collection_path resource
|
4
|
+
send "#{base_path resource, plural: true}_path"
|
5
|
+
end
|
6
|
+
|
7
|
+
def record_path record
|
8
|
+
send "#{base_path record.class}_path", *([@parent, record].compact)
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_path resource
|
12
|
+
send "new_#{base_path resource}_path"
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit_path record
|
16
|
+
send "edit_#{base_path record.class}_path", *([@parent, record].compact)
|
17
|
+
end
|
18
|
+
|
19
|
+
def relation_path record, relation
|
20
|
+
send "#{base_path record.class}_#{relation.model_name.route_key}_path",
|
21
|
+
record
|
22
|
+
end
|
23
|
+
|
24
|
+
def form_arguments record
|
25
|
+
[*current_namespace, @parent, record].compact
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def current_namespace
|
31
|
+
(controller_path.split('/') - [controller_name]).map &:to_sym
|
32
|
+
end
|
33
|
+
|
34
|
+
def base_path klass, plural: false
|
35
|
+
path = [*current_namespace].flatten
|
36
|
+
path << parent_class.model_name.singular_route_key if parent?
|
37
|
+
path << klass.model_name.send(plural ? :route_key : :singular_route_key)
|
38
|
+
path * '_'
|
39
|
+
end
|
40
|
+
|
41
|
+
def parent?
|
42
|
+
!!@parent
|
43
|
+
end
|
44
|
+
|
45
|
+
def parent_class
|
46
|
+
@parent ? @parent.class : nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/dry/version.rb
ADDED
data/lib/dry.rb
ADDED
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dry_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thibault Jouan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: railties
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.5
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.5
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: haml
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activerecord
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capybara
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sqlite3
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.3'
|
104
|
+
- - "<"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '1.4'
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '1.3'
|
114
|
+
- - "<"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '1.4'
|
117
|
+
description:
|
118
|
+
email: tj@a13.fr
|
119
|
+
executables: []
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- app/views/_form.haml
|
124
|
+
- app/views/_form_errors.haml
|
125
|
+
- app/views/edit.haml
|
126
|
+
- app/views/index.haml
|
127
|
+
- app/views/new.haml
|
128
|
+
- lib/dry.rb
|
129
|
+
- lib/dry/controller.rb
|
130
|
+
- lib/dry/resource.rb
|
131
|
+
- lib/dry/resource_routes.rb
|
132
|
+
- lib/dry/routing_helpers.rb
|
133
|
+
- lib/dry/template_resolver.rb
|
134
|
+
- lib/dry/version.rb
|
135
|
+
homepage:
|
136
|
+
licenses:
|
137
|
+
- BSD-3-Clause
|
138
|
+
metadata: {}
|
139
|
+
post_install_message:
|
140
|
+
rdoc_options: []
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubygems_version: 3.0.3
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: Dry
|
158
|
+
test_files: []
|