orthoses-rails 1.2.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/orthoses/rails/templates/rails.rake +7 -0
- data/lib/orthoses/action_mailer/base.rb +85 -0
- data/lib/orthoses/action_mailer.rb +3 -0
- data/lib/orthoses/active_model/attributes.rb +64 -0
- data/lib/orthoses/active_model.rb +1 -0
- data/lib/orthoses/active_record/enum.rb +23 -3
- data/lib/orthoses/active_record/generated_attribute_methods.rb +18 -5
- data/lib/orthoses/active_record/relation.rb +9 -0
- data/lib/orthoses/active_record/scope.rb +9 -1
- data/lib/orthoses/active_support/concern.rb +1 -1
- data/lib/orthoses/rails/application.rb +3 -0
- data/lib/orthoses/rails/version.rb +1 -1
- data/lib/orthoses/rails.rb +1 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9a2d180cb8faa295dc3043ea66a379ee71939436075104c0f85b63d6aede665
|
4
|
+
data.tar.gz: e02fa19ea12dfd296936673d67ecc6457b0e16101c18d4851747e0b895dace96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e97ed8964e301618db94df7c0d410310ea3bd9605f66c9d7d0431dc71546e0faaff24f918ce05a58510250f7563934a9adb3977662d3526db0198016801ba77
|
7
|
+
data.tar.gz: 5d43746f2bcb1ae068902a66a0da54a852bb173fcdd85ff5d9ce0f07e2051cbbc31e7b1a2c8e0469b28e2ca6ca1661edb76a1665e6d7a3356c6bedb9de97cf00
|
@@ -17,6 +17,13 @@ namespace :orthoses do
|
|
17
17
|
# Complement missing const name.
|
18
18
|
use Orthoses::MissingName
|
19
19
|
|
20
|
+
# You can use other publicly available middleware.
|
21
|
+
# `Orthoses::YARD` is available at https://github.com/ksss/orthoses-yard.
|
22
|
+
# By using this middleware, you can add the capability
|
23
|
+
# to generate type information from YARD documentation.
|
24
|
+
# use Orthoses::YARD,
|
25
|
+
# parse: ['{app/lib}/**/*.rb']
|
26
|
+
|
20
27
|
# You can load hand written RBS.
|
21
28
|
# use Orthoses::LoadRBS,
|
22
29
|
# paths: Dir.glob(Rails.root / "sig/hand-written/**/*.rbs")
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
module ActionMailer
|
5
|
+
class Base
|
6
|
+
def initialize(loader)
|
7
|
+
@loader = loader
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
@loader.call.tap do |store|
|
12
|
+
::ActionMailer::Base.descendants.each do |mailer_class|
|
13
|
+
base_name = Utils.module_name(mailer_class) or next
|
14
|
+
content = store[base_name]
|
15
|
+
mailer_class.action_methods.each do |action_method|
|
16
|
+
method_object = mailer_class.instance_method(action_method)
|
17
|
+
parameters = method_parameters_to_rbs_method_type(method_object).to_s.gsub(' -> untyped', '')
|
18
|
+
content << "def self.#{action_method}: #{parameters} -> ::ActionMailer::MessageDelivery"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def method_parameters_to_rbs_method_type(method_object)
|
27
|
+
required_positionals = []
|
28
|
+
optional_positionals = []
|
29
|
+
rest_positionals = nil
|
30
|
+
trailing_positionals = []
|
31
|
+
required_keywords = {}
|
32
|
+
optional_keywords = {}
|
33
|
+
rest_keywords = nil
|
34
|
+
requireds = required_positionals
|
35
|
+
block = nil
|
36
|
+
untyped = RBS::Types::Bases::Any.new(location: nil)
|
37
|
+
|
38
|
+
method_object.parameters.each do |kind, name|
|
39
|
+
case kind
|
40
|
+
when :req
|
41
|
+
requireds << ::RBS::Types::Function::Param.new(name: name, type: untyped)
|
42
|
+
when :opt
|
43
|
+
requireds = trailing_positionals
|
44
|
+
optional_positionals << ::RBS::Types::Function::Param.new(name: name, type: untyped)
|
45
|
+
when :rest
|
46
|
+
requireds = trailing_positionals
|
47
|
+
name = nil if name == :*
|
48
|
+
rest_positionals = ::RBS::Types::Function::Param.new(name: name, type: untyped)
|
49
|
+
when :keyreq
|
50
|
+
required_keywords[name] = ::RBS::Types::Function::Param.new(name: nil, type: untyped)
|
51
|
+
when :key
|
52
|
+
optional_keywords[name] = ::RBS::Types::Function::Param.new(name: nil, type: untyped)
|
53
|
+
when :keyrest
|
54
|
+
rest_keywords = ::RBS::Types::Function::Param.new(name: name, type: untyped)
|
55
|
+
when :block
|
56
|
+
block = RBS::Types::Block.new(
|
57
|
+
type: RBS::Types::Function.empty(untyped).update(rest_positionals: RBS::Types::Function::Param.new(name: nil, type: untyped)),
|
58
|
+
required: true,
|
59
|
+
self_type: nil
|
60
|
+
)
|
61
|
+
else
|
62
|
+
raise "bug"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
function = ::RBS::Types::Function.new(
|
67
|
+
required_positionals: required_positionals,
|
68
|
+
optional_positionals: optional_positionals,
|
69
|
+
rest_positionals: rest_positionals,
|
70
|
+
trailing_positionals: trailing_positionals,
|
71
|
+
required_keywords: required_keywords,
|
72
|
+
optional_keywords: optional_keywords,
|
73
|
+
rest_keywords: rest_keywords,
|
74
|
+
return_type: untyped,
|
75
|
+
)
|
76
|
+
::RBS::MethodType.new(
|
77
|
+
location: nil,
|
78
|
+
type_params: [],
|
79
|
+
type: function,
|
80
|
+
block: block
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
module ActiveModel
|
5
|
+
# < 7.0
|
6
|
+
# def attribute(name, type = Type::Value.new, **options)
|
7
|
+
# >= 7.0
|
8
|
+
# def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
|
9
|
+
class Attributes
|
10
|
+
DEFAULT_TYPES = {
|
11
|
+
big_integer: '::Integer',
|
12
|
+
binary: '::String',
|
13
|
+
boolean: 'bool',
|
14
|
+
date: '::Date',
|
15
|
+
datetime: '::Time',
|
16
|
+
decimal: '::BigDecimal',
|
17
|
+
float: '::Float',
|
18
|
+
immutable_string: '::String',
|
19
|
+
integer: '::Integer',
|
20
|
+
string: '::String',
|
21
|
+
time: '::Time'
|
22
|
+
}
|
23
|
+
|
24
|
+
def initialize(loader)
|
25
|
+
@loader = loader
|
26
|
+
end
|
27
|
+
|
28
|
+
def call
|
29
|
+
attribute = CallTracer::Lazy.new
|
30
|
+
store = attribute.trace('ActiveModel::Attributes::ClassMethods#attribute') do
|
31
|
+
@loader.call
|
32
|
+
end
|
33
|
+
attribute.captures.each do |capture|
|
34
|
+
receiver_name = Utils.module_name(capture.method.receiver) or next
|
35
|
+
name = capture.argument[:name]
|
36
|
+
active_model_version = Gem::Version.new(::ActiveModel::VERSION::STRING)
|
37
|
+
cast_type =
|
38
|
+
if active_model_version >= Gem::Version.new('7.1')
|
39
|
+
# https://github.com/rails/rails/commit/608cbfae36b125d7962b7ed9083c9e9e6ce70b88
|
40
|
+
capture.argument[:*].first
|
41
|
+
elsif active_model_version >= Gem::Version.new('7.0')
|
42
|
+
capture.argument[:cast_type]
|
43
|
+
else
|
44
|
+
capture.argument[:type]
|
45
|
+
end
|
46
|
+
|
47
|
+
return_type = DEFAULT_TYPES[cast_type] || 'untyped'
|
48
|
+
|
49
|
+
generated_attribute_methods = "#{receiver_name}::ActiveModelGeneratedAttributeMethods"
|
50
|
+
c = store[generated_attribute_methods]
|
51
|
+
c.header = "module #{generated_attribute_methods}"
|
52
|
+
c << "def #{name}: () -> #{return_type}?"
|
53
|
+
c << "def #{name}=: (untyped) -> untyped"
|
54
|
+
|
55
|
+
unless store[receiver_name].body.include?("include #{generated_attribute_methods}")
|
56
|
+
store[receiver_name] << "include #{generated_attribute_methods}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
store
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -67,15 +67,35 @@ module Orthoses
|
|
67
67
|
|
68
68
|
return_type_param = Hash === values ? "[String, String]" : "[String, Integer]"
|
69
69
|
store[base_name] << "def self.#{name.pluralize}: () -> ActiveSupport::HashWithIndifferentAccess#{return_type_param}"
|
70
|
+
enum_methods_content = store["#{base_name}::ActiveRecord_Enum_EnumMethods"]
|
71
|
+
enum_methods_content.header = "module #{base_name}::ActiveRecord_Enum_EnumMethods"
|
70
72
|
|
71
|
-
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
|
73
|
+
pairs = (values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index).to_h
|
72
74
|
pairs.each do |label, value|
|
73
75
|
value_method_name = "#{prefix}#{label}#{suffix}"
|
74
|
-
enum_methods_content = store["#{base_name}::ActiveRecord_Enum_EnumMethods"]
|
75
|
-
enum_methods_content.header = "module #{base_name}::ActiveRecord_Enum_EnumMethods"
|
76
76
|
enum_methods_content << "def #{value_method_name}?: () -> bool"
|
77
77
|
enum_methods_content << "def #{value_method_name}!: () -> bool"
|
78
|
+
|
79
|
+
value_method_alias = "#{prefix}#{label.to_s.gsub(/[\W&&[:ascii:]]+/, "_")}#{suffix}"
|
80
|
+
if value_method_alias != value_method_name
|
81
|
+
enum_methods_content << "def #{value_method_alias}?: () -> bool"
|
82
|
+
enum_methods_content << "def #{value_method_alias}!: () -> bool"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Expressing type casting.
|
87
|
+
store[base_name] << "def #{name}: () -> (#{pairs.keys.map { |k| "\"#{k}\"" }.join(" | ")})"
|
88
|
+
symbol_pattern = if pairs.keys.any? { |key| key.match?(/[^a-zA-Z_]/) }
|
89
|
+
"(Symbol) -> void"
|
90
|
+
else
|
91
|
+
"(#{pairs.keys.map{|key|key.to_sym.inspect}.join(" | ")}) -> void"
|
78
92
|
end
|
93
|
+
overloads = [
|
94
|
+
symbol_pattern,
|
95
|
+
"(#{pairs.keys.map{|key|key.to_s.inspect}.join(" | ")}) -> void",
|
96
|
+
"(#{pairs.values.map(&:inspect).join(" | ")}) -> void",
|
97
|
+
]
|
98
|
+
store[base_name] << "def #{name}=: #{overloads.join(" | ")}"
|
79
99
|
end
|
80
100
|
end
|
81
101
|
end
|
@@ -4,8 +4,6 @@ module Orthoses
|
|
4
4
|
module ActiveRecord
|
5
5
|
class GeneratedAttributeMethods
|
6
6
|
TARGET_TYPE_MAP = {
|
7
|
-
"attribute" => "() -> %<type>s",
|
8
|
-
"attribute=" => "(%<type>s) -> %<type>s",
|
9
7
|
"attribute?" => "() -> bool",
|
10
8
|
"attribute_before_last_save" => "() -> %<opt>s",
|
11
9
|
"attribute_before_type_cast" => "() -> %<type>s",
|
@@ -50,13 +48,14 @@ module Orthoses
|
|
50
48
|
opt = "#{req}?"
|
51
49
|
type = col.null ? opt : req
|
52
50
|
|
53
|
-
|
54
|
-
|
51
|
+
lines << "attr_accessor #{name}: #{type}"
|
52
|
+
attribute_method_patterns(::ActiveRecord::Base).each do |matcher|
|
53
|
+
tmpl = TARGET_TYPE_MAP[matcher.proxy_target] or next
|
55
54
|
lines << "def #{matcher.method_name(name)}: #{tmpl % {type: type, opt: opt}}"
|
56
55
|
end
|
57
56
|
end
|
58
57
|
klass.attribute_aliases.each do |alias_name, column_name|
|
59
|
-
::ActiveRecord::Base.
|
58
|
+
attribute_method_patterns(::ActiveRecord::Base).each do |matcher|
|
60
59
|
lines << "alias #{matcher.method_name(alias_name)} #{matcher.method_name(column_name)}"
|
61
60
|
end
|
62
61
|
end
|
@@ -69,6 +68,20 @@ module Orthoses
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def attribute_method_patterns(const)
|
75
|
+
if const.respond_to?(:attribute_method_patterns)
|
76
|
+
const.attribute_method_patterns
|
77
|
+
else
|
78
|
+
const.attribute_method_matchers.each do |matcher|
|
79
|
+
def matcher.proxy_target
|
80
|
+
target
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
@@ -19,7 +19,16 @@ module Orthoses
|
|
19
19
|
class_specific_proxy = "#{model_name}::ActiveRecord_Associations_CollectionProxy"
|
20
20
|
class_specific_generated_relation_methods = "#{model_name}::GeneratedRelationMethods"
|
21
21
|
|
22
|
+
# Expressing delegation.
|
22
23
|
store[class_specific_generated_relation_methods].tap do |c|
|
24
|
+
klass.singleton_methods(false).each do |singleton_method|
|
25
|
+
c << "def #{singleton_method}: (*untyped, **untyped) -> untyped"
|
26
|
+
end
|
27
|
+
(klass.singleton_class.included_modules - ::ActiveRecord::Relation.included_modules).each do |mod|
|
28
|
+
mname = Utils.module_name(mod) or next
|
29
|
+
store[mname].header = "module #{mname}"
|
30
|
+
c << "include #{mname}"
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
store[class_specific_relation].tap do |c|
|
@@ -20,7 +20,7 @@ module Orthoses
|
|
20
20
|
name = capture.argument[:name]
|
21
21
|
body = capture.argument[:body]
|
22
22
|
|
23
|
-
definition = "#{name}: #{parameters_to_type(body
|
23
|
+
definition = "#{name}: #{parameters_to_type(parameters(body))} -> #{base_name}::ActiveRecord_Relation"
|
24
24
|
store[base_name] << "def self.#{definition}"
|
25
25
|
store["#{base_name}::GeneratedRelationMethods"].header = "module #{base_name}::GeneratedRelationMethods"
|
26
26
|
store["#{base_name}::GeneratedRelationMethods"] << "def #{definition}"
|
@@ -58,6 +58,14 @@ module Orthoses
|
|
58
58
|
end
|
59
59
|
"(#{res.join(", ")})#{block}"
|
60
60
|
end
|
61
|
+
|
62
|
+
def parameters(body)
|
63
|
+
if body.respond_to?(:to_proc)
|
64
|
+
body.to_proc.parameters
|
65
|
+
else
|
66
|
+
body.method(:call).parameters
|
67
|
+
end
|
68
|
+
end
|
61
69
|
end
|
62
70
|
end
|
63
71
|
end
|
@@ -36,7 +36,7 @@ module Orthoses
|
|
36
36
|
def members_prototype_of(mod_name)
|
37
37
|
mod = Object.const_get(mod_name)
|
38
38
|
runtime = ::RBS::Prototype::Runtime.new(patterns: nil, env: nil, merge: false)
|
39
|
-
type_name =
|
39
|
+
type_name = TypeName(mod_name)
|
40
40
|
[].tap do |members|
|
41
41
|
runtime.generate_methods(mod, type_name, members)
|
42
42
|
end
|
data/lib/orthoses/rails.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orthoses-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ksss
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: orthoses
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.13'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.13'
|
27
27
|
description: Orthoses middleware collection for Ruby on Rails
|
28
28
|
email:
|
29
29
|
- co000ri@gmail.com
|
@@ -37,7 +37,10 @@ files:
|
|
37
37
|
- lib/generators/orthoses/rails/install_generator.rb
|
38
38
|
- lib/generators/orthoses/rails/templates/rails.rake
|
39
39
|
- lib/orthoses-rails.rb
|
40
|
+
- lib/orthoses/action_mailer.rb
|
41
|
+
- lib/orthoses/action_mailer/base.rb
|
40
42
|
- lib/orthoses/active_model.rb
|
43
|
+
- lib/orthoses/active_model/attributes.rb
|
41
44
|
- lib/orthoses/active_model/has_secure_password.rb
|
42
45
|
- lib/orthoses/active_record.rb
|
43
46
|
- lib/orthoses/active_record/belongs_to.rb
|