sorbet-rails 0.7.3 → 0.7.4

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.
@@ -0,0 +1,137 @@
1
+ # typed: false
2
+ class AttrJsonPlugin < SorbetRails::ModelPlugins::Base
3
+ sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
4
+ def generate(root)
5
+ return unless @model_class.include?(::AttrJson::Record)
6
+
7
+ # Module for instance methods
8
+ obj_custom_module_name = self.model_module_name("GeneratedAttrJsonMethods")
9
+ obj_custom_module_rbi = root.create_module(obj_custom_module_name)
10
+
11
+ # Module for class methods
12
+ klass_custom_module_name = self.model_module_name("GeneratedAttrJsonClassMethods")
13
+ klass_custom_module_rbi = root.create_module(klass_custom_module_name)
14
+
15
+ # here we re-create the model class!
16
+ model_class_rbi = root.create_class(self.model_class_name)
17
+ model_class_rbi.create_include(obj_custom_module_name)
18
+ model_class_rbi.create_extend(klass_custom_module_name)
19
+
20
+ # then create custom methods, constants, etc. for this module.
21
+ add_class_methods(klass_custom_module_rbi)
22
+
23
+ @model_class.attr_json_registry.definitions.each do |definition|
24
+ add_methods_for_attributes(definition, obj_custom_module_rbi)
25
+ end
26
+
27
+ if @model_class.include?(::AttrJson::Record::Dirty)
28
+ obj_custom_module_rbi.create_method(
29
+ 'attr_json_changes',
30
+ returns: 'AttrJson::Record::Dirty::Implementation'
31
+ )
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ sig { params(custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
38
+ def add_class_methods(custom_module_rbi)
39
+ custom_module_rbi.create_method(
40
+ 'attr_json_config',
41
+ parameters: [
42
+ ::Parlour::RbiGenerator::Parameter.new(
43
+ 'new_values',
44
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
45
+ )
46
+ ],
47
+ returns: 'T::Hash[Symbol, T.untyped]'
48
+ )
49
+
50
+ custom_module_rbi.create_method(
51
+ 'attr_json',
52
+ parameters: [
53
+ ::Parlour::RbiGenerator::Parameter.new(
54
+ 'name',
55
+ type: 'T.any(Symbol, String)'
56
+ ),
57
+ ::Parlour::RbiGenerator::Parameter.new(
58
+ 'type',
59
+ type: 'T.any(Symbol, ActiveModel::Type::Value)'
60
+ ),
61
+ ::Parlour::RbiGenerator::Parameter.new(
62
+ '**options',
63
+ type: 'T.untyped'
64
+ )
65
+ ]
66
+ )
67
+ end
68
+
69
+ sig do
70
+ params(
71
+ definition: ::AttrJson::AttributeDefinition,
72
+ custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace
73
+ )
74
+ .void
75
+ end
76
+ def add_methods_for_attributes(definition, custom_module_rbi)
77
+ # set methods can receive an argument of any type because attr_json will try
78
+ # to parse to the correct type. Example:
79
+ #
80
+ # class Post < ApplicationRecord
81
+ # ...
82
+ # attr_json :my_datetime, :datetime
83
+ # end
84
+ #
85
+ # > p = Post.new
86
+ # > (p.my_datetime = '2020-02-02').class
87
+ # => String
88
+ # > p.my_datetime.class
89
+ # => Time
90
+ #
91
+ # Also, the setter type return is the same as its argument type (before parse).
92
+ custom_module_rbi.create_method(
93
+ "#{definition.name}=",
94
+ parameters: [
95
+ ::Parlour::RbiGenerator::Parameter.new(
96
+ 'value',
97
+ type: 'T.untyped'
98
+ )
99
+ ],
100
+ returns: 'T.untyped'
101
+ )
102
+
103
+ definition_type = get_definition_type(definition)
104
+
105
+ custom_module_rbi.create_method(
106
+ definition.name.to_s,
107
+ returns: definition_type
108
+ )
109
+
110
+ custom_module_rbi.create_method(
111
+ "#{definition.name}?",
112
+ returns: 'T::Boolean'
113
+ )
114
+ end
115
+
116
+ sig { params(definition: ::AttrJson::AttributeDefinition).returns(String) }
117
+ def get_definition_type(definition)
118
+
119
+ if definition.array_type?
120
+ "T::Array[#{type_to_class(definition.type.base_type.type.to_s)}]"
121
+ else
122
+ "T.nilable(#{type_to_class(definition.type.type.to_s)})"
123
+ end
124
+ end
125
+
126
+ sig { params(type: String).returns(String) }
127
+ def type_to_class(type)
128
+ return 'T.untyped' unless type.present?
129
+
130
+ case type
131
+ when 'datetime' then 'Time'
132
+ when 'decimal' then 'BigDecimal'
133
+ when 'boolean' then 'T::Boolean'
134
+ else type.camelize
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,201 @@
1
+ # typed: false
2
+ class FlagShihTzuPlugin < SorbetRails::ModelPlugins::Base
3
+ sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
4
+ def generate(root)
5
+ return unless @model_class.include?(::FlagShihTzu)
6
+
7
+ obj_custom_module_name = self.model_module_name("GeneratedFlagShihTzuMethods")
8
+ obj_custom_module_rbi = root.create_module(obj_custom_module_name)
9
+
10
+ klass_custom_module_name = self.model_module_name("GeneratedFlagShihTzuClassMethods")
11
+ klass_custom_module_rbi = root.create_module(klass_custom_module_name)
12
+
13
+
14
+ # here we re-create the model class!
15
+ model_class_rbi = root.create_class(self.model_class_name)
16
+ model_class_rbi.create_include(obj_custom_module_name)
17
+ model_class_rbi.create_extend(klass_custom_module_name)
18
+
19
+ # then create custom methods, constants, etc. for this module.
20
+ add_class_methods(klass_custom_module_rbi)
21
+
22
+ if @model_class.flag_columns.present?
23
+ @model_class
24
+ .flag_columns
25
+ .each do |column|
26
+ add_methods_for_column(column, obj_custom_module_rbi)
27
+ end
28
+ end
29
+
30
+ if @model_class.flag_mapping.present?
31
+ @model_class
32
+ .flag_mapping
33
+ .each do |column, flags|
34
+ flags.keys
35
+ .select { |flag_key| really_has_the_flag?(flag_key) }
36
+ .each do |flag_key|
37
+ add_methods_for_flag(column, flag_key, obj_custom_module_rbi)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ sig { params(custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
46
+ def add_class_methods(custom_module_rbi)
47
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L12
48
+ custom_module_rbi.create_method(
49
+ 'flag_options',
50
+ returns: 'T::Hash[String, T::Hash[Symbol, T.untyped]]'
51
+ )
52
+
53
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L13
54
+ custom_module_rbi.create_method(
55
+ 'flag_mapping',
56
+ returns: 'T::Hash[String, T::Hash[Symbol, Integer]]'
57
+ )
58
+
59
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L14
60
+ custom_module_rbi.create_method(
61
+ 'flag_columns',
62
+ returns: 'T::Array[Symbol]'
63
+ )
64
+
65
+ # https://github.com/pboling/flag_shih_tzu#updating-flag-column-by-raw-sql
66
+ custom_module_rbi.create_method(
67
+ 'set_flag_sql',
68
+ parameters: [
69
+ ::Parlour::RbiGenerator::Parameter.new(
70
+ 'flag',
71
+ type: 'Symbol'
72
+ ),
73
+ ::Parlour::RbiGenerator::Parameter.new(
74
+ 'value',
75
+ type: 'T::Boolean'
76
+ ),
77
+ ::Parlour::RbiGenerator::Parameter.new(
78
+ 'colmn',
79
+ type: 'T.nilable(String)'
80
+ ),
81
+ ::Parlour::RbiGenerator::Parameter.new(
82
+ 'custom_table_name',
83
+ type: 'T.any(String, Symbol)'
84
+ )
85
+ ],
86
+ returns: 'T::Hash[String, T::Hash[Symbol, T.untyped]]'
87
+ )
88
+
89
+ if @model_class.flag_mapping.present?
90
+ # https://github.com/pboling/flag_shih_tzu#support-for-manually-building-conditions
91
+ @model_class
92
+ .flag_mapping
93
+ .flat_map { |_, flags| flags.keys }
94
+ .each do |flag_key|
95
+ next unless really_has_the_flag?(flag_key)
96
+
97
+ custom_module_rbi.create_method(
98
+ "#{flag_key}_condition",
99
+ parameters: [
100
+ ::Parlour::RbiGenerator::Parameter.new(
101
+ 'options',
102
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
103
+ )
104
+ ],
105
+ returns: 'String'
106
+ )
107
+
108
+ custom_module_rbi.create_method(
109
+ "not_#{flag_key}_condition",
110
+ parameters: [
111
+ ::Parlour::RbiGenerator::Parameter.new(
112
+ 'options',
113
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
114
+ )
115
+ ],
116
+ returns: 'String'
117
+ )
118
+ end
119
+ end
120
+ end
121
+
122
+ # https://github.com/pboling/flag_shih_tzu#generated-boolean-patterned-instance-methods
123
+ sig { params(column: String, custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
124
+ def add_methods_for_column(column, custom_module_rbi)
125
+ custom_module_rbi.create_method(
126
+ "all_#{column}",
127
+ returns: 'T::Array[Symbol]'
128
+ )
129
+
130
+ custom_module_rbi.create_method(
131
+ "selected_#{column}",
132
+ returns: 'T::Array[Symbol]'
133
+ )
134
+
135
+ custom_module_rbi.create_method(
136
+ "select_all_#{column}",
137
+ returns: 'T::Array[Symbol]'
138
+ )
139
+
140
+ custom_module_rbi.create_method(
141
+ "unselect_all_#{column}",
142
+ returns: 'T::Array[Symbol]'
143
+ )
144
+
145
+ custom_module_rbi.create_method(
146
+ "selected_#{column}=",
147
+ parameters: [
148
+ ::Parlour::RbiGenerator::Parameter.new(
149
+ 'chosen_flags',
150
+ type: 'T.nilable(T::Array[Symbol])'
151
+ )
152
+ ],
153
+ returns: 'T::Array[Symbol]'
154
+ )
155
+
156
+ end
157
+
158
+ # https://github.com/pboling/flag_shih_tzu#generated-boolean-patterned-instance-methods
159
+ sig { params(column: String, flag_key: Symbol, custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
160
+ def add_methods_for_flag(column, flag_key, custom_module_rbi)
161
+ custom_module_rbi.create_method(flag_key.to_s, returns: 'T::Boolean')
162
+ custom_module_rbi.create_method("#{flag_key}?", returns: 'T::Boolean')
163
+ custom_module_rbi.create_method(
164
+ "#{flag_key}=",
165
+ parameters: [
166
+ ::Parlour::RbiGenerator::Parameter.new(
167
+ 'value',
168
+ type: 'T::Boolean'
169
+ )
170
+ ],
171
+ returns: 'T::Boolean'
172
+ )
173
+
174
+ custom_module_rbi.create_method("not_#{flag_key}", returns: 'T::Boolean')
175
+ custom_module_rbi.create_method("not_#{flag_key}?", returns: 'T::Boolean')
176
+ custom_module_rbi.create_method(
177
+ "not_#{flag_key}=",
178
+ parameters: [
179
+ ::Parlour::RbiGenerator::Parameter.new(
180
+ 'value',
181
+ type: 'T::Boolean'
182
+ )
183
+ ],
184
+ returns: 'T::Boolean'
185
+ )
186
+
187
+ custom_module_rbi.create_method("#{flag_key}_changed?", returns: 'T::Boolean')
188
+
189
+ custom_module_rbi.create_method("has_#{flag_key}?", returns: 'T::Boolean')
190
+
191
+ if @model_class.flag_options[column][:bang_methods]
192
+ custom_module_rbi.create_method("#{flag_key}!", returns: 'T::Boolean')
193
+ custom_module_rbi.create_method("not_#{flag_key}!", returns: 'T::Boolean')
194
+ end
195
+ end
196
+
197
+ sig { params(flag_name: Symbol).returns(T::Boolean) }
198
+ def really_has_the_flag?(flag_name)
199
+ @model_class.respond_to?("#{flag_name}_condition")
200
+ end
201
+ end
@@ -43,5 +43,25 @@ class KaminariPlugin < SorbetRails::ModelPlugins::Base
43
43
  return_type: "Integer",
44
44
  class_method: true,
45
45
  )
46
+
47
+ # https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-core/lib/kaminari/models/page_scope_methods.rb#L82
48
+ model_relation_rbi = root.create_class(self.model_relation_class_name)
49
+ model_relation_rbi.create_method(
50
+ 'last_page?',
51
+ parameters: nil,
52
+ return_type: 'T::Boolean',
53
+ )
54
+ model_assoc_relation_rbi = root.create_class(self.model_assoc_relation_class_name)
55
+ model_assoc_relation_rbi.create_method(
56
+ 'last_page?',
57
+ parameters: nil,
58
+ return_type: 'T::Boolean',
59
+ )
60
+ collection_proxy_rbi = root.create_class(self.model_assoc_proxy_class_name)
61
+ collection_proxy_rbi.create_method(
62
+ 'last_page?',
63
+ parameters: nil,
64
+ return_type: 'T::Boolean',
65
+ )
46
66
  end
47
67
  end
@@ -45,7 +45,7 @@ class ShrinePlugin < SorbetRails::ModelPlugins::Base
45
45
  parameters: [
46
46
  ::Parlour::RbiGenerator::Parameter.new(
47
47
  "url",
48
- type: T.untyped # TODO likely T.nilable(String)
48
+ type: "T.untyped" # TODO likely T.nilable(String)
49
49
  ),
50
50
  ],
51
51
  )
@@ -81,6 +81,12 @@ module SorbetRails::ModelPlugins
81
81
  when :paperclip
82
82
  require('sorbet-rails/gem_plugins/paperclip_plugin')
83
83
  PaperclipPlugin
84
+ when :attr_json
85
+ require('sorbet-rails/gem_plugins/attr_json_plugin')
86
+ AttrJsonPlugin
87
+ when :flag_shih_tzu
88
+ require('sorbet-rails/gem_plugins/flag_shih_tzu_plugin')
89
+ FlagShihTzuPlugin
84
90
  else
85
91
  raise UnrecognizedPluginName.new(
86
92
  "Unrecognized plugin with name: #{plugin_name}. Please check available plugins in the
data/sorbet-rails.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{sorbet-rails}
3
- s.version = "0.7.3"
3
+ s.version = "0.7.4"
4
4
  s.date = %q{2019-04-18}
5
5
  s.summary = %q{Set of tools to make Sorbet work with Rails seamlessly.}
6
6
  s.authors = ["Chan Zuckerberg Initiative"]
data/spec/rails_helper.rb CHANGED
@@ -36,7 +36,6 @@ RSpec.configure do |config|
36
36
  next if ENV["DISABLE_DATABASE_CLEANER"] == 'true'
37
37
  DatabaseCleaner.clean_with(:truncation, {
38
38
  pre_count: true,
39
- reset_ids: false,
40
39
  except: %w(ar_internal_metadata),
41
40
  })
42
41
  end
@@ -46,10 +45,7 @@ RSpec.configure do |config|
46
45
  example.run
47
46
  next
48
47
  end
49
- DatabaseCleaner.strategy = :truncation, {
50
- pre_count: true,
51
- reset_ids: false,
52
- }
48
+ DatabaseCleaner.strategy = :truncation, { pre_count: true }
53
49
  DatabaseCleaner.start
54
50
  example.run
55
51
  DatabaseCleaner.clean
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../../..
3
3
  specs:
4
- sorbet-rails (0.7.3)
4
+ sorbet-rails (0.7.4)
5
5
  method_source (>= 0.9.2)
6
6
  parlour (>= 4.0.1)
7
7
  parser (>= 2.7)
@@ -49,10 +49,10 @@ GEM
49
49
  minitest (~> 5.1)
50
50
  tzinfo (~> 1.1)
51
51
  arel (7.1.4)
52
- ast (2.4.1)
52
+ ast (2.4.2)
53
53
  builder (3.2.4)
54
54
  byebug (11.1.1)
55
- commander (4.5.2)
55
+ commander (4.6.0)
56
56
  highline (~> 2.0.0)
57
57
  concurrent-ruby (1.1.6)
58
58
  crass (1.0.6)
@@ -71,20 +71,24 @@ GEM
71
71
  mini_mime (>= 0.1.1)
72
72
  method_source (1.0.0)
73
73
  mini_mime (1.0.2)
74
- mini_portile2 (2.4.0)
74
+ mini_portile2 (2.5.0)
75
75
  minitest (5.14.0)
76
76
  nio4r (2.5.2)
77
- nokogiri (1.10.9)
78
- mini_portile2 (~> 2.4.0)
79
- parlour (5.0.0)
77
+ nokogiri (1.11.1)
78
+ mini_portile2 (~> 2.5.0)
79
+ racc (~> 1.4)
80
+ nokogiri (1.11.1-x86_64-darwin)
81
+ racc (~> 1.4)
82
+ parlour (6.0.0)
80
83
  commander (~> 4.5)
81
84
  parser
82
85
  rainbow (~> 3.0)
83
86
  sorbet-runtime (>= 0.5)
84
- parser (3.0.0.0)
87
+ parser (3.0.1.1)
85
88
  ast (~> 2.4.1)
86
89
  polyfill (1.9.0)
87
90
  puma (3.12.6)
91
+ racc (1.5.2)
88
92
  rack (2.2.3)
89
93
  rack-test (0.6.3)
90
94
  rack (>= 1.0)
@@ -116,10 +120,9 @@ GEM
116
120
  safe_type (1.1.1)
117
121
  sorbet (0.5.5480)
118
122
  sorbet-static (= 0.5.5480)
119
- sorbet-coerce (0.3.0)
123
+ sorbet-coerce (0.4.0)
120
124
  polyfill (~> 1.8)
121
125
  safe_type (~> 1.1, >= 1.1.1)
122
- sorbet (>= 0.4.4704)
123
126
  sorbet-runtime (>= 0.4.4704)
124
127
  sorbet-runtime (0.5.5480)
125
128
  sorbet-static (0.5.5480-universal-darwin-19)