typed_struct 0.1.0 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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