orthoses-rails 1.1.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: ec337b1da4ecda39f953797824239ede59c536c74da48cc1dbd01e46eed1d2b0
4
- data.tar.gz: b146481d3fda9b3568a1593fd05608f09c811e1181356f2e36d2b010c30dd130
3
+ metadata.gz: dc7b416eba2452375317a5c028aeae285d135ee8c8ef4129f28170f46d0090d9
4
+ data.tar.gz: 71148b9456d3038c6960611ac78e764590f8becd9376e1d136fb06549e80a378
5
5
  SHA512:
6
- metadata.gz: 2bec23dc332048a010d10a2dc01754b969f76d2dd19bfa4b50393c1a764b3de496a35d018560aca04fe43630de497e900bb580774698bda3073ea33dcbf44bb5
7
- data.tar.gz: e2dac22ee12a3bf049a73e5609d4a3ca1693c2dbc851c3bb06256e4566e9adad6c991fa9a60b0aaa7b22d6ea19e0c7cbc65c403cd136669d4c98b58deb7d90e7
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'
@@ -18,15 +18,7 @@ module Orthoses
18
18
  type = if ref.polymorphic?
19
19
  'untyped'
20
20
  else
21
- begin
22
- Utils.module_name(ref.klass) or next
23
- rescue NameError => e
24
- while e
25
- Orthoses.logger.warn(e.message)
26
- e = e.cause
27
- end
28
- next
29
- end
21
+ Orthoses::ActiveRecord.reflection_klass_name(ref) or next
30
22
  end
31
23
  opt = "#{type}?"
32
24
 
@@ -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
@@ -15,16 +15,7 @@ module Orthoses
15
15
 
16
16
  lines = base.reflect_on_all_associations(:has_many).flat_map do |ref|
17
17
  singular_name = ref.name.to_s.singularize
18
- type =
19
- begin
20
- Utils.module_name(ref.klass)
21
- rescue NameError => e
22
- while e
23
- Orthoses.logger.warn(e.message)
24
- e = e.cause
25
- end
26
- next
27
- end
18
+ type = Orthoses::ActiveRecord.reflection_klass_name(ref) or next
28
19
 
29
20
  collection_proxy = "::#{type}::ActiveRecord_Associations_CollectionProxy"
30
21
  [
@@ -14,16 +14,7 @@ module Orthoses
14
14
  base_name = Utils.module_name(base) || next
15
15
 
16
16
  lines = base.reflect_on_all_associations(:has_one).flat_map do |ref|
17
- type =
18
- begin
19
- Utils.module_name(ref.klass) or next
20
- rescue NameError => e
21
- while e
22
- Orthoses.logger.warn(e.message)
23
- e = e.cause
24
- end
25
- next
26
- end
17
+ type = Orthoses::ActiveRecord.reflection_klass_name(ref) or next
27
18
  opt = "#{type}?"
28
19
 
29
20
  [
@@ -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|
@@ -43,5 +43,16 @@ module Orthoses
43
43
  'untyped'
44
44
  end
45
45
  end
46
+
47
+ def self.reflection_klass_name(ref)
48
+ Utils.module_name(ref.klass)
49
+ rescue NameError, ArgumentError => e
50
+ while e
51
+ Orthoses.logger.warn(e.message)
52
+ e = e.cause
53
+ end
54
+
55
+ nil
56
+ end
46
57
  end
47
58
  end
@@ -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.1.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.1.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-08-30 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
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '1.11'
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.10'
26
+ version: '1.11'
27
27
  description: Orthoses middleware collection for Ruby on Rails
28
28
  email:
29
29
  - co000ri@gmail.com
@@ -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