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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a6532caf62048d8a54a3dccfca29166c8277b47c19765d9ce8ee02b97ee709c
4
- data.tar.gz: d58115282488d0c4dc22bacf65e8ea83e98986653b29798d6cade1d705e04fba
3
+ metadata.gz: fbd0b561e866c45f6e850b592620df78d4573635165807cd2284ab45baed9e0c
4
+ data.tar.gz: 699be912aa836a55faa10886a3a1c1bb7b17c006f1db445694660d2fbe0ec0f4
5
5
  SHA512:
6
- metadata.gz: c177e83e03d1d80e6bcfa1970c3786a9e496f5d1e09df05d7758772be244d1c056c28971c4c4b1de6c040c8ea839b34c4e69b2cdf38bdc2bd1269133640bad1b
7
- data.tar.gz: d664544c2fa4b822c8d677efe546ae13521daed0e700fd20ec72255a13595014213934154abe5ef70f7a94dce8ef5a886493c430ba41791b1a9c38b57bdae2f4
6
+ metadata.gz: 58fc168ad299aee9555ec7e1a1355f533c65af5ff1620095a7e49829252b39e92f45714083cc03fd1cde2ccc027acabd98b3526618caae07fb226be7e294694b
7
+ data.tar.gz: 8d59938b7bdcc5b9a32683695b6146186cb12bf6132326ecfff5b01685b7740dbf78ef513a43fbf5ff58716c38848881229600e4eb2f059dc13efc530120d68d
@@ -2,9 +2,9 @@ name: RSpec
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [ master ]
5
+ branches: [ main ]
6
6
  pull_request:
7
- branches: [ master ]
7
+ branches: [ main ]
8
8
 
9
9
  jobs:
10
10
  test:
data/.gitignore CHANGED
@@ -7,5 +7,8 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ # Recommended for gems
11
+ /Gemfile.lock
12
+
10
13
  # rspec failure tracking
11
14
  .rspec_status
@@ -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
- ![RSpec](https://github.com/scottscheapflights/portrayal/workflows/RSpec/badge.svg?branch=master)
1
+ ![RSpec](https://github.com/scottscheapflights/portrayal/workflows/RSpec/badge.svg)
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, optional: true
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, optional: true
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=>{:optional=>false, :default=>nil}, :city=>{:optional=>false, :default=>nil}, :postcode=>{:optional=>false, :default=>nil}, :country=>{:optional=>true, :default=>[:return, nil]}}
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, optional: true
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, optional: true
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/master/CODE_OF_CONDUCT.md).
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).
@@ -4,7 +4,7 @@ require 'portrayal/schema'
4
4
  module Portrayal
5
5
  NULL = :_portrayal_value_not_set
6
6
 
7
- def keyword(name, optional: NULL, default: NULL, define: nil, &block)
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(portrayal.definition_of_object_enhancements)
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, optional, default)
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
@@ -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
- def initialize; @schema = {} end
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('@' + key.to_s, value.dup)
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('@' + key.to_s, value.clone)
32
+ instance_variable_set("@\#{key}", value.clone)
82
33
  end
83
34
  super
84
35
  end
85
- RUBY
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
@@ -1,3 +1,3 @@
1
1
  module Portrayal
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -1,6 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
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.6.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-08-11 00:00:00.000000000 Z
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: '0'
110
+ version: 2.4.0
108
111
  required_rubygems_version: !ruby/object:Gem::Requirement
109
112
  requirements:
110
113
  - - ">="
@@ -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