dry-view 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ba3055d4bb318adbf1cc7718433873c0f8726e26
4
- data.tar.gz: 9e09c2f6cf9b340010dcda9319c23b6d78d48c61
2
+ SHA256:
3
+ metadata.gz: ce2a157debc72c52b51ea0111281241d65c8b6c30284a28d42fa8f24c70a3660
4
+ data.tar.gz: fa47926b849a06728df59429b1ee419651d06477d308cd8d9c0068d78fc911f5
5
5
  SHA512:
6
- metadata.gz: 0decd3ced65ee18f4f4bd95c18af6866c53fba4ed92c1e6a2774f8e8bdc787183ee90a260c5904c5a9b661cf106f822e60bd48ba4b4d89ff33fad630daf1eccc
7
- data.tar.gz: 5b7792fd0b18d5c9dcd2c10d53d3f817fd643ee90e97d866f68e8920f543126d4fed444afa9e0cae1193fa7cde5794cb9d54a16d8d63a1f9314228bc23171308
6
+ metadata.gz: 1a0d5e51ea2e331216e7a0efdce0e995155b2e9bef0bc8b94eb565165331fbd553c0aff1585a607523b5c94a80500c3f0d28881c953f118c6458f77ae980168b
7
+ data.tar.gz: 0256d4aa8f7365f4d9f9d98c21ae0dfa2fa5a5c4ff540a3127e3036780078cb96a947fc3bd2933be4157213741772ed21c1d4eee89e64e17e50d7475869d87a3
data/.travis.yml CHANGED
@@ -1,28 +1,18 @@
1
1
  language: ruby
2
- dist: trusty
3
- sudo: false
4
2
  cache: bundler
5
3
  bundler_args: --without tools benchmarks
6
4
  before_install:
7
5
  - gem update --system
8
- - rvm @global do gem uninstall bundler -a -x
9
- - rvm @global do gem install bundler -v 1.13.7
10
6
  script:
11
7
  - bundle exec rake
12
8
  after_success:
13
9
  # Send coverage report from the job #1 == current MRI release
14
10
  - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
15
11
  rvm:
12
+ - 2.5.0
16
13
  - 2.4.2
17
- - 2.3.5
18
- - 2.2.8
19
- - jruby-9.1.6.0
20
- env:
21
- global:
22
- - JRUBY_OPTS='--dev -J-Xmx1024M'
23
- matrix:
24
- allow_failures:
25
- - rvm: jruby-9.1.6.0
14
+ - 2.3.6
15
+ - jruby-9.1.10.0
26
16
  notifications:
27
17
  email: false
28
18
  webhooks:
@@ -31,6 +21,3 @@ notifications:
31
21
  on_success: change # options: [always|never|change] default: always
32
22
  on_failure: always # options: [always|never|change] default: always
33
23
  on_start: false # default: false
34
- addons:
35
- code_climate:
36
- repo_token: c1c8f334714254acf5da901ca4da6afe24b15408074faae27159e3d14a450b62
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 0.5.0 / 2018-01-23
2
+
3
+ ### Added
4
+
5
+ * Support for parts with decorated attributes (timriley + GustavoCaso)
6
+ * Ability to easily create another part instance via `Part#new` (GustavoCaso)
7
+
8
+ [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-view/compare/v0.4.0...v0.5.0)
9
+
1
10
  # 0.4.0 / 2017-11-01
2
11
 
3
12
  ### Added
data/README.md CHANGED
@@ -1,15 +1,14 @@
1
1
  [gitter]: https://gitter.im/dry-rb/chat
2
2
  [gem]: https://rubygems.org/gems/dry-view
3
3
  [travis]: https://travis-ci.org/dry-rb/dry-view
4
- [code_climate]: https://codeclimate.com/github/dry-rb/dry-view
5
4
  [inch]: http://inch-ci.org/github/dry-rb/dry-view
6
5
 
7
6
  # dry-view [![Join the Gitter chat](https://badges.gitter.im/Join%20Chat.svg)][gitter]
8
7
 
9
8
  [![Gem Version](https://img.shields.io/gem/v/dry-view.svg)][gem]
10
9
  [![Build Status](https://img.shields.io/travis/dry-rb/dry-view.svg)][travis]
11
- [![Code Climate](https://img.shields.io/codeclimate/github/dry-rb/dry-view.svg)][code_climate]
12
- [![Test Coverage](https://img.shields.io/codeclimate/coverage/github/dry-rb/dry-view.svg)][code_climate]
10
+ [![Maintainability](https://api.codeclimate.com/v1/badges/de81a8026a2e7f64e4df/maintainability)](https://codeclimate.com/github/dry-rb/dry-view/maintainability)
11
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/de81a8026a2e7f64e4df/test_coverage)](https://codeclimate.com/github/dry-rb/dry-view/test_coverage)
13
12
  [![API Documentation Coverage](http://inch-ci.org/github/dry-rb/dry-view.svg)][inch]
14
13
 
15
14
 
@@ -18,9 +18,9 @@ module Dry
18
18
  call(singular_name, obj, renderer: renderer, context: context, **singular_options)
19
19
  }
20
20
 
21
- klass.new(name: name, value: arr, renderer: renderer, context: context)
21
+ klass.new(name: name, value: arr, decorator: self, renderer: renderer, context: context)
22
22
  else
23
- klass.new(name: name, value: value, renderer: renderer, context: context)
23
+ klass.new(name: name, value: value, decorator: self, renderer: renderer, context: context)
24
24
  end
25
25
  end
26
26
 
data/lib/dry/view/part.rb CHANGED
@@ -11,7 +11,7 @@ module Dry
11
11
  value
12
12
  ].freeze
13
13
 
14
- include Dry::Equalizer(:_name, :_value, :_context, :_renderer)
14
+ include Dry::Equalizer(:_name, :_value, :_decorator, :_context, :_renderer)
15
15
 
16
16
  attr_reader :_name
17
17
 
@@ -21,11 +21,30 @@ module Dry
21
21
 
22
22
  attr_reader :_renderer
23
23
 
24
- def initialize(name:, value:, renderer: MissingRenderer.new, context: nil)
24
+ attr_reader :_decorator
25
+
26
+ attr_reader :_decorated_attributes
27
+
28
+ # @api public
29
+ def self.decorate(*names, **options)
30
+ names.each do |name|
31
+ decorated_attributes[name] = options
32
+ end
33
+ end
34
+
35
+ # @api private
36
+ def self.decorated_attributes
37
+ @decorated_attributes ||= {}
38
+ end
39
+
40
+ # FIXME: does MissingRenderer.new lead to needless allocations of MissingRenderer? We only need one globally.
41
+ def initialize(name:, value:, decorator: Dry::View::Decorator.new, renderer: MissingRenderer.new, context: nil)
25
42
  @_name = name
26
43
  @_value = value
27
44
  @_context = context
28
45
  @_renderer = renderer
46
+ @_decorator = decorator
47
+ @_decorated_attributes = {}
29
48
  end
30
49
 
31
50
  def _render(partial_name, as: _name, **locals, &block)
@@ -36,10 +55,23 @@ module Dry
36
55
  _value.to_s
37
56
  end
38
57
 
58
+ def new(klass = (self.class), name: (_name), value: (_value), **options)
59
+ klass.new(
60
+ name: name,
61
+ value: value,
62
+ context: _context,
63
+ renderer: _renderer,
64
+ decorator: _decorator,
65
+ **options,
66
+ )
67
+ end
68
+
39
69
  private
40
70
 
41
71
  def method_missing(name, *args, &block)
42
- if _value.respond_to?(name)
72
+ if self.class.decorated_attributes.key?(name)
73
+ _resolve_decorated_attribute(name)
74
+ elsif _value.respond_to?(name)
43
75
  _value.public_send(name, *args, &block)
44
76
  elsif CONVENIENCE_METHODS.include?(name)
45
77
  __send__(:"_#{name}", *args, &block)
@@ -55,6 +87,18 @@ module Dry
55
87
  renderer: _renderer,
56
88
  )
57
89
  end
90
+
91
+ def _resolve_decorated_attribute(name)
92
+ _decorated_attributes.fetch(name) {
93
+ _decorated_attributes[name] = _decorator.(
94
+ name,
95
+ _value.__send__(name),
96
+ renderer: _renderer,
97
+ context: _context,
98
+ **self.class.decorated_attributes[name],
99
+ )
100
+ }
101
+ end
58
102
  end
59
103
  end
60
104
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module View
3
- VERSION = '0.4.0'.freeze
3
+ VERSION = '0.5.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1 @@
1
+ h1 Partial new hello
@@ -0,0 +1,157 @@
1
+ RSpec.describe 'Part / Decorated attributes' do
2
+ let(:article_class) {
3
+ Class.new do
4
+ attr_reader :title, :author, :comments
5
+
6
+ def initialize(title:, author:, comments:)
7
+ @title = title
8
+ @author = author
9
+ @comments = comments
10
+ end
11
+ end
12
+ }
13
+
14
+ let(:author_class) {
15
+ Class.new do
16
+ attr_reader :name
17
+
18
+ def initialize(name:)
19
+ @name = name
20
+ end
21
+ end
22
+ }
23
+
24
+ let(:comment_class) {
25
+ Class.new do
26
+ attr_reader :author, :body
27
+
28
+ def initialize(author:, body:)
29
+ @author = author
30
+ @body = body
31
+ end
32
+ end
33
+ }
34
+
35
+ let(:article) {
36
+ article_class.new(
37
+ title: 'Hello world',
38
+ author: author_class.new(name: 'Jane Doe'),
39
+ comments: [
40
+ comment_class.new(author: author_class.new(name: 'Sue Smith'), body: 'Great article')
41
+ ]
42
+ )
43
+ }
44
+
45
+ describe 'using default decorator' do
46
+ subject(:article_part) {
47
+ article_part_class.new(
48
+ name: :article,
49
+ value: article,
50
+ )
51
+ }
52
+
53
+ describe 'decorating without options' do
54
+ describe 'multiple declarations' do
55
+ let(:article_part_class) {
56
+ Class.new(Dry::View::Part) do
57
+ decorate :author
58
+ decorate :comments
59
+ end
60
+ }
61
+
62
+ it 'decorates exposures with the standard Dry::View::Part class' do
63
+ expect(article_part.author).to be_a Dry::View::Part
64
+ expect(article_part.comments[0]).to be_a Dry::View::Part
65
+ end
66
+ end
67
+
68
+ describe 'single declaration' do
69
+ let(:article_part_class) {
70
+ Class.new(Dry::View::Part) do
71
+ decorate :author, :comments
72
+ end
73
+ }
74
+
75
+ it 'decorates exposures with the standard Dry::View::Part class' do
76
+ expect(article_part.author).to be_a Dry::View::Part
77
+ expect(article_part.comments[0]).to be_a Dry::View::Part
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'decorating with part class specified' do
83
+ before do
84
+ module Test
85
+ class AuthorPart < Dry::View::Part
86
+ end
87
+
88
+ class CommentPart < Dry::View::Part
89
+ end
90
+ end
91
+ end
92
+
93
+ let(:article_part_class) {
94
+ Class.new(Dry::View::Part) do
95
+ decorate :author, as: Test::AuthorPart
96
+ decorate :comments, as: Test::CommentPart
97
+ end
98
+ }
99
+
100
+ it 'deorates exposures with the specified part class' do
101
+ expect(article_part.author).to be_a Test::AuthorPart
102
+ expect(article_part.comments[0]).to be_a Test::CommentPart
103
+ end
104
+ end
105
+ end
106
+
107
+ describe 'using custom decorator' do
108
+ let(:article_part_class) {
109
+ Class.new(Dry::View::Part) do
110
+ decorate :author
111
+ decorate :comments
112
+ end
113
+ }
114
+
115
+ subject(:article_part) {
116
+ article_part_class.new(
117
+ name: :article,
118
+ value: article,
119
+ decorator: decorator,
120
+ )
121
+ }
122
+
123
+ let(:decorator) {
124
+ Class.new(Dry::View::Decorator) do
125
+ def part_class(name, value, **options)
126
+ if !options.key?(:as)
127
+ part_name = Dry::Core::Inflector.camelize(name)
128
+ begin
129
+ Test.const_get(:"#{part_name}Part")
130
+ rescue NameError
131
+ super
132
+ end
133
+ else
134
+ super
135
+ end
136
+ end
137
+ end.new
138
+ }
139
+
140
+ before do
141
+ module Test
142
+ class AuthorPart < Dry::View::Part
143
+ end
144
+
145
+ class CommentPart < Dry::View::Part
146
+ decorate :author
147
+ end
148
+ end
149
+ end
150
+
151
+ it 'deorates exposures using the custom decorator' do
152
+ expect(article_part.author).to be_a Test::AuthorPart
153
+ expect(article_part.comments[0]).to be_a Test::CommentPart
154
+ expect(article_part.comments[0].author).to be_a Test::AuthorPart
155
+ end
156
+ end
157
+ end
@@ -40,6 +40,16 @@ RSpec.describe Dry::View::Part do
40
40
  end
41
41
  end
42
42
 
43
+ describe '#new' do
44
+ it 'preserves decorator, renderer, and context' do
45
+ new_part = part.new(value: 'new value')
46
+
47
+ expect(new_part._decorator).to eql part._decorator
48
+ expect(new_part._renderer).to eql part._renderer
49
+ expect(new_part._context).to eql part._context
50
+ end
51
+ end
52
+
43
53
  describe '#method_missing' do
44
54
  let(:value) { double(greeting: 'hello from value') }
45
55
 
@@ -67,7 +77,7 @@ RSpec.describe Dry::View::Part do
67
77
  let(:value) { double('value') }
68
78
  let(:context) { double('context') }
69
79
 
70
- describe '#new' do
80
+ describe '#initialize' do
71
81
  it 'can be initialized' do
72
82
  expect(part).to be_an_instance_of(Dry::View::Part)
73
83
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-view
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-11-01 00:00:00.000000000 Z
12
+ date: 2018-01-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tilt
@@ -161,9 +161,11 @@ files:
161
161
  - spec/fixtures/templates/users/_row.html.slim
162
162
  - spec/fixtures/templates/users/_tbody.html.slim
163
163
  - spec/fixtures/templates/users_with_count.html.slim
164
+ - spec/fixtures/templates_override/_hello.html.slim
164
165
  - spec/fixtures/templates_override/users.html.slim
165
166
  - spec/integration/decorator_spec.rb
166
167
  - spec/integration/exposures_spec.rb
168
+ - spec/integration/part/decorated_attributes_spec.rb
167
169
  - spec/integration/view_spec.rb
168
170
  - spec/spec_helper.rb
169
171
  - spec/unit/controller_spec.rb
@@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
195
  version: '0'
194
196
  requirements: []
195
197
  rubyforge_project:
196
- rubygems_version: 2.6.11
198
+ rubygems_version: 2.7.4
197
199
  signing_key:
198
200
  specification_version: 4
199
201
  summary: Functional view rendering system
@@ -217,9 +219,11 @@ test_files:
217
219
  - spec/fixtures/templates/users/_row.html.slim
218
220
  - spec/fixtures/templates/users/_tbody.html.slim
219
221
  - spec/fixtures/templates/users_with_count.html.slim
222
+ - spec/fixtures/templates_override/_hello.html.slim
220
223
  - spec/fixtures/templates_override/users.html.slim
221
224
  - spec/integration/decorator_spec.rb
222
225
  - spec/integration/exposures_spec.rb
226
+ - spec/integration/part/decorated_attributes_spec.rb
223
227
  - spec/integration/view_spec.rb
224
228
  - spec/spec_helper.rb
225
229
  - spec/unit/controller_spec.rb