momocop 0.1.4 → 0.1.6

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: d7bbeea4b66a57e0dd2768cd593c653501cc745e73439d254dfa6ff56d26ad7a
4
- data.tar.gz: 3181561d6c590050106bcf13a1c6b6cec2f22179e2b1c8bcbb5b126630fd27d5
3
+ metadata.gz: 583e60d7747c3d18b2e39a5fe6d2f4cb4a02d9484ee21d49c3b6e06381c7db1a
4
+ data.tar.gz: 72139ae77375a441a56925c906be69d34993c867a3a23337dde3f7e47e257b31
5
5
  SHA512:
6
- metadata.gz: 19113cb5c6945b125d1688553deb24933b111ebe9d43521212fad4b38ca495676635c3047250e07a8a4b784c68f4d9b51a76ae8b0f56a167f5dc60d60939a78d
7
- data.tar.gz: c9841b2375bdd3e81682e73da8dd42f45174de77c27c265b10e7a7f7750bd8424c804bb2bea1e3f02f287d52926cd4895670988dac7d19f6d3b5d72c6a3a7314
6
+ metadata.gz: e0fb80f1fa23509e2ace6883efd371d3aeffac8f8472f484b8e797ba2ce1347518e2b124da72116fffe86ad82610a1d7e9af557da0cc04666bc214e4228d7248
7
+ data.tar.gz: 125d23305c4a085e35a0f3785f5b5f3f6cb00c4cfbeb44063e838ea5138b755e3d8b183a813c2776ddd56bf566cf682081bde359fc4e5c713d28459494b124e1
data/.rubocop.yml CHANGED
@@ -41,6 +41,10 @@ Security:
41
41
  Style:
42
42
  Enabled: true
43
43
 
44
+ Style/BlockDelimiters:
45
+ EnforcedStyle: semantic
46
+ AllowBracesOnProceduralOneLiners: false
47
+
44
48
  Style/Documentation:
45
49
  Enabled: false
46
50
 
@@ -49,6 +53,9 @@ Style/FrozenStringLiteralComment:
49
53
  EnforcedStyle: always_true
50
54
  SafeAutoCorrect: true
51
55
 
56
+ Style/IfUnlessModifier:
57
+ Enabled: false
58
+
52
59
  Style/RequireOrder:
53
60
  Enabled: true
54
61
  SafeAutoCorrect: true
@@ -22,9 +22,23 @@ module Momocop
22
22
  end
23
23
 
24
24
  private def extract_associations(node, associations = [])
25
- if node.type == :send && ASSOCIATION_METHODS.include?(node.children[1])
26
- association_name = node.children[2].type == :sym ? node.children[2].children[0] : node.children[2]
27
- associations << { type: node.children[1], name: association_name }
25
+ association_type = node.children[1]
26
+ options = {}
27
+ if node.type == :send && ASSOCIATION_METHODS.include?(association_type)
28
+ association_name = node.children[2].children[0].to_sym
29
+
30
+ # Extract some options
31
+ if association_type == :belongs_to
32
+ option_hash = node.children[3]
33
+ option_hash&.children&.each do |option|
34
+ key_node, value_node = option.children
35
+ if value_node.type == :sym || value_node.type == :str
36
+ options[key_node.children[0]] = value_node.children[0]
37
+ end
38
+ end
39
+ end
40
+
41
+ associations << { type: association_type, name: association_name, options: }
28
42
  elsif node.children.is_a? Array
29
43
  node.children.each do |child|
30
44
  extract_associations(child, associations) if child.is_a? Parser::AST::Node
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Momocop
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.6'
5
5
  end
@@ -49,11 +49,24 @@ module RuboCop
49
49
  block_node = node.block_node
50
50
 
51
51
  # Check missing associations
52
+
53
+ # Exclude defined sequences
52
54
  defined_sequences = get_defined_sequence_names(block_node)
55
+ # Exclude defined properties
53
56
  defined_properties = get_defined_property_names(block_node)
57
+ # Exclude foreign keys
58
+ model_foreign_keys = get_model_foreign_key_column_names(class_name)
59
+ # All available properties
54
60
  model_properties = get_model_property_names(class_name)
61
+ # Calc missing properties
62
+ missing_properties = (
63
+ model_properties -
64
+ (defined_sequences + defined_properties) -
65
+ model_foreign_keys
66
+ ).sort
67
+
68
+ # for definition block generation
55
69
  model_enum_properties = get_model_enum_property_names(class_name)
56
- missing_properties = (model_properties - (defined_sequences + defined_properties)).sort
57
70
 
58
71
  # Add offense for missing properties
59
72
  return unless missing_properties.any?
@@ -101,8 +114,31 @@ module RuboCop
101
114
  return [] unless source
102
115
 
103
116
  extractor = ::Momocop::EnumExtractor.new
117
+ enums = extractor.extract(source)
118
+ return enums.map(&:to_sym)
119
+ end
120
+
121
+ private def get_model_foreign_key_column_names(class_name)
122
+ source = model_file_source(class_name)
123
+ return [] unless source
124
+
125
+ extractor = ::Momocop::AssociationExtractor.new
104
126
  associations = extractor.extract(source)
105
- return associations.map(&:to_sym)
127
+ foreign_key_names =
128
+ associations
129
+ .select { _1[:type] == :belongs_to }
130
+ .map { |association|
131
+ options = association[:options]
132
+ if options[:foreign_key]
133
+ options[:foreign_key]
134
+ elsif options[:class_name]
135
+ foreign_key_name(options[:class_name])
136
+ else
137
+ "#{association[:name]}_id"
138
+ end
139
+ }
140
+ .compact
141
+ return foreign_key_names.map(&:to_sym)
106
142
  end
107
143
 
108
144
  RESTRICTED_COLUMNS = %w[created_at updated_at].freeze
@@ -123,6 +159,14 @@ module RuboCop
123
159
  class_name.tableize.gsub('/', '_')
124
160
  end
125
161
 
162
+ # e.g.)
163
+ # 'User' -> ['users']
164
+ # 'Admin::User' -> ['admin_users', 'users']
165
+ private def foreign_key_name(class_name)
166
+ # TODO: parse model class file and try to get table_name_prefix and table_name_suffix
167
+ "#{class_name.underscore.gsub('/', '_')}_id"
168
+ end
169
+
126
170
  private def get_defined_sequence_names(block_node)
127
171
  body_node = block_node&.children&.last
128
172
  return [] unless body_node
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: momocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - supermomonga