sorbet-rails 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)