boba 0.0.11 → 0.0.13
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/README.md +13 -3
- data/lib/boba/relations_railtie.rb +19 -2
- data/lib/boba/version.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_relation_types.rb +67 -0
- data/lib/tapioca/dsl/compilers/attr_json.rb +5 -5
- data/lib/tapioca/dsl/compilers/{state_machines.rb → state_machines_extended.rb} +1 -1
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c88ef5656da55d5a864ad1bf3b5231907260c62f2239964f47921368dbffea8
|
4
|
+
data.tar.gz: c32f3fe6f3063407146db5559cee2d6714474e9f69eb769ce39278c961908537
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba9b4ccc7ffb27011848c62428a8cbed4cf9556bc3b63c04a4db867ed08ca12c2f16f48bc9f4c1f0ade04bd769d5033a977bc1e34f85115995c31dcdd65d21e0
|
7
|
+
data.tar.gz: dfe9d28722a6191722271c44b64ba2aec62eca438534b9617b2806d460c35c171635a662d6a6033d96220de6f3ff40cf0d4dc5e4122643ecad4fe3b6b6ac9b52
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Boba
|
2
2
|
|
3
|
-
> :warning: This
|
3
|
+
> :warning: This software is currently under active development. It should not be considered stable until 1.0.0.
|
4
4
|
|
5
5
|
Boba is a collection of compilers for Sorbet & Tapioca.
|
6
6
|
|
@@ -36,7 +36,8 @@ If you'd like to use relation types in your sigs that are less broad than `Activ
|
|
36
36
|
gem 'boba'
|
37
37
|
```
|
38
38
|
|
39
|
-
The railtie will automatically define the `PrivateRelation`
|
39
|
+
The railtie will automatically define the `PrivateRelation`, `PrivateAssociationRelation`, and `PrivateCollectionProxy` constants on each model that inherits from `ActiveRecord::Base`. These are defined as their corresponding private `ActiveRecord` classes, so runtime type checking works as expected. They can then be used in typing, like so:
|
40
|
+
|
40
41
|
```ruby
|
41
42
|
class Post < ::ActiveRecord::Base
|
42
43
|
scope :recent -> { where('created_at > ?', Date.current) }
|
@@ -49,7 +50,7 @@ sig { params(author: Author).returns(Post::PrivateRelation) }
|
|
49
50
|
def posts_from_author(author); end
|
50
51
|
```
|
51
52
|
|
52
|
-
and the following should not raise
|
53
|
+
and the following should not raise a Sorbet error:
|
53
54
|
|
54
55
|
```ruby
|
55
56
|
sig { params(author: Author).returns(Post::PrivateRelation) }
|
@@ -58,6 +59,15 @@ def recent_posts_from_author(author)
|
|
58
59
|
end
|
59
60
|
```
|
60
61
|
|
62
|
+
Boba also defines a type alias `RelationType` on each such class, which is defined as the union of the three relation types. This is useful because the relation types are often used interchangeably and so you may expect to return or pass any of the three classes as an argument. To use this, you will also need to use the `ActiveRecordRelationTypes` compiler to generate the type alias in the signatures as well (or define them manually in shims).
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
sig { params(author: Author).returns(Post::RelationType) }
|
66
|
+
def recent_posts_from_author(author)
|
67
|
+
posts_from_author(author).recent
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
61
71
|
## Contributing
|
62
72
|
|
63
73
|
Bugs and feature requests are welcome and should be [filed as issues on github](https://github.com/angellist/boba/issues).
|
@@ -6,13 +6,30 @@ require "rails/railtie"
|
|
6
6
|
class Boba::RelationsRailtie < Rails::Railtie
|
7
7
|
railtie_name(:boba)
|
8
8
|
|
9
|
-
initializer("boba.
|
9
|
+
initializer("boba.add_private_relation_constants") do
|
10
10
|
ActiveSupport.on_load(:active_record) do
|
11
11
|
module AciveRecordInheritDefineRelationTypes
|
12
12
|
def inherited(child)
|
13
13
|
super(child)
|
14
14
|
|
15
|
-
|
15
|
+
# Tapioca defines these three classes for each active record model as proxies for the actual AR internal
|
16
|
+
# classes. In order to be able to use these as types in signatures, we need to expose them as actual constants
|
17
|
+
# at runtime. Tapioca intentionally obfuscates these classes because they're private, so exposing them is
|
18
|
+
# _slightly_ dangerous in that someone could do something naughty. But we're not super worried about it.
|
19
|
+
child.const_set("PrivateRelation", child.const_get(:ActiveRecord_Relation))
|
20
|
+
child.const_set("PrivateAssociationRelation", child.const_get(:ActiveRecord_AssociationRelation))
|
21
|
+
child.const_set("PrivateCollectionProxy", child.const_get(:ActiveRecord_Associations_CollectionProxy))
|
22
|
+
|
23
|
+
# Expose a common type so that signatures can be typed to the broader `RelationType` since the three are often
|
24
|
+
# used interchangeably.
|
25
|
+
relation_type = T.type_alias do
|
26
|
+
T.any(
|
27
|
+
child.const_get(:PrivateRelation),
|
28
|
+
child.const_get(:PrivateAssociationRelation),
|
29
|
+
child.const_get(:PrivateCollectionProxy),
|
30
|
+
)
|
31
|
+
end
|
32
|
+
child.const_set(:RelationType, relation_type)
|
16
33
|
end
|
17
34
|
end
|
18
35
|
|
data/lib/boba/version.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
return unless defined?(ActiveRecord::Base)
|
5
|
+
|
6
|
+
require "tapioca/dsl/helpers/active_record_constants_helper"
|
7
|
+
require "tapioca/dsl/compilers/active_record_relations"
|
8
|
+
|
9
|
+
return unless defined?(Tapioca::Dsl::Compilers::ActiveRecordRelations)
|
10
|
+
|
11
|
+
module Tapioca
|
12
|
+
module Dsl
|
13
|
+
module Compilers
|
14
|
+
# `Tapioca::Dsl::Compilers::ActiveRecordRelationTypes` extends `Tapioca::Dsl::Compilers::ActiveRecordRelationTypes`
|
15
|
+
# to generate a `RelationType` type alias for each class. This type alias is defined a runtime through the Boba
|
16
|
+
# railtie, and is useful for typing signatures to accept or return relations. For instance, with the following
|
17
|
+
# `ActiveRecord::Base` subclass:
|
18
|
+
# ~~~rb
|
19
|
+
# class Post < ApplicationRecord
|
20
|
+
# end
|
21
|
+
# ~~~
|
22
|
+
#
|
23
|
+
# This compiler will produce the RBI file `post.rbi` with the following content:
|
24
|
+
# ~~~rbi
|
25
|
+
# # post.rbi
|
26
|
+
# # typed: true
|
27
|
+
#
|
28
|
+
# class Post
|
29
|
+
# RelationType = T.any(PrivateRelation, PrivateAssociationRelation, PrivateCollectionProxy)
|
30
|
+
# end
|
31
|
+
# ~~~
|
32
|
+
# So that the following method will accept any of the private relation types as an argument:
|
33
|
+
# ~~~rb
|
34
|
+
# sig { params(posts: Post::RelationType).void }
|
35
|
+
# def process_posts(posts)
|
36
|
+
# # ...
|
37
|
+
# end
|
38
|
+
# ~~~
|
39
|
+
class ActiveRecordRelationTypes < Compiler
|
40
|
+
extend T::Sig
|
41
|
+
|
42
|
+
ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
|
43
|
+
|
44
|
+
sig { override.void }
|
45
|
+
def decorate
|
46
|
+
root.create_path(constant) do |rbi_class|
|
47
|
+
relation_type_alias = "T.any(" \
|
48
|
+
"#{Tapioca::Dsl::Helpers::ActiveRecordConstantsHelper::RelationClassName}, " \
|
49
|
+
"#{Tapioca::Dsl::Helpers::ActiveRecordConstantsHelper::AssociationRelationClassName}, " \
|
50
|
+
"#{Tapioca::Dsl::Helpers::ActiveRecordConstantsHelper::AssociationsCollectionProxyClassName}" \
|
51
|
+
")"
|
52
|
+
rbi_class.create_type_variable("RelationType", type: "T.type_alias { #{relation_type_alias} }")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
extend T::Sig
|
58
|
+
|
59
|
+
sig { override.returns(T::Enumerable[Module]) }
|
60
|
+
def gather_constants
|
61
|
+
Tapioca::Dsl::Compilers::ActiveRecordRelations.gather_constants
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
1
|
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
|
-
return
|
4
|
+
return unless defined?(AttrJson::Record)
|
5
5
|
|
6
6
|
module Tapioca
|
7
7
|
module Dsl
|
@@ -39,7 +39,7 @@ module Tapioca
|
|
39
39
|
# Class methods module is already defined in the gem rbi, so just reference it here.
|
40
40
|
ClassMethodsModuleName = "AttrJson::Record::ClassMethods"
|
41
41
|
InstanceMethodModuleName = "AttrJsonGeneratedMethods"
|
42
|
-
ConstantType = type_member {{ fixed: T.any(T.class_of(::AttrJson::Record), T.class_of(::AttrJson::Model)) }}
|
42
|
+
ConstantType = type_member { { fixed: T.any(T.class_of(::AttrJson::Record), T.class_of(::AttrJson::Model)) } }
|
43
43
|
|
44
44
|
class << self
|
45
45
|
extend T::Sig
|
@@ -65,7 +65,7 @@ module Tapioca
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def decorate_attributes(rbi_scope)
|
68
|
-
|
68
|
+
constant.attr_json_registry
|
69
69
|
.definitions
|
70
70
|
.sort_by(&:name) # this is annoying, but we need to sort to force consistent ordering or the rbi checks fail
|
71
71
|
.each do |definition|
|
@@ -122,7 +122,7 @@ module Tapioca
|
|
122
122
|
|
123
123
|
sorbet_type = "::#{sorbet_type}"
|
124
124
|
sorbet_type = "T::Array[#{sorbet_type}]" if array
|
125
|
-
sorbet_type = "T.nilable(#{sorbet_type})" if nilable #
|
125
|
+
sorbet_type = "T.nilable(#{sorbet_type})" if nilable # TODO: improve this
|
126
126
|
|
127
127
|
sorbet_type
|
128
128
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Angellist
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-static-and-runtime
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: tapioca
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "<="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.16.
|
33
|
+
version: 0.16.5
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "<="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.16.
|
40
|
+
version: 0.16.5
|
41
41
|
description:
|
42
42
|
email:
|
43
43
|
- alex.stathis@angellist.com
|
@@ -54,18 +54,19 @@ files:
|
|
54
54
|
- lib/boba/version.rb
|
55
55
|
- lib/tapioca/dsl/compilers/active_record_associations_persisted.rb
|
56
56
|
- lib/tapioca/dsl/compilers/active_record_columns_persisted.rb
|
57
|
+
- lib/tapioca/dsl/compilers/active_record_relation_types.rb
|
57
58
|
- lib/tapioca/dsl/compilers/attr_json.rb
|
58
59
|
- lib/tapioca/dsl/compilers/money_rails.rb
|
59
60
|
- lib/tapioca/dsl/compilers/paperclip.rb
|
60
|
-
- lib/tapioca/dsl/compilers/
|
61
|
+
- lib/tapioca/dsl/compilers/state_machines_extended.rb
|
61
62
|
homepage: https://github.com/angellist/boba
|
62
63
|
licenses:
|
63
64
|
- MIT
|
64
65
|
metadata:
|
65
66
|
bug_tracker_uri: https://github.com/angellist/boba/issues
|
66
|
-
changelog_uri: https://github.com/angellist/boba/blob/0.0.
|
67
|
+
changelog_uri: https://github.com/angellist/boba/blob/0.0.13/History.md
|
67
68
|
homepage_uri: https://github.com/angellist/boba
|
68
|
-
source_code_uri: https://github.com/angellist/boba/tree/0.0.
|
69
|
+
source_code_uri: https://github.com/angellist/boba/tree/0.0.13
|
69
70
|
rubygems_mfa_required: 'true'
|
70
71
|
post_install_message:
|
71
72
|
rdoc_options: []
|