portrayal 0.9.0 → 0.9.1

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: acf906a0356260f40fbe25b94b12f72f8c696ee723dff3c2f7dc0f3817154fd0
4
- data.tar.gz: 0bb4b5a5d4982a59f6e66cd7fa2fe7eeec93b7880537c9e605c47f2d1b0df009
3
+ metadata.gz: dd6f188d345ad88e1da91277955947e32f1b7dfc9b0d0f840b4164bd0ad17930
4
+ data.tar.gz: a087113263a3ec551fa4d0c2ba3ab529172ff8252a5782fcc495a838a9f30e8c
5
5
  SHA512:
6
- metadata.gz: 5d3543a802ba4dad5b8c746fa2e187b0debb95bd52354509bb29c2d88e6977d622aeafc8fca3db0a65811a9918c7044985c3355bea78799a0b7730b84da28e21
7
- data.tar.gz: 66f61afd2be1633c12739d49db088265d90279b622b4f4bf050bba2c4d7dc6444ce232e16be00485702ef9285fe2507758d8fdfee447414ac35bc44fe07a5e89
6
+ metadata.gz: 278094b098ec368126dd078903d4a523dd2344dadee05195f0712a47daaab186638a385c45f822b993d35e4aef3f5bf56f2ec5b3722b348efa1e0f553277887a
7
+ data.tar.gz: fbb5ce904eb704669e8a59990b7a2c959e2559f265f6a38ce9be5b1aff19b4363bbdd4fb982ac8e465aa483c883ebc91e18c3c0fd7c641a316048da304fc9a29
@@ -6,7 +6,7 @@ jobs:
6
6
  strategy:
7
7
  fail-fast: false
8
8
  matrix:
9
- ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.2' ]
9
+ ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.2', '3.3', '3.4' ]
10
10
 
11
11
  name: Ruby ${{ matrix.ruby }}
12
12
  steps:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.9.1 - 2025-01-28
6
+
7
+ * Add aliases for all redefined methods to suppress method redefinition warnings.
8
+ * Add `+''` to mutated strings to suppress Ruby 3.4 frozen string literal warnings.
9
+
5
10
  ## 0.9.0 - 2023-05-06
6
11
 
7
12
  None of these changes should break anything for you, only speed things up, unless you're doing something very weird.
data/README.md CHANGED
@@ -8,7 +8,7 @@ Inspired by:
8
8
  - Piotr Solnica's [virtus](https://github.com/solnic/virtus)
9
9
  - Everything [Michel Martens](https://github.com/soveran)
10
10
 
11
- Portrayal is a minimalist gem (~110 loc, no dependencies) for building struct-like classes. It provides a small yet powerful step up from plain ruby with its one and only `keyword` method.
11
+ Portrayal is a minimalist gem (~122 loc, no dependencies) for building struct-like classes. It provides a small yet powerful step up from plain ruby with its one and only `keyword` method.
12
12
 
13
13
  ```ruby
14
14
  class Person < MySuperClass
@@ -56,24 +56,25 @@ class Person < MySuperClass
56
56
  @address = address
57
57
  end
58
58
 
59
- def eql?(other)
60
- self.class == other.class && self == other
61
- end
62
-
63
59
  def ==(other)
64
- { name: name, age: age, favorite_fruit: favorite_fruit, address: address } ==
65
- { name: other.name, age: other.age, favorite_fruit: other.favorite_fruit, address: other.address }
60
+ self.class == other.class &&
61
+ @name == other.instance_variable_get('@name') &&
62
+ @age == other.instance_variable_get('@age') &&
63
+ @favorite_fruit == other.instance_variable_get('@favorite_fruit') &&
64
+ @address == other.instance_variable_get('@address')
66
65
  end
67
66
 
67
+ alias eql? ==
68
+
68
69
  def hash
69
- [ self.class, { name: name, age: age, favorite_fruit: favorite_fruit, address: address } ].hash
70
+ [ self.class, { name: @name, age: @age, favorite_fruit: @favorite_fruit, address: @address } ].hash
70
71
  end
71
72
 
72
73
  def freeze
73
- name.freeze
74
- age.freeze
75
- favorite_fruit.freeze
76
- address.freeze
74
+ @name.freeze
75
+ @age.freeze
76
+ @favorite_fruit.freeze
77
+ @address.freeze
77
78
  super
78
79
  end
79
80
 
@@ -86,18 +87,18 @@ class Person < MySuperClass
86
87
  end
87
88
 
88
89
  def initialize_dup(source)
89
- @name = source.name.dup
90
- @age = source.age.dup
91
- @favorite_fruit = source.favorite_fruit.dup
92
- @address = source.address.dup
90
+ @name = source.instance_variable_get('@name').dup
91
+ @age = source.instance_variable_get('@age').dup
92
+ @favorite_fruit = source.instance_variable_get('@favorite_fruit').dup
93
+ @address = source.instance_variable_get('@address').dup
93
94
  super
94
95
  end
95
96
 
96
97
  def initialize_clone(source)
97
- @name = source.name.clone
98
- @age = source.age.clone
99
- @favorite_fruit = source.favorite_fruit.clone
100
- @address = source.address.clone
98
+ @name = source.instance_variable_get('@name').clone
99
+ @age = source.instance_variable_get('@age').clone
100
+ @favorite_fruit = source.instance_variable_get('@favorite_fruit').clone
101
+ @address = source.instance_variable_get('@address').clone
101
102
  super
102
103
  end
103
104
 
@@ -114,21 +115,21 @@ class Person < MySuperClass
114
115
  "#{street}, #{city}"
115
116
  end
116
117
 
117
- def eql?(other)
118
- self.class == other.class && self == other
119
- end
120
-
121
118
  def ==(other)
122
- { street: street, city: city } == { street: other.street, city: other.city }
119
+ self.class == other.class &&
120
+ @street == other.instance_variable_get('@street') &&
121
+ @city == other.instance_variable_get('@city')
123
122
  end
124
123
 
124
+ alias eql? ==
125
+
125
126
  def hash
126
- [ self.class, { street: street, city: city } ].hash
127
+ [ self.class, { street: @street, city: @city } ].hash
127
128
  end
128
129
 
129
130
  def freeze
130
- street.freeze
131
- city.freeze
131
+ @street.freeze
132
+ @city.freeze
132
133
  super
133
134
  end
134
135
 
@@ -141,14 +142,14 @@ class Person < MySuperClass
141
142
  end
142
143
 
143
144
  def initialize_dup(source)
144
- @street = source.street.dup
145
- @city = source.city.dup
145
+ @street = source.instance_variable_get('@street').dup
146
+ @city = source.instance_variable_get('@city').dup
146
147
  super
147
148
  end
148
149
 
149
150
  def initialize_clone(source)
150
- @street = source.street.clone
151
- @city = source.city.clone
151
+ @street = source.instance_variable_get('@street').clone
152
+ @city = source.instance_variable_get('@city').clone
152
153
  super
153
154
  end
154
155
  end
@@ -394,7 +395,7 @@ Since a portrayal object is read-only (nothing stops you from adding writers, bu
394
395
  class Address < ApplicationStruct
395
396
  class << self
396
397
  def from_form(params)
397
- raise ArgumentError, 'invalid postcode' unless postcode =~ /\A\d+\z/
398
+ raise ArgumentError, 'invalid postcode' if params[:postcode] !~ /\A\d+\z/
398
399
 
399
400
  new \
400
401
  street: params[:street].to_s,
@@ -490,6 +491,16 @@ def deconstruct_keys(keys)
490
491
  filtered_keys &= keys if Array === keys
491
492
  Hash[filtered_keys.map { |k| [k, public_send(k)] }]
492
493
  end
494
+ alias initialize initialize
495
+ alias hash hash
496
+ alias == ==
497
+ alias eql? eql?
498
+ alias freeze freeze
499
+ alias initialize_dup initialize_dup
500
+ alias initialize_clone initialize_clone
501
+ alias deconstruct deconstruct
502
+ alias deconstruct_keys deconstruct_keys
503
+ alias street street; alias street= street=; alias city city; alias city= city=; alias postcode postcode; alias postcode= postcode=; alias country country; alias country= country=
493
504
  ```
494
505
 
495
506
  #### Implementation decisions
data/bin/bench CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # This file is a set of benchmarks directly or tangentially related to
4
+ # implementation decisions.
5
+
3
6
  require 'bundler/setup'
4
7
  require 'portrayal'
5
8
  require 'benchmark/ips'
data/bin/loc CHANGED
@@ -1,2 +1,3 @@
1
1
  #!/usr/bin/env bash
2
+ # Count LOC in the project for pasting into README.
2
3
  find lib -name '*.rb' | xargs wc -l
data/bin/module CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # This is a demo of what module code looks like, for pasting into README.
4
+
3
5
  require 'bundler/setup'
4
6
  require 'portrayal'
5
7
 
@@ -23,8 +23,8 @@ class Portrayal::Schema
23
23
  end
24
24
 
25
25
  def render_module_code
26
- args, inits, syms, hash, eqls, dups, clones, setters, freezes =
27
- '', '', '', '', '', '', '', '', ''
26
+ args, inits, syms, hash, eqls, dups, clones, setters, freezes, aliases =
27
+ +'', +'', +'', +'', +'', +'', +'', +'', +'', +'' # + keeps string unfrozen
28
28
 
29
29
  @schema.each do |k, default|
30
30
  args << "#{k}:#{default && " self.class.portrayal.schema[:#{k}]"}, "
@@ -36,6 +36,7 @@ class Portrayal::Schema
36
36
  clones << "@#{k} = src.instance_variable_get('@#{k}').clone; "
37
37
  setters << ":#{k}=, "
38
38
  freezes << "@#{k}.freeze; "
39
+ aliases << "alias #{k} #{k}; alias #{k}= #{k}=; "
39
40
  end
40
41
 
41
42
  args.chomp!(', ') # key1:, key2: self.class.portrayal.schema[:key2]
@@ -47,7 +48,10 @@ class Portrayal::Schema
47
48
  clones.chomp!('; ') # @key1 = src.instance_variable_get('@key1').clone;
48
49
  setters.chomp!(', ') # :key1=, :key2=
49
50
  freezes.chomp!('; ') # @key1.freeze; @key2.freeze
51
+ aliases.chomp!('; ') # alias key1 key1; alias key1= key1=
50
52
 
53
+ # Aliases at the bottom help prevent method redefinition warnings.
54
+ # See https://bugs.ruby-lang.org/issues/17055 for details.
51
55
  <<-RUBY
52
56
  attr_accessor #{syms}
53
57
  protected #{setters}
@@ -67,6 +71,16 @@ def deconstruct_keys(keys)
67
71
  filtered_keys &= keys if Array === keys
68
72
  Hash[filtered_keys.map { |k| [k, public_send(k)] }]
69
73
  end
74
+ alias initialize initialize
75
+ alias hash hash
76
+ alias == ==
77
+ alias eql? eql?
78
+ alias freeze freeze
79
+ alias initialize_dup initialize_dup
80
+ alias initialize_clone initialize_clone
81
+ alias deconstruct deconstruct
82
+ alias deconstruct_keys deconstruct_keys
83
+ #{aliases}
70
84
  RUBY
71
85
  end
72
86
  end
@@ -1,3 +1,3 @@
1
1
  module Portrayal
2
- VERSION = '0.9.0'
2
+ VERSION = '0.9.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: portrayal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Chernyak
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-05-07 00:00:00.000000000 Z
10
+ date: 2025-01-28 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rake
@@ -102,7 +101,6 @@ metadata:
102
101
  homepage_uri: https://github.com/maxim/portrayal
103
102
  source_code_uri: https://github.com/maxim/portrayal
104
103
  changelog_uri: https://github.com/maxim/portrayal/blob/main/CHANGELOG.md
105
- post_install_message:
106
104
  rdoc_options: []
107
105
  require_paths:
108
106
  - lib
@@ -117,8 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
115
  - !ruby/object:Gem::Version
118
116
  version: '0'
119
117
  requirements: []
120
- rubygems_version: 3.4.2
121
- signing_key:
118
+ rubygems_version: 3.6.3
122
119
  specification_version: 4
123
120
  summary: A minimal builder for struct-like classes
124
121
  test_files: []