typed_struct 0.1.0 → 0.1.4
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/Gemfile.lock +2 -2
- data/README.md +32 -7
- data/lib/typed_struct/version.rb +1 -1
- data/lib/typed_struct.rb +38 -18
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b49cf9fe619f10d5b29cd5a25cb5ad6b881c05db4a8de195235a471182e8a93
|
|
4
|
+
data.tar.gz: d90fbe0ae7d7886208207e12dbd71c99b07238a453fce26469fdef534f7210b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3ee1d309ac25b3b76e03b5acf485c1d7ac6159aaf74adbad3e72db771a153679bfa0a08569f3957df7489cf221bfdd1f11fc0c648c065496cba74bffa7fa15e0
|
|
7
|
+
data.tar.gz: c30d9b77718eb33435ec5b5995c078db3cf1a99e0d456c1a45f26b06bac57bbc14d255adc070a965b81df7aafb6edd9d0074fd74851c828d1681685a1d375e61
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
typed_struct (0.1.
|
|
4
|
+
typed_struct (0.1.4)
|
|
5
5
|
rbs (~> 1.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -9,7 +9,7 @@ GEM
|
|
|
9
9
|
specs:
|
|
10
10
|
diff-lcs (1.4.4)
|
|
11
11
|
rake (13.0.3)
|
|
12
|
-
rbs (1.
|
|
12
|
+
rbs (1.5.1)
|
|
13
13
|
rspec (3.10.0)
|
|
14
14
|
rspec-core (~> 3.10.0)
|
|
15
15
|
rspec-expectations (~> 3.10.0)
|
data/README.md
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
# TypedStruct
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Typed Struct is a lightweight data structure inspired by [Dry Struct](https://github.com/dry-rb/dry-struct), which allows for reading and writing properties while making use of a flexible and powerful type checking system, which also incorporates Ruby's [RBS](https://github.com/ruby/rbs/) for type definitions.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Example
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
require 'typed_struct' # unless using rails
|
|
9
|
+
|
|
10
|
+
User = TypedStruct.new name: String, # an instance of String
|
|
11
|
+
age: Integer, # an instance of Integer
|
|
12
|
+
username: /\w{4,}/, # must match given Regexp
|
|
13
|
+
rating: (0..5), # must be value from 0 to 5
|
|
14
|
+
type: "User", # must by a string with value "User"
|
|
15
|
+
interests: Rbs("Array[String]"), # an RBS generic type (an Array of Strings)
|
|
16
|
+
preferences: Rbs("{ opt_out_of_emails: bool, additional: untyped }") # RBS record type
|
|
17
|
+
|
|
18
|
+
clive = User.new name: "Clive",
|
|
19
|
+
age: 22,
|
|
20
|
+
interests: %w[surfing skiing],
|
|
21
|
+
preferences: { opt_out_of_emails: true, additional: { preferred_theme: :dark } },
|
|
22
|
+
type: "User",
|
|
23
|
+
rating: 4,
|
|
24
|
+
username: "cliveabc"
|
|
25
|
+
|
|
26
|
+
clive.age # 22
|
|
27
|
+
clive.age = '22' # => Error
|
|
28
|
+
clive.preferences = { "opt_out_of_emails" => true, "additional" => nil } # error - type mismatch, not Symbol keys
|
|
29
|
+
clive.freeze # no more changes can be made
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Note that a `TypedStruct` inherits from `Struct` directly, so anything from `Struct` is also available in `TypedStruct` - see [Struct docs](https://ruby-doc.org/core-3.0.1/Struct.html) for more info.
|
|
33
|
+
|
|
34
|
+
**See [RBS reference](https://github.com/ruby/rbs/blob/3c046c77c3006211a1a14eedc35221ac4198f788/docs/syntax.md) for more info on writing RBS types**
|
|
6
35
|
|
|
7
36
|
## Installation
|
|
8
37
|
|
|
@@ -20,10 +49,6 @@ Or install it yourself as:
|
|
|
20
49
|
|
|
21
50
|
$ gem install typed_struct
|
|
22
51
|
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
|
-
TODO: Write usage instructions here
|
|
26
|
-
|
|
27
52
|
## Development
|
|
28
53
|
|
|
29
54
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -32,7 +57,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
|
32
57
|
|
|
33
58
|
## Contributing
|
|
34
59
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
60
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/johansenja/typed_struct.
|
|
36
61
|
|
|
37
62
|
## License
|
|
38
63
|
|
data/lib/typed_struct/version.rb
CHANGED
data/lib/typed_struct.rb
CHANGED
|
@@ -4,11 +4,27 @@ require_relative "typed_struct/version"
|
|
|
4
4
|
require_relative "typed_struct/type_checking"
|
|
5
5
|
require "rbs"
|
|
6
6
|
|
|
7
|
+
def Rbs(type_str)
|
|
8
|
+
RBS::Parser.parse_type(type_str)
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
class TypedStruct < Struct
|
|
8
12
|
include TypeChecking
|
|
9
13
|
|
|
14
|
+
OVERRIDING_NATIVE_METHOD_MSG =
|
|
15
|
+
"*** WARNING *** property %s overrides a native method in #{name}. Consider using something else (called from %s)".freeze
|
|
16
|
+
|
|
17
|
+
# any methods which are able to be overridden
|
|
18
|
+
alias_method :__class__, :class
|
|
19
|
+
|
|
10
20
|
class << self
|
|
11
|
-
def new(**properties)
|
|
21
|
+
def new(opts = Options.new, **properties)
|
|
22
|
+
properties.each_key do |prop|
|
|
23
|
+
if method_defined?(prop)
|
|
24
|
+
$stdout.puts OVERRIDING_NATIVE_METHOD_MSG % [prop.inspect, caller(3).first]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
12
28
|
super(*properties.keys, keyword_init: true).tap do |klass|
|
|
13
29
|
klass.class.instance_eval do
|
|
14
30
|
include TypeChecking
|
|
@@ -16,15 +32,20 @@ class TypedStruct < Struct
|
|
|
16
32
|
end
|
|
17
33
|
|
|
18
34
|
klass.instance_eval do
|
|
19
|
-
@options = { types: properties }
|
|
35
|
+
@options = { types: properties, options: opts }
|
|
36
|
+
|
|
37
|
+
define_method :[]= do |key, val|
|
|
38
|
+
prop = properties[key]
|
|
39
|
+
unless val_is_type? val, prop
|
|
40
|
+
raise "Unexpected type #{val.class} for #{key.inspect} (expected #{prop})"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
super key, val
|
|
44
|
+
end
|
|
45
|
+
|
|
20
46
|
properties.each_key do |k|
|
|
21
47
|
define_method :"#{k}=" do |val|
|
|
22
|
-
|
|
23
|
-
if val_is_type? val, prop
|
|
24
|
-
raise "Unexpected type #{val.class} for #{k.inspect} (expected #{prop})"
|
|
25
|
-
end
|
|
26
|
-
# it seems that structs behave in such a way that you can't call super here, but it
|
|
27
|
-
# will still set the value anyway
|
|
48
|
+
self[k] = val
|
|
28
49
|
end
|
|
29
50
|
end
|
|
30
51
|
end
|
|
@@ -33,18 +54,17 @@ class TypedStruct < Struct
|
|
|
33
54
|
end
|
|
34
55
|
|
|
35
56
|
def initialize(**attrs)
|
|
36
|
-
opts = self.
|
|
37
|
-
opts[:types].
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
opts = self.__class__.options
|
|
58
|
+
vals = opts[:types].to_h do |prop, expected_type|
|
|
59
|
+
value = attrs.fetch(prop, opts[:options][:default])
|
|
60
|
+
unless val_is_type? value, expected_type
|
|
61
|
+
raise "Unexpected type #{value.class} for #{prop.inspect} (expected #{expected_type})"
|
|
62
|
+
end
|
|
63
|
+
[prop, value]
|
|
42
64
|
end
|
|
43
65
|
|
|
44
|
-
super
|
|
66
|
+
super **vals
|
|
45
67
|
end
|
|
46
|
-
end
|
|
47
68
|
|
|
48
|
-
|
|
49
|
-
RBS::Parser.parse_type(type_str)
|
|
69
|
+
Options = TypedStruct.new({ default: nil }, default: Rbs("untyped"))
|
|
50
70
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typed_struct
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joseph Johansen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rbs
|