orthoses-rails 1.8.1 → 1.9.0

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: cc54caaf37167d7f0daa8a69f17d0776ab4475e5f416c82b27df0598624c5479
4
- data.tar.gz: 400219e841b26f2d07996717634a16ba1d983b5abb4a1272ca8fc5f5b7b5d0a2
3
+ metadata.gz: 9c6dae9c8bb5c75510f72e22da5f64146257fa400f727556fc9ba362b5314451
4
+ data.tar.gz: 4b1abfccbdfaf8257cae7bfc680e3d224928b20ef1c9a7d6db95ba87a200bead
5
5
  SHA512:
6
- metadata.gz: 52963191cb29945fe832adf1688474cb554803c743cd023f98de8dad3fe9bdc7e5461b426c5e6bbe6146dcc9d7ee02e9fc810b9a9814950240fe2bb66bd118b1
7
- data.tar.gz: 7fe661c22f957eef62f2dc04eef9845e7000f052c88deddf7e359b99e962c44a6fdd5411efe6d3db6342ebf3c47ced1fbfd6454564427559112d170eee65e914
6
+ metadata.gz: c649345760163f2df4e274b8fc10e6c07431301829bc3a0e32ab76a1e1586859affadb56e61c397177b25553b4fe3bebaf40dde4c25ee216f3a479bdab5a8169
7
+ data.tar.gz: f6cebe8cdb7fddab69d3654fe70e84a03790182901b5335d2da2f5289f815f7802ff2508cce1abd8840b0c984eace3d8f355e07279f86c229cc6f7896acc5c76
data/README.md CHANGED
@@ -15,15 +15,122 @@ $ bundle exec rbs collection install
15
15
  Build your Rake task for RBS generation.
16
16
 
17
17
  ```
18
- $ bin/rails generate orthoses:rails:install
18
+ $ bundle exec rails generate orthoses:rails:install
19
19
  ```
20
20
 
21
21
  Then run the rake task.
22
22
 
23
23
  ```
24
- $ bin/rails orthoses:rails
24
+ $ bundle exec rails orthoses:rails
25
25
  ```
26
26
 
27
+ Output is stored in the `sig/orthoses` directory.
28
+
29
+ ## Output example
30
+
31
+ ```rb
32
+ class User < ApplicationRecord
33
+ has_one :email_account, dependent: :destroy
34
+ end
35
+ ```
36
+
37
+ ```rbs
38
+ class User < ::ApplicationRecord
39
+ include User::GeneratedAssociationMethods
40
+ include User::GeneratedAttributeMethods
41
+ extend User::ActiveRecord_Persistence_ClassMethods
42
+ extend _ActiveRecord_Relation_ClassMethods[User, User::ActiveRecord_Relation, Integer]
43
+ end
44
+
45
+ class User::ActiveRecord_Associations_CollectionProxy < ::ActiveRecord::Associations::CollectionProxy
46
+ include _ActiveRecord_Relation[User, Integer]
47
+ include Enumerable[User]
48
+ end
49
+
50
+ module User::ActiveRecord_Persistence_ClassMethods
51
+ def build: (?id: Integer, ?created_at: ActiveSupport::TimeWithZone?, ?updated_at: ActiveSupport::TimeWithZone?, ?nickname: String?, **untyped) ?{ (User) -> void } -> User
52
+ | (Array[Hash[Symbol, untyped]]) ?{ (User) -> void } -> Array[User]
53
+
54
+ def create: (?id: Integer, ?created_at: ActiveSupport::TimeWithZone?, ?updated_at: ActiveSupport::TimeWithZone?, ?nickname: String?, **untyped) ?{ (User) -> void } -> User
55
+ | (Array[Hash[Symbol, untyped]]) ?{ (User) -> void } -> Array[User]
56
+
57
+ def create!: (?id: Integer, ?created_at: ActiveSupport::TimeWithZone?, ?updated_at: ActiveSupport::TimeWithZone?, ?nickname: String?, **untyped) ?{ (User) -> void } -> User
58
+ | (Array[Hash[Symbol, untyped]]) ?{ (User) -> void } -> Array[User]
59
+ end
60
+
61
+ class User::ActiveRecord_Relation < ::ActiveRecord::Relation
62
+ include Enumerable[User]
63
+ include User::GeneratedRelationMethods
64
+ include _ActiveRecord_Relation[User, Integer]
65
+ end
66
+
67
+ module ::User::GeneratedAssociationMethods
68
+ def build_email_account: (?untyped attributes) ?{ (EmailAccount) -> void } -> EmailAccount
69
+
70
+ def create_email_account: (?untyped attributes) ?{ (EmailAccount) -> void } -> EmailAccount
71
+
72
+ def create_email_account!: (?untyped attributes) ?{ (EmailAccount) -> void } -> EmailAccount
73
+
74
+ def email_account: () -> EmailAccount?
75
+
76
+ def email_account=: (EmailAccount?) -> EmailAccount?
77
+
78
+ # ...snip...
79
+ end
80
+
81
+ module ::User::GeneratedAttributeMethods
82
+ attr_accessor id: ::Integer
83
+
84
+ attr_accessor nickname: ::String?
85
+
86
+ attr_accessor updated_at: ::ActiveSupport::TimeWithZone?
87
+
88
+ attr_accessor created_at: ::ActiveSupport::TimeWithZone?
89
+
90
+ # ...snip...
91
+ end
92
+
93
+ module ::User::GeneratedRelationMethods
94
+ # ...snip...
95
+ end
96
+ ```
97
+
98
+ ## Supported methods
99
+
100
+ ### ActionMailer
101
+
102
+ - Action methods
103
+
104
+ ### ActiveModel
105
+
106
+ - `attribute`
107
+ - `has_secure_password`
108
+
109
+ ### ActiveRecord
110
+
111
+ - Column attribute methods
112
+ - `belongs_to`
113
+ - `delegated_type`
114
+ - `enum`
115
+ - `has_many`
116
+ - `has_one`
117
+ - Relation and CollectionProxy methods
118
+ - `scope`
119
+ - `secure_token`
120
+
121
+ ### ActiveStorage
122
+
123
+ - `has_one_attached`
124
+
125
+ ### ActiveSupport
126
+
127
+ - `alias_attribute`
128
+ - `class_attribute`
129
+ - `class_methods`
130
+ - `config_accessor`
131
+ - `delegate`
132
+ - `mattr_accessor`
133
+
27
134
  ## Installation
28
135
 
29
136
  Install the gem and add to the application's Gemfile by executing:
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Orthoses
4
4
  module ActiveRecord
5
- # <= 6.1
6
- # def enum(definitions)
7
5
  # >= 7.0
8
6
  # def enum(name = nil, values = nil, **options)
9
7
  class Enum
@@ -26,27 +24,19 @@ module Orthoses
26
24
  store[base_name] << sig
27
25
  end
28
26
 
29
- if capture.argument[:definitions]
30
- # on rails 6
31
- definitions = capture.argument[:definitions].slice!(:_prefix, :_suffix, :_scopes, :_default)
32
- options = capture.argument[:definitions].transform_keys { |key| :"#{key[1..-1]}" }
33
- definitions.each { |name, values| _enum(store, base_name, name, values, **options) }
27
+ name = capture.argument[:name]
28
+ values = capture.argument[:values]
29
+ options = capture.argument[:options]
30
+ if name
31
+ # rails 7 style
32
+ values, options = options, {} unless values
33
+ _enum(store, base_name, name, values, **options)
34
34
  else
35
- # on rails 7
36
- name = capture.argument[:name]
37
- values = capture.argument[:values]
38
- options = capture.argument[:options]
39
- if name
40
- # rails 7 style
41
- values, options = options, {} unless values
42
- _enum(store, base_name, name, values, **options)
43
- else
44
- # rails 6 style
45
- definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
46
- options.transform_keys! { |key| :"#{key[1..-1]}" }
35
+ # rails 6 style (will remove rails 8)
36
+ definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
37
+ options.transform_keys! { |key| :"#{key[1..-1]}" }
47
38
 
48
- definitions.each { |name, values| _enum(store, base_name, name, values, **options) }
49
- end
39
+ definitions.each { |name, values| _enum(store, base_name, name, values, **options) }
50
40
  end
51
41
  end
52
42
 
@@ -87,6 +77,7 @@ module Orthoses
87
77
  # Expressing type casting.
88
78
  overloads = [] #: Array[String]
89
79
  if pairs.length <= @strict_limit
80
+ store[base_name] << "type #{name}_return = #{pairs.keys.map { |k| "\"#{k}\"" }.join(" | ")}"
90
81
  if pairs.keys.any? { |key| key.match?(/[^a-zA-Z_]/) }
91
82
  overloads << "(Symbol) -> void"
92
83
  else
@@ -94,12 +85,13 @@ module Orthoses
94
85
  end
95
86
  overloads << "(#{pairs.keys.map{|key|key.to_s.inspect}.join(" | ")}) -> void"
96
87
  overloads << "(#{pairs.values.map(&:inspect).join(" | ")}) -> void"
97
- store[base_name] << "def #{name}: () -> (#{pairs.keys.map { |k| "\"#{k}\"" }.join(" | ")})"
88
+ store[base_name] << "def #{name}: () -> #{name}_return"
98
89
  store[base_name] << "def #{name}=: #{overloads.join(" | ")}"
99
90
  else
91
+ store[base_name] << "type #{name}_return = String"
100
92
  overloads << "(Symbol | String) -> void"
101
93
  overloads << "(#{pairs.values.map { |v| Orthoses::Utils.object_to_rbs(v) }.uniq.join(" | ")}) -> void"
102
- store[base_name] << "def #{name}: () -> String"
94
+ store[base_name] << "def #{name}: () -> #{name}_return"
103
95
  store[base_name] << "def #{name}=: #{overloads.join(" | ")}"
104
96
  end
105
97
  end
@@ -25,8 +25,12 @@ module Orthoses
25
25
  "will_save_change_to_attribute?" => "() -> bool",
26
26
  }
27
27
 
28
- def initialize(loader)
28
+ def initialize(loader, targets: TARGET_TYPE_MAP.keys)
29
29
  @loader = loader
30
+ unless targets.all? { |target| TARGET_TYPE_MAP.key?(target) }
31
+ raise ArgumentError, "Unknown target type: #{targets - TARGET_TYPE_MAP.keys}"
32
+ end
33
+ @targets = targets
30
34
  end
31
35
 
32
36
  def call
@@ -50,12 +54,13 @@ module Orthoses
50
54
 
51
55
  lines << "attr_accessor #{name}: #{type}"
52
56
  attribute_method_patterns(::ActiveRecord::Base).each do |matcher|
53
- tmpl = TARGET_TYPE_MAP[matcher.proxy_target] or next
57
+ tmpl = target_type(matcher.proxy_target) or next
54
58
  lines << "def #{matcher.method_name(name)}: #{tmpl % {type: type, opt: opt}}"
55
59
  end
56
60
  end
57
61
  klass.attribute_aliases.each do |alias_name, column_name|
58
62
  attribute_method_patterns(::ActiveRecord::Base).each do |matcher|
63
+ next unless matcher.proxy_target == "attribute" || target_type(matcher.proxy_target)
59
64
  lines << "alias #{matcher.method_name(alias_name)} #{matcher.method_name(column_name)}"
60
65
  end
61
66
  end
@@ -82,6 +87,11 @@ module Orthoses
82
87
  end
83
88
  end
84
89
  end
90
+
91
+ def target_type(target)
92
+ return unless @targets.include?(target)
93
+ TARGET_TYPE_MAP[target]
94
+ end
85
95
  end
86
96
  end
87
97
  end
@@ -23,7 +23,7 @@ module Orthoses
23
23
  # Expressing delegation.
24
24
  store[class_specific_generated_relation_methods].tap do |c|
25
25
  klass.singleton_methods(false).each do |singleton_method|
26
- c << "def #{singleton_method}: (*untyped, **untyped) -> untyped"
26
+ c << "def #{singleton_method}: (?) -> untyped"
27
27
  end
28
28
  if @strict
29
29
  (klass.singleton_class.included_modules - ::ActiveRecord::Relation.included_modules).each do |mod|
@@ -44,6 +44,7 @@ module Orthoses
44
44
  store[class_specific_proxy].tap do |c|
45
45
  c.header = "class #{class_specific_proxy} < ::ActiveRecord::Associations::CollectionProxy"
46
46
  c << "include _ActiveRecord_Relation[#{model_name}, #{primary_key}]"
47
+ c << "include Enumerable[#{model_name}]"
47
48
  end
48
49
 
49
50
  store[model_name].tap do |c|
@@ -32,6 +32,10 @@ module Orthoses
32
32
  private
33
33
 
34
34
  def parameters_to_type(parameters)
35
+ # foo(...)
36
+ if parameters in [[:rest, :*], [:keyrest, :**], [:block, :&]]
37
+ return "(?)"
38
+ end
35
39
  # @type var res: Array[String]
36
40
  res = []
37
41
  # @type var block: String?
@@ -50,7 +50,7 @@ module Orthoses
50
50
  # no type found
51
51
  capture.argument[:methods].each do |method|
52
52
  receiver_content << "# defined by `delegate` to: #{to_return_type}##{to_name}"
53
- receiver_content << "#{prefix}def #{method}: (*untyped, **untyped) -> untyped"
53
+ receiver_content << "#{prefix}def #{method}: (?) -> untyped"
54
54
  end
55
55
  else
56
56
  # found return type in store or env
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Orthoses
4
4
  module Rails
5
- VERSION = "1.8.1"
5
+ VERSION = "1.9.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orthoses-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-04 00:00:00.000000000 Z
10
+ date: 2025-04-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: orthoses
@@ -84,14 +84,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - ">="
86
86
  - !ruby/object:Gem::Version
87
- version: 2.6.0
87
+ version: 3.2.0
88
88
  required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  requirements:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
92
  version: '0'
93
93
  requirements: []
94
- rubygems_version: 3.6.2
94
+ rubygems_version: 3.6.6
95
95
  specification_version: 4
96
96
  summary: Orthoses middleware collection for Ruby on Rails
97
97
  test_files: []