the_schema_is 0.0.4 → 0.0.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: 054c02711e49163e9600e925da6c9bab7007b276528472834e3383326284f5c9
4
- data.tar.gz: 837d5d1f3910505a3ac0e2aa4ff7742ff960555ed0edd27dfa2a7f7b7f75d996
3
+ metadata.gz: 4e9f1550133bd9ad6932e9940f55a7921b956a228dda93b14029e98d7d83d10b
4
+ data.tar.gz: 35903ce14ac034af1649d2a92be07f063fb1c224dcd48c92a8b4c696827b8968
5
5
  SHA512:
6
- metadata.gz: 2042bfe76d1813cc7ad043b4947fa885162e4630e27d4bdb30b5ff961de77ad9fd9e01ae36d348ddf25fa55d63d58157cb0256d1ebad80ec7fd9246368201d60
7
- data.tar.gz: da567e5da9f013be952177ce79d2ba6f2ed1431f342723360f660b0dda909d02a120ad9bcfd6dfa5d9b039e74948f005655151280e10c1dd3509af27b6897d2e
6
+ metadata.gz: 24b95d5aac99fbc31fc87b7fdf7254450a6cee7f862d155d1a7a0d7539e89b2b1b105016f6f245e6a40cd913edb3e20430d9f7fab46ba47964be289c1e436596
7
+ data.tar.gz: 652544c051f292ddaaf7cde3bd7ce4a68702590f6efe79eb7fd9196dec78b726cb1cb19ca206cf0e354bc11ccbfb189b3580e7ac91c353bdafc0150c2a6ebefc
data/Changelog.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # the-schema-is changes
2
2
 
3
+ ## 2024-12-22 - 0.0.6
4
+
5
+ * Drop support for Ruby < 2.7;
6
+ * Ensure support for all Ruby versions from 2.7 to 3.4-dev (replace memoist with memery);
7
+ * Slightly update code with the new Rubocop.
8
+
9
+ ## 2021-11-04 - 0.0.5
10
+
11
+ * Support `enum` column type;
12
+ * Add `RemoveDefinitions` config key for leaner `the_schema_is` definitions (avoiding huge index descriptions in models).
13
+
3
14
  ## 2021-09-15 - 0.0.4
4
15
 
5
16
  * Get rid of [Fast](https://jonatas.github.io/fast/) dependency. It is cool, but we switched to use Rubocop's own `NodePattern` to lessen the dependency burden (Fast was depending on [astrolabe](https://github.com/yujinakayama/astrolabe) which wasn't updated in 6 years, locking parser dependency to old version and making Fast incompatible with newer Rubocop);
data/README.md CHANGED
@@ -134,8 +134,9 @@ TheSchemaIs:
134
134
  Currently available settings are:
135
135
 
136
136
  * `TablePrefix` to help `the_schema_is` deduce table name from class name;
137
- * `Schema` to set path to schema (by default `db/schema.rb`)
138
- * `BaseClass` to help `the_schema_is` guess what is a model class (by default `ApplicationRecord` and `ActiveRecord::Base`).
137
+ * `Schema` to set path to schema (by default `db/schema.rb`);
138
+ * `BaseClass` to help `the_schema_is` guess what is a model class (by default `ApplicationRecord` and `ActiveRecord::Base`);
139
+ * `RemoveDefinitions`: list of definition keys to remove (for example, `[index, foreign_key, limit]`) when copying definitions into models; this might be desirable for leaner `the_schema_is` statements, displaying only field types/names.
139
140
 
140
141
  So, if you have your custom-named base class, you should do:
141
142
 
data/config/defaults.yml CHANGED
@@ -6,6 +6,7 @@ TheSchemaIs:
6
6
  Schema: db/schema.rb
7
7
  BaseClass: ['ActiveRecord::Base', 'ApplicationRecord']
8
8
  TablePrefix: ''
9
+ RemoveDefinitions: []
9
10
 
10
11
  TheSchemaIs/Presence:
11
12
  Description: "Check presence of the_schema_is statement in ActiveRecord models"
@@ -15,7 +15,7 @@ module TheSchemaIs
15
15
  extend RuboCop::AST::NodePattern::Macros
16
16
 
17
17
  class << self
18
- extend Memoist
18
+ include Memery
19
19
 
20
20
  def search(pattern, node)
21
21
  search_methods[pattern].then { |m| instance.send(m, node) }
@@ -66,7 +66,7 @@ module TheSchemaIs
66
66
  end
67
67
 
68
68
  def find_parent(type)
69
- Enumerator.produce(parent, &:parent).slice_after { |n| n && n.type == type }.first.last
69
+ Enumerator.produce(parent, &:parent).find { |n| n && n.type == type }
70
70
  end
71
71
  end
72
72
  end
@@ -15,7 +15,7 @@ module TheSchemaIs
15
15
  float integer json string text time timestamp virtual].freeze
16
16
  POSTGRES_COLUMN_TYPES = %i[jsonb inet cidr macaddr hstore uuid].freeze
17
17
 
18
- COLUMN_DEFS = (STANDARD_COLUMN_TYPES + POSTGRES_COLUMN_TYPES + %i[column]).freeze
18
+ COLUMN_DEFS = (STANDARD_COLUMN_TYPES + POSTGRES_COLUMN_TYPES + %i[enum column]).freeze
19
19
 
20
20
  Model = Struct.new(:class_name, :table_name, :source, :schema, :table_name_node,
21
21
  keyword_init: true)
@@ -33,9 +33,11 @@ module TheSchemaIs
33
33
  RuboCop::AST::ProcessedSource.new(code, 2.7).ast
34
34
  end
35
35
 
36
- def self.schema(path)
36
+ def self.schema(path, remove_definition_attrs: [])
37
37
  ast = parse(File.read(path))
38
38
 
39
+ ast = remove_attributes(ast, remove_definition_attrs) unless remove_definition_attrs.empty?
40
+
39
41
  ast.ast_search('(block (send nil? :create_table (str $_) _) _ $_)').to_h
40
42
  end
41
43
 
@@ -68,8 +70,7 @@ module TheSchemaIs
68
70
 
69
71
  Model.new(
70
72
  class_name: class_name,
71
- table_name: table_name ||
72
- table_prefix.+(ActiveSupport::Inflector.tableize(class_name)),
73
+ table_name: table_name || table_prefix + ActiveSupport::Inflector.tableize(class_name),
73
74
  source: definition_node,
74
75
  schema: schema_node,
75
76
  table_name_node: name_node&.first
@@ -95,6 +96,29 @@ module TheSchemaIs
95
96
  end
96
97
  }.compact
97
98
  end
99
+
100
+ # Removes unnecessary column definitions from further comparison, using schema source tree editing
101
+ def self.remove_attributes(ast, attrs_to_remove)
102
+ buf = ast.loc.expression.source_buffer
103
+ src = buf.source
104
+ rewriter = ::Parser::Source::TreeRewriter.new(buf)
105
+
106
+ # FIXME: Two nested cycles can be simplifid to just look for column definition, probably
107
+ ast.ast_search('(block (send nil? :create_table (str _) _) _ $_)').each do |table_def|
108
+ table_def.children.each do |col|
109
+ dfn = col.children[3] or next
110
+ dfn.children
111
+ .select { |c| attrs_to_remove.include?(c.children[0].children[0]) }
112
+ .each do |c|
113
+ prev_comma = c.source_range.begin_pos.step(by: -1).find { |pos| src[pos] == ',' }
114
+ range = ::Parser::Source::Range.new(buf, prev_comma, c.source_range.end_pos)
115
+ rewriter.remove(range)
116
+ end
117
+ end
118
+ end
119
+
120
+ RuboCop::AST::ProcessedSource.new(rewriter.process, 2.7).ast
121
+ end
98
122
  end
99
123
  end
100
124
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'memoist'
3
+ require 'memery'
4
4
  require 'rubocop'
5
5
  require 'backports/latest'
6
6
 
@@ -15,13 +15,17 @@ module TheSchemaIs
15
15
  using Cops::NodeRefinements
16
16
 
17
17
  module Cops
18
- def self.schema_cache
19
- @schema_cache ||= Hash.new { |h, path| h[path] = Cops::Parser.schema(path) }
18
+ class << self
19
+ include Memery
20
+
21
+ memoize def fetch_schema(path, remove_definition_attrs: [])
22
+ Cops::Parser.schema(path, remove_definition_attrs: remove_definition_attrs)
23
+ end
20
24
  end
21
25
  end
22
26
 
23
27
  module Common
24
- extend Memoist
28
+ include Memery
25
29
 
26
30
  def self.included(cls)
27
31
  cls.define_singleton_method(:badge) do
@@ -59,7 +63,9 @@ module TheSchemaIs
59
63
  end
60
64
 
61
65
  memoize def schema
62
- Cops.schema_cache.dig(schema_path, model.table_name)
66
+ attrs_to_remove = cop_config['RemoveDefinitions']&.map(&:to_sym) || []
67
+ # It is OK if it returns Nil, just will be handled by "schema is absent" cop
68
+ Cops.fetch_schema(schema_path, remove_definition_attrs: attrs_to_remove)[model.table_name]
63
69
  end
64
70
 
65
71
  memoize def model_columns
@@ -183,7 +189,7 @@ module TheSchemaIs
183
189
  def register_offense(_node)
184
190
  return if model.schema.nil? || schema.nil?
185
191
 
186
- extra_columns.each do |_, col|
192
+ extra_columns.each_value do |col|
187
193
  add_offense(col.source, message: MSG % col.name) do |corrector|
188
194
  src_range = col.source.loc.expression
189
195
  end_pos = col.source.next_sibling.then { |n|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: the_schema_is
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-16 00:00:00.000000000 Z
11
+ date: 2024-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backports
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: memoist
56
+ name: memery
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -137,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
137
  requirements:
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
- version: 2.5.0
140
+ version: 2.7.0
141
141
  required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="