orthoses-rails 1.2.0 → 1.3.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: d9681e80e9a106b8d984c304a0f26777deb5e2077aba6f8a0321f52976e24bcc
4
- data.tar.gz: c1f248d0e236bc72491e507da185317d55d607cebf4d6364209cd1601cacb6aa
3
+ metadata.gz: dc7b416eba2452375317a5c028aeae285d135ee8c8ef4129f28170f46d0090d9
4
+ data.tar.gz: 71148b9456d3038c6960611ac78e764590f8becd9376e1d136fb06549e80a378
5
5
  SHA512:
6
- metadata.gz: 8ff02244b5844c28186021d4379818a5a0b56ffcb693425f500e3145ff36da721a278c972a6a324e3b3b26bcb3ce9652c98f9fb3c15549fd51924371362d37fb
7
- data.tar.gz: 284d60f37efb290cf6e5230dd10cda55066278e89e4b81866896793c535b4864edc7cb13c389d0c98a861c34630fba09df3bb04b1035291f7c4cc46666d22b9b
6
+ metadata.gz: 6abe5dd4e76632c6039a20da11e44e63851713a4793e31661e246ce00d1de36ced9c0ecfe182efe2108df2e59c54e00cadf4d857eb1e7c447dd36d289de068b5
7
+ data.tar.gz: 6e1df2008c803ffa594d2fc96312ef9d97bda0570339604a40b47e8ff35c94118dd7ed2ca1cf77f7316cf3464ba7cbdc9ec438d182a4099983c0625ece69024c
@@ -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,55 @@
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
+ cast_type = capture.argument[:cast_type] || capture.argument[:type]
37
+
38
+ return_type = DEFAULT_TYPES[cast_type] || 'untyped'
39
+
40
+ generated_attribute_methods = "#{receiver_name}::ActiveModelGeneratedAttributeMethods"
41
+ c = store[generated_attribute_methods]
42
+ c.header = "module #{generated_attribute_methods}"
43
+ c << "def #{name}: () -> #{return_type}?"
44
+ c << "def #{name}=: (untyped) -> untyped"
45
+
46
+ unless store[receiver_name].body.include?("include #{generated_attribute_methods}")
47
+ store[receiver_name] << "include #{generated_attribute_methods}"
48
+ end
49
+ end
50
+
51
+ store
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'active_model/attributes'
3
4
  require_relative 'active_model/has_secure_password'
@@ -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
@@ -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|
@@ -17,6 +17,7 @@ module Orthoses
17
17
  def call
18
18
  loader = @loader
19
19
  Orthoses::Builder.new do
20
+ use Orthoses::ActiveModel::Attributes
20
21
  use Orthoses::ActiveModel::HasSecurePassword
21
22
 
22
23
  use Orthoses::ActiveRecord::BelongsTo
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Orthoses
4
4
  module Rails
5
- VERSION = "1.2.0"
5
+ VERSION = "1.3.0"
6
6
  end
7
7
  end
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.2.0
4
+ version: 1.3.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-09-02 00:00:00.000000000 Z
11
+ date: 2023-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: orthoses
@@ -38,6 +38,7 @@ files:
38
38
  - lib/generators/orthoses/rails/templates/rails.rake
39
39
  - lib/orthoses-rails.rb
40
40
  - lib/orthoses/active_model.rb
41
+ - lib/orthoses/active_model/attributes.rb
41
42
  - lib/orthoses/active_model/has_secure_password.rb
42
43
  - lib/orthoses/active_record.rb
43
44
  - lib/orthoses/active_record/belongs_to.rb