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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3375fc3fde1c42faa3d3ab97fd452cbe00bc869928d152a0ea67af139aab30d
4
- data.tar.gz: b4981b8264cc69a678dca36c666ee10ee82371e451ba067e558334240621de6a
3
+ metadata.gz: 3b49cf9fe619f10d5b29cd5a25cb5ad6b881c05db4a8de195235a471182e8a93
4
+ data.tar.gz: d90fbe0ae7d7886208207e12dbd71c99b07238a453fce26469fdef534f7210b5
5
5
  SHA512:
6
- metadata.gz: e823becbc89695f9e7cd9e6a2c494750b5507ffd6cf6d638089007e4f1294950b140d73f4494e7edc592f1116389f4800312c406913767c2b53076e718dddb56
7
- data.tar.gz: 6fd49203aec3eee88359bc7bb94dcc2782387c47c11f3bd4f8c53b20bfec76778061c8632575f526396795098e13d0833cbc23987a28a9667c0b72fd8785438f
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.0)
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.1.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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/typed_struct`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
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/[USERNAME]/typed_struct.
60
+ Bug reports and pull requests are welcome on GitHub at https://github.com/johansenja/typed_struct.
36
61
 
37
62
  ## License
38
63
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TypedStruct < Struct
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.4"
5
5
  end
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
- prop = properties[k]
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.class.options
37
- opts[:types].each do |prop, expected_type|
38
- passed_value = attrs[prop]
39
- next if val_is_type? passed_value, expected_type
40
-
41
- raise "Unexpected type #{passed_value.class} for #{prop.inspect} (expected #{expected_type})"
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
- def Rbs(type_str)
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.0
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-06-21 00:00:00.000000000 Z
11
+ date: 2021-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs