portrayal 0.6.0 → 0.7.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 +4 -4
- data/.github/workflows/rspec.yml +2 -2
- data/.gitignore +3 -0
- data/CHANGELOG.md +6 -0
- data/README.md +42 -7
- data/lib/portrayal.rb +3 -3
- data/lib/portrayal/default.rb +13 -0
- data/lib/portrayal/schema.rb +37 -55
- data/lib/portrayal/version.rb +1 -1
- data/portrayal.gemspec +6 -3
- metadata +8 -5
- data/Gemfile.lock +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbd0b561e866c45f6e850b592620df78d4573635165807cd2284ab45baed9e0c
|
4
|
+
data.tar.gz: 699be912aa836a55faa10886a3a1c1bb7b17c006f1db445694660d2fbe0ec0f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58fc168ad299aee9555ec7e1a1355f533c65af5ff1620095a7e49829252b39e92f45714083cc03fd1cde2ccc027acabd98b3526618caae07fb226be7e294694b
|
7
|
+
data.tar.gz: 8d59938b7bdcc5b9a32683695b6146186cb12bf6132326ecfff5b01685b7740dbf78ef513a43fbf5ff58716c38848881229600e4eb2f059dc13efc530120d68d
|
data/.github/workflows/rspec.yml
CHANGED
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 0.7.0 - 2020-12-13
|
6
|
+
|
7
|
+
* **Breaking change:** Remove `optional` setting. To update find all `optional: true` and change to `default: nil` instead.
|
8
|
+
|
9
|
+
* **Breaking change:** Move `self` of default procs to `initialize` context. Before this change, default procs used to be executed naively in class context. Now they can access other keyword readers and instance methods since their `self` is now coming from `initialize`. To update, look through your default procs and replace any reference to current class's methods such as `method_name` with `self.class.method_name`.
|
10
|
+
|
5
11
|
## 0.6.0 - 2020-08-10
|
6
12
|
|
7
13
|
* Return keyword name from `keyword`, allowing usage such as `private keyword :foo`. [[commit]](https://github.com/scottscheapflights/portrayal/commit/9e9db2cafc7eae14789c5b84f70efd18898ace76)
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-

|
2
2
|
|
3
3
|
# Portrayal
|
4
4
|
|
@@ -15,7 +15,7 @@ class Person < MySuperClass
|
|
15
15
|
extend Portrayal
|
16
16
|
|
17
17
|
keyword :name
|
18
|
-
keyword :age,
|
18
|
+
keyword :age, default: nil
|
19
19
|
keyword :favorite_fruit, default: 'feijoa'
|
20
20
|
|
21
21
|
keyword :address do
|
@@ -172,7 +172,7 @@ class Address < ApplicationStruct
|
|
172
172
|
keyword :street
|
173
173
|
keyword :city
|
174
174
|
keyword :postcode
|
175
|
-
keyword :country,
|
175
|
+
keyword :country, default: nil
|
176
176
|
end
|
177
177
|
```
|
178
178
|
|
@@ -198,6 +198,41 @@ Any other value works as normal.
|
|
198
198
|
keyword :foo, default: 4
|
199
199
|
```
|
200
200
|
|
201
|
+
#### Default procs
|
202
|
+
|
203
|
+
Default procs are executed as though they were called in your class's `initialize`, so they have access to other keywords and instance methods.
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
keyword :name
|
207
|
+
keyword :greeting, default: proc { "Hello, #{name}" }
|
208
|
+
```
|
209
|
+
|
210
|
+
Defaults can also use results of other defaults.
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
keyword :four, default: proc { 2 + 2 }
|
214
|
+
keyword :eight, default: proc { four * 2 }
|
215
|
+
```
|
216
|
+
|
217
|
+
Or instance methods of the class.
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
keyword :id, default: proc { generate_id }
|
221
|
+
|
222
|
+
private
|
223
|
+
|
224
|
+
def generate_id
|
225
|
+
SecureRandom.alphanumeric
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
Note: The order in which you declare keywords matters when specifying defaults that depend on other keywords. This will not have the desired effect:
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
keyword :greeting, default: proc { "Hello, #{name}" }
|
233
|
+
keyword :name
|
234
|
+
```
|
235
|
+
|
201
236
|
### Nested Classes
|
202
237
|
|
203
238
|
When you pass a block to a keyword, it creates a nested class named after camelized keyword name.
|
@@ -254,7 +289,7 @@ Address.portrayal.attributes(address) # => {street: '34th st', city: 'NYC', post
|
|
254
289
|
Get everything portrayal knows about your keywords in one hash.
|
255
290
|
|
256
291
|
```ruby
|
257
|
-
Address.portrayal.schema # => {:street=>
|
292
|
+
Address.portrayal.schema # => {:street=>nil, :city=>nil, :postcode=>nil, :country=><Portrayal::Default @value=nil @callable=false>}
|
258
293
|
```
|
259
294
|
|
260
295
|
## Philosophy
|
@@ -288,7 +323,7 @@ class Address < ApplicationStruct
|
|
288
323
|
keyword :street
|
289
324
|
keyword :city
|
290
325
|
keyword :postcode
|
291
|
-
keyword :country,
|
326
|
+
keyword :country, default: nil
|
292
327
|
end
|
293
328
|
```
|
294
329
|
|
@@ -331,7 +366,7 @@ class Address < ApplicationStruct
|
|
331
366
|
keyword :street
|
332
367
|
keyword :city
|
333
368
|
keyword :postcode
|
334
|
-
keyword :country,
|
369
|
+
keyword :country, default: nil
|
335
370
|
end
|
336
371
|
```
|
337
372
|
|
@@ -360,4 +395,4 @@ The gem is available as open source under the terms of the [Apache License Versi
|
|
360
395
|
|
361
396
|
## Code of Conduct
|
362
397
|
|
363
|
-
Everyone interacting in the Portrayal project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/scottscheapflights/portrayal/blob/
|
398
|
+
Everyone interacting in the Portrayal project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/scottscheapflights/portrayal/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/portrayal.rb
CHANGED
@@ -4,7 +4,7 @@ require 'portrayal/schema'
|
|
4
4
|
module Portrayal
|
5
5
|
NULL = :_portrayal_value_not_set
|
6
6
|
|
7
|
-
def keyword(name,
|
7
|
+
def keyword(name, default: NULL, define: nil, &block)
|
8
8
|
unless respond_to?(:portrayal)
|
9
9
|
class << self
|
10
10
|
attr_reader :portrayal
|
@@ -14,13 +14,13 @@ module Portrayal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
@portrayal = Schema.new
|
17
|
-
class_eval(
|
17
|
+
class_eval(Schema::DEFINITION_OF_OBJECT_ENHANCEMENTS)
|
18
18
|
end
|
19
19
|
|
20
20
|
attr_accessor name
|
21
21
|
protected "#{name}="
|
22
22
|
|
23
|
-
portrayal.add_keyword(name,
|
23
|
+
portrayal.add_keyword(name, default)
|
24
24
|
class_eval(portrayal.definition_of_initialize)
|
25
25
|
|
26
26
|
if block_given?
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Portrayal
|
2
|
+
class Default
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
@callable = value.is_a?(Proc) && !value.lambda?
|
8
|
+
end
|
9
|
+
|
10
|
+
def call?; @callable end
|
11
|
+
def initialize_dup(src); super; @value = src.value.dup end
|
12
|
+
end
|
13
|
+
end
|
data/lib/portrayal/schema.rb
CHANGED
@@ -1,59 +1,10 @@
|
|
1
|
+
require 'portrayal/default'
|
2
|
+
|
1
3
|
module Portrayal
|
2
4
|
class Schema
|
3
5
|
attr_reader :schema
|
4
6
|
|
5
|
-
|
6
|
-
def keywords; @schema.keys end
|
7
|
-
def [](name); @schema[name] end
|
8
|
-
|
9
|
-
def attributes(object)
|
10
|
-
Hash[object.class.portrayal.keywords.map { |k| [k, object.send(k)] }]
|
11
|
-
end
|
12
|
-
|
13
|
-
def camelize(string); string.to_s.gsub(/(?:^|_+)([^_])/) { $1.upcase } end
|
14
|
-
|
15
|
-
def add_keyword(name, optional, default)
|
16
|
-
optional, default =
|
17
|
-
case [optional == NULL, default == NULL]
|
18
|
-
when [true, true]; [false, nil]
|
19
|
-
when [false, true]; [optional, optional ? [:return, nil] : nil]
|
20
|
-
when [true, false]; [true, [default_strategy(default), default]]
|
21
|
-
else; [optional, optional ? [default_strategy(default), default] : nil]
|
22
|
-
end
|
23
|
-
|
24
|
-
@schema[name.to_sym] = { optional: optional, default: default }
|
25
|
-
end
|
26
|
-
|
27
|
-
def get_default(name)
|
28
|
-
action, value = @schema[name][:default]
|
29
|
-
action == :call ? value.call : value
|
30
|
-
end
|
31
|
-
|
32
|
-
def default_strategy(value)
|
33
|
-
(value.is_a?(Proc) && !value.lambda?) ? :call : :return
|
34
|
-
end
|
35
|
-
|
36
|
-
def initialize_dup(other)
|
37
|
-
super
|
38
|
-
@schema =
|
39
|
-
other.schema.map { |k, v|
|
40
|
-
default = v[:default] ? v[:default].map(&:dup) : v[:default]
|
41
|
-
[k, { optional: v[:optional], default: default }]
|
42
|
-
}.to_h
|
43
|
-
end
|
44
|
-
|
45
|
-
def definition_of_initialize
|
46
|
-
init_args = @schema.map { |name, config|
|
47
|
-
config[:optional] ?
|
48
|
-
"#{name}: self.class.portrayal.get_default(:#{name})" : "#{name}:"
|
49
|
-
}.join(',')
|
50
|
-
|
51
|
-
init_assigns = @schema.keys.map { |name| "@#{name} = #{name}" }.join('; ')
|
52
|
-
"def initialize(#{init_args}); #{init_assigns} end"
|
53
|
-
end
|
54
|
-
|
55
|
-
def definition_of_object_enhancements
|
56
|
-
<<-RUBY
|
7
|
+
DEFINITION_OF_OBJECT_ENHANCEMENTS = <<~RUBY.freeze
|
57
8
|
def eql?(other); self.class == other.class && self == other end
|
58
9
|
def hash; [self.class, self.class.portrayal.attributes(self)].hash end
|
59
10
|
|
@@ -71,18 +22,49 @@ module Portrayal
|
|
71
22
|
|
72
23
|
def initialize_dup(source)
|
73
24
|
self.class.portrayal.attributes(source).each do |key, value|
|
74
|
-
instance_variable_set(
|
25
|
+
instance_variable_set("@\#{key}", value.dup)
|
75
26
|
end
|
76
27
|
super
|
77
28
|
end
|
78
29
|
|
79
30
|
def initialize_clone(source)
|
80
31
|
self.class.portrayal.attributes(source).each do |key, value|
|
81
|
-
instance_variable_set(
|
32
|
+
instance_variable_set("@\#{key}", value.clone)
|
82
33
|
end
|
83
34
|
super
|
84
35
|
end
|
85
|
-
|
36
|
+
RUBY
|
37
|
+
|
38
|
+
def initialize; @schema = {} end
|
39
|
+
def keywords; @schema.keys end
|
40
|
+
def [](name); @schema[name] end
|
41
|
+
|
42
|
+
def attributes(object)
|
43
|
+
Hash[object.class.portrayal.keywords.map { |k| [k, object.send(k)] }]
|
44
|
+
end
|
45
|
+
|
46
|
+
def camelize(string); string.to_s.gsub(/(?:^|_+)([^_])/) { $1.upcase } end
|
47
|
+
|
48
|
+
def add_keyword(name, default)
|
49
|
+
@schema[name.to_sym] = default.equal?(NULL) ? nil : Default.new(default)
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize_dup(other)
|
53
|
+
super; @schema = other.schema.transform_values(&:dup)
|
54
|
+
end
|
55
|
+
|
56
|
+
def definition_of_initialize
|
57
|
+
init_args = @schema.map { |name, default|
|
58
|
+
"#{name}:#{default && " self.class.portrayal[:#{name}]"}"
|
59
|
+
}.join(', ')
|
60
|
+
|
61
|
+
init_assigns = @schema.keys.map { |name|
|
62
|
+
"@#{name} = #{name}.is_a?(::Portrayal::Default) ? " \
|
63
|
+
"(#{name}.call? ? instance_exec(&#{name}.value) : #{name}.value) : " \
|
64
|
+
"#{name}"
|
65
|
+
}.join('; ')
|
66
|
+
|
67
|
+
"def initialize(#{init_args}); #{init_assigns} end"
|
86
68
|
end
|
87
69
|
end
|
88
70
|
end
|
data/lib/portrayal/version.rb
CHANGED
data/portrayal.gemspec
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'portrayal/version'
|
1
|
+
require_relative 'lib/portrayal/version'
|
4
2
|
|
5
3
|
Gem::Specification.new do |spec|
|
6
4
|
spec.name = 'portrayal'
|
@@ -13,6 +11,11 @@ Gem::Specification.new do |spec|
|
|
13
11
|
spec.homepage = 'https://github.com/scottscheapflights/portrayal'
|
14
12
|
spec.license = 'Apache-2.0'
|
15
13
|
|
14
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
15
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
16
|
+
spec.metadata['changelog_uri'] = 'https://github.com/scottscheapflights/portrayal/blob/main/CHANGELOG.md'
|
17
|
+
|
18
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
16
19
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
17
20
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^spec/}) }
|
18
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: portrayal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxim Chernyak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -82,20 +82,23 @@ files:
|
|
82
82
|
- CHANGELOG.md
|
83
83
|
- CODE_OF_CONDUCT.md
|
84
84
|
- Gemfile
|
85
|
-
- Gemfile.lock
|
86
85
|
- LICENSE.txt
|
87
86
|
- README.md
|
88
87
|
- Rakefile
|
89
88
|
- bin/console
|
90
89
|
- bin/setup
|
91
90
|
- lib/portrayal.rb
|
91
|
+
- lib/portrayal/default.rb
|
92
92
|
- lib/portrayal/schema.rb
|
93
93
|
- lib/portrayal/version.rb
|
94
94
|
- portrayal.gemspec
|
95
95
|
homepage: https://github.com/scottscheapflights/portrayal
|
96
96
|
licenses:
|
97
97
|
- Apache-2.0
|
98
|
-
metadata:
|
98
|
+
metadata:
|
99
|
+
homepage_uri: https://github.com/scottscheapflights/portrayal
|
100
|
+
source_code_uri: https://github.com/scottscheapflights/portrayal
|
101
|
+
changelog_uri: https://github.com/scottscheapflights/portrayal/blob/main/CHANGELOG.md
|
99
102
|
post_install_message:
|
100
103
|
rdoc_options: []
|
101
104
|
require_paths:
|
@@ -104,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
107
|
requirements:
|
105
108
|
- - ">="
|
106
109
|
- !ruby/object:Gem::Version
|
107
|
-
version:
|
110
|
+
version: 2.4.0
|
108
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
112
|
requirements:
|
110
113
|
- - ">="
|
data/Gemfile.lock
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
portrayal (0.6.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
coderay (1.1.2)
|
10
|
-
diff-lcs (1.3)
|
11
|
-
method_source (1.0.0)
|
12
|
-
pry (0.13.1)
|
13
|
-
coderay (~> 1.1)
|
14
|
-
method_source (~> 1.0)
|
15
|
-
rake (13.0.1)
|
16
|
-
rspec (3.9.0)
|
17
|
-
rspec-core (~> 3.9.0)
|
18
|
-
rspec-expectations (~> 3.9.0)
|
19
|
-
rspec-mocks (~> 3.9.0)
|
20
|
-
rspec-core (3.9.2)
|
21
|
-
rspec-support (~> 3.9.3)
|
22
|
-
rspec-expectations (3.9.2)
|
23
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
-
rspec-support (~> 3.9.0)
|
25
|
-
rspec-mocks (3.9.1)
|
26
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
-
rspec-support (~> 3.9.0)
|
28
|
-
rspec-support (3.9.3)
|
29
|
-
|
30
|
-
PLATFORMS
|
31
|
-
ruby
|
32
|
-
|
33
|
-
DEPENDENCIES
|
34
|
-
bundler (~> 2.1)
|
35
|
-
portrayal!
|
36
|
-
pry (~> 0.13)
|
37
|
-
rake (~> 13.0)
|
38
|
-
rspec (~> 3.9)
|
39
|
-
|
40
|
-
BUNDLED WITH
|
41
|
-
2.1.4
|