legacy_column 0.1.2 → 0.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: ee20abfdeccbe8272d2ab663d6978c4de1034061750bedc386b9f6538f380f76
4
- data.tar.gz: 751edea2ab275196035179d7d15a93fcd02fc6f8d4e1665123334ff59f251baf
3
+ metadata.gz: a09851d6a69c5fffa341bbcb0fae4b937903c1b26e2a8d36bb9f4a8b2ca9201a
4
+ data.tar.gz: d458748a4dc483d16d11e8c6f02f4a794b5cc08bfad3f36f42bbba375816f91f
5
5
  SHA512:
6
- metadata.gz: fd99cfa33049ebdfd7a64bd5589350ae4c963845319b9637afd472f9ee0efae3d6a2e0fe09f14db461cd2f134816dd768829dec347d69da85dfd21ab9ebaa653
7
- data.tar.gz: e1bec36f5e7420cbd1eb25b38b8748cff21afba5f32ff4d533c3fd43b185562b39d0b0c2ad2cc29e732bb37e2e7ed506df0100a3f6c8722beb51277bdca13c7a
6
+ metadata.gz: cf307d3a3da65ed7441173135cce638179e810b12c72b791aea18eeb93248740aba8aaf9dcf8e16a7bf3d2af82390f2ef189d6e01b096710a5bb7176a0c65056
7
+ data.tar.gz: 4b0427368bbf8969f7eadbe243307d71a4306381af8f5027b1ab0b5ba4fd03969375f3d3e324722aabe81ab7cd2bfd88989571634f28f63abf0955f3fa77f008
data/CLAUDE.md ADDED
@@ -0,0 +1,53 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is a Ruby gem called `legacy_column` that provides a Rails plugin for warning developers when they attempt to use legacy database columns that should be avoided. The gem uses ActiveSupport::Concern to extend ActiveRecord models with a class method that marks specified columns as legacy and prints warning messages when those columns are modified.
8
+
9
+ ## Core Architecture
10
+
11
+ - **Main module**: `lib/legacy_column.rb` - The core concern that provides the `legacy_column` class method and warning functionality
12
+ - **Rails integration**: `lib/legacy_column/railtie.rb` - Handles automatic inclusion into ActiveRecord::Base when Rails is present
13
+ - **Version file**: `lib/legacy_column/version.rb` - Contains gem version constant
14
+ - **Entry points**: `init.rb` and `rails/init.rb` - Legacy entry points for older Rails versions
15
+
16
+ The gem works by:
17
+ 1. Including the LegacyColumn concern into ActiveRecord::Base
18
+ 2. Adding a `legacy_column` class method that accepts column names and an optional message
19
+ 3. Setting up a `before_validation` callback that checks for changes to legacy columns
20
+ 4. Printing warnings to stdout when legacy columns are modified
21
+
22
+ ## Development Commands
23
+
24
+ ### Setup
25
+ ```bash
26
+ bin/setup # Install dependencies
27
+ ```
28
+
29
+ ### Testing
30
+ ```bash
31
+ bundle exec rake # Run all tests (default rake task)
32
+ bundle exec rspec # Run tests directly with RSpec
33
+ ```
34
+
35
+ ### Building
36
+ ```bash
37
+ bundle exec rake build # Build the gem
38
+ bundle exec rake install # Install gem locally
39
+ bundle exec rake release # Release gem (bumps version, creates git tag, pushes to rubygems)
40
+ ```
41
+
42
+ ## Test Database Configuration
43
+
44
+ The test suite uses SQLite3 with configuration in `spec/db/database.yml` and schema in `spec/db/schema.rb`. Tests create a temporary User model to test the legacy column functionality.
45
+
46
+ ## Dependencies
47
+
48
+ - **Runtime**: ActiveSupport >= 4.0.0, ActiveRecord >= 4.0.0
49
+ - **Development**: RSpec 3.2+, SQLite3 1.4.2+, Bundler 2.2.33+, Rake 13.0.1+
50
+
51
+ ## CI/CD
52
+
53
+ CircleCI configuration uses Ruby 2.6.3 and runs `bundle exec rake` to execute the test suite.
data/Gemfile.lock CHANGED
@@ -1,29 +1,44 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- legacy_column (0.1.2)
5
- activerecord (>= 4.0.0)
6
- activesupport (>= 4.0.0)
4
+ legacy_column (0.3.0)
5
+ activerecord (>= 5.2.0, < 9.0)
6
+ activesupport (>= 5.2.0, < 9.0)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (6.1.4.4)
12
- activesupport (= 6.1.4.4)
13
- activerecord (6.1.4.4)
14
- activemodel (= 6.1.4.4)
15
- activesupport (= 6.1.4.4)
16
- activesupport (6.1.4.4)
17
- concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ activemodel (8.0.2.1)
12
+ activesupport (= 8.0.2.1)
13
+ activerecord (8.0.2.1)
14
+ activemodel (= 8.0.2.1)
15
+ activesupport (= 8.0.2.1)
16
+ timeout (>= 0.4.0)
17
+ activesupport (8.0.2.1)
18
+ base64
19
+ benchmark (>= 0.3)
20
+ bigdecimal
21
+ concurrent-ruby (~> 1.0, >= 1.3.1)
22
+ connection_pool (>= 2.2.5)
23
+ drb
18
24
  i18n (>= 1.6, < 2)
25
+ logger (>= 1.4.2)
19
26
  minitest (>= 5.1)
20
- tzinfo (~> 2.0)
21
- zeitwerk (~> 2.3)
22
- concurrent-ruby (1.1.9)
27
+ securerandom (>= 0.3)
28
+ tzinfo (~> 2.0, >= 2.0.5)
29
+ uri (>= 0.13.1)
30
+ base64 (0.3.0)
31
+ benchmark (0.4.1)
32
+ bigdecimal (3.2.3)
33
+ concurrent-ruby (1.3.5)
34
+ connection_pool (2.5.4)
23
35
  diff-lcs (1.4.4)
24
- i18n (1.8.11)
36
+ drb (2.2.3)
37
+ i18n (1.14.7)
25
38
  concurrent-ruby (~> 1.0)
26
- minitest (5.15.0)
39
+ logger (1.7.0)
40
+ mini_portile2 (2.8.9)
41
+ minitest (5.25.5)
27
42
  rake (13.0.1)
28
43
  rspec (3.9.0)
29
44
  rspec-core (~> 3.9.0)
@@ -38,10 +53,13 @@ GEM
38
53
  diff-lcs (>= 1.2.0, < 2.0)
39
54
  rspec-support (~> 3.9.0)
40
55
  rspec-support (3.9.3)
41
- sqlite3 (1.4.2)
42
- tzinfo (2.0.4)
56
+ securerandom (0.4.1)
57
+ sqlite3 (2.7.3)
58
+ mini_portile2 (~> 2.8.0)
59
+ timeout (0.4.3)
60
+ tzinfo (2.0.6)
43
61
  concurrent-ruby (~> 1.0)
44
- zeitwerk (2.5.3)
62
+ uri (1.0.3)
45
63
 
46
64
  PLATFORMS
47
65
  ruby
@@ -51,7 +69,7 @@ DEPENDENCIES
51
69
  legacy_column!
52
70
  rake (~> 13.0.1)
53
71
  rspec (~> 3.2)
54
- sqlite3 (~> 1.4.2)
72
+ sqlite3 (>= 1.4.0)
55
73
 
56
74
  BUNDLED WITH
57
75
  2.3.4
data/README.md CHANGED
@@ -7,13 +7,27 @@ A gem that will print a message if a developer is trying to use a column that is
7
7
 
8
8
  ## Installation
9
9
 
10
+ Add this line to your application's Gemfile:
10
11
 
11
12
  ```ruby
12
13
  gem 'legacy_column'
13
14
  ```
14
15
 
16
+ And then execute:
17
+ ```bash
18
+ bundle install
19
+ ```
20
+
21
+ ## Compatibility
22
+
23
+ This gem supports:
24
+ - Ruby 2.7+
25
+ - Rails 5.2+, 6.0+, 6.1+, 7.0+, 7.1+, 7.2+, 8.0+
26
+
15
27
  ## Usage
16
28
 
29
+ ### Basic Usage
30
+
17
31
  Just list the column names:
18
32
  ```ruby
19
33
  legacy_column :old_email, :old_phone_number
@@ -24,14 +38,61 @@ A custom message can be added:
24
38
  legacy_column :old_email, :old_phone_number, message: 'Do not touch this!!!'
25
39
  ```
26
40
 
27
- It will output something like this in rails logs:
41
+ ### Read Access Detection
42
+
43
+ By default, the gem only detects write operations (when columns are modified). To also detect read access, use the `detect_reads` option:
44
+
45
+ ```ruby
46
+ legacy_column :old_email, :old_phone_number, detect_reads: true
47
+ ```
48
+
49
+ This will warn whenever the legacy columns are accessed:
50
+
51
+ ```ruby
52
+ legacy_column :old_status, message: 'This field is deprecated!', detect_reads: true
53
+
54
+ user.old_status # Will log a warning about read access
55
+ user.old_status = 'active' # Will log a warning about write access
56
+ ```
57
+
58
+ ### Combined Usage
59
+
60
+ You can combine read detection with custom messages:
61
+ ```ruby
62
+ legacy_column :old_price, :old_name,
63
+ message: 'These fields will be removed in v2.0!',
64
+ detect_reads: true
65
+ ```
66
+
67
+ ## Output Examples
68
+
69
+ ### Write Detection (Default)
70
+ ```
71
+ USE of legacy column detected.
72
+ User => old_email
73
+ Do not touch this!!!
74
+ ```
28
75
 
76
+ ### Read Detection (When enabled)
29
77
  ```
30
- Use of legacy column detected.
78
+ READ of legacy column detected.
31
79
  User => old_email
32
80
  Do not touch this!!!
33
81
  ```
34
82
 
83
+ ## Logging
84
+
85
+ The gem will:
86
+ - Log warnings to `Rails.logger` when Rails is available
87
+ - Fall back to `puts` for non-Rails environments or when Rails.logger is not available
88
+
89
+ ## Options
90
+
91
+ | Option | Default | Description |
92
+ |--------|---------|-------------|
93
+ | `message` | `"This column is set as legacy and should not be used anymore."` | Custom warning message |
94
+ | `detect_reads` | `false` | Enable read access detection |
95
+
35
96
  ## Contributing
36
97
  Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
37
98
 
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.required_rubygems_version = ">= 1.3.4"
20
20
 
21
- spec.add_dependency "activesupport", [">= 4.0.0"]
22
- spec.add_dependency "activerecord", [">= 4.0.0"]
21
+ spec.add_dependency "activesupport", [">= 5.2.0", "< 9.0"]
22
+ spec.add_dependency "activerecord", [">= 5.2.0", "< 9.0"]
23
23
  spec.add_development_dependency "bundler", ">= 2.2.33"
24
24
  spec.add_development_dependency "rake", "~> 13.0.1"
25
25
  spec.add_development_dependency "rspec", "~> 3.2"
26
- spec.add_development_dependency "sqlite3", "~> 1.4.2"
26
+ spec.add_development_dependency "sqlite3", ">= 1.4.0"
27
27
  end
@@ -1,3 +1,3 @@
1
1
  module LegacyColumn
2
- VERSION = '0.1.2'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/legacy_column.rb CHANGED
@@ -10,25 +10,54 @@ module LegacyColumn
10
10
  included do
11
11
  class_attribute :legacy_column_names, instance_writer: false, default: nil
12
12
  class_attribute :legacy_column_message, instance_writer: false, default: nil
13
+ class_attribute :legacy_column_detect_reads, instance_writer: false, default: false
13
14
  end
14
15
 
15
16
  module ClassMethods
16
17
  DEFAULT_MESSAGE = 'This column is set as legacy and should not be used anymore.'
17
18
 
18
- def legacy_column(*columns, message: nil)
19
+ def legacy_column(*columns, message: nil, detect_reads: false)
19
20
  return unless columns
20
21
 
21
22
  self.legacy_column_names = columns
22
23
  self.legacy_column_message = message || DEFAULT_MESSAGE
24
+ self.legacy_column_detect_reads = detect_reads
23
25
 
24
26
  send('before_validation', :legacy_column)
27
+
28
+ if detect_reads
29
+ setup_read_detection(columns)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def setup_read_detection(columns)
36
+ mod = Module.new do
37
+ columns.each do |column|
38
+ define_method(column) do
39
+ # Log read access
40
+ if defined?(Rails) && Rails.logger
41
+ Rails.logger.warn "\n\nREAD of legacy column detected.\n #{self.class} => #{column}\n #{legacy_column_message}\n\n"
42
+ else
43
+ puts "\n\nREAD of legacy column detected.\n #{self.class} => #{column}\n #{legacy_column_message}\n\n"
44
+ end
45
+ super() # Call original getter
46
+ end
47
+ end
48
+ end
49
+ prepend(mod)
25
50
  end
26
51
  end
27
52
 
28
53
  def legacy_column
29
54
  legacy_column_names.each do |column|
30
- if changed_attributes.key?(column.to_s)
31
- puts "\n\nUSE of legacy column detected.\n #{self.class} => #{column}\n #{legacy_column_message}\n\n"
55
+ if changes_to_save.key?(column.to_s)
56
+ if defined?(Rails) && Rails.logger
57
+ Rails.logger.warn "\n\nUSE of legacy column detected.\n #{self.class} => #{column}\n #{legacy_column_message}\n\n"
58
+ else
59
+ puts "\n\nUSE of legacy column detected.\n #{self.class} => #{column}\n #{legacy_column_message}\n\n"
60
+ end
32
61
  end
33
62
  end
34
63
  end
data/spec/db/schema.rb CHANGED
@@ -6,4 +6,21 @@ ActiveRecord::Schema.define(:version => 0) do
6
6
  t.string :old_email
7
7
  t.string :old_phone_number
8
8
  end
9
+
10
+ create_table :products, :force => true do |t|
11
+ t.decimal :old_price
12
+ t.string :old_name
13
+ end
14
+
15
+ create_table :items, :force => true do |t|
16
+ t.string :old_status
17
+ end
18
+
19
+ create_table :orders, :force => true do |t|
20
+ t.decimal :old_total
21
+ end
22
+
23
+ create_table :accounts, :force => true do |t|
24
+ t.decimal :old_balance
25
+ end
9
26
  end
data/spec/db/test.sqlite3 CHANGED
Binary file
@@ -50,4 +50,124 @@ RSpec.describe LegacyColumn do
50
50
  end
51
51
  end
52
52
  end
53
+
54
+ context 'read detection enabled' do
55
+ before do
56
+ class Product < ActiveRecord::Base
57
+ legacy_column :old_price, :old_name, detect_reads: true
58
+ end
59
+ end
60
+
61
+ it 'should recognize detect_reads setting' do
62
+ expect(Product.legacy_column_detect_reads).to eq(true)
63
+ end
64
+
65
+ describe 'read access detection' do
66
+ let(:product) do
67
+ # Create product without triggering write detection by using update_attribute
68
+ p = Product.create
69
+ p.update_attribute(:old_price, 100)
70
+ p.update_attribute(:old_name, 'Test Product')
71
+ p
72
+ end
73
+
74
+ it 'detects read access to legacy columns' do
75
+ expect {
76
+ product.old_price
77
+ }.to output(/READ of legacy column detected.*Product => old_price.*This column is set as legacy and should not be used anymore/m).to_stdout
78
+ end
79
+
80
+ it 'detects read access to multiple legacy columns' do
81
+ expect {
82
+ product.old_name
83
+ }.to output(/READ of legacy column detected.*Product => old_name.*This column is set as legacy and should not be used anymore/m).to_stdout
84
+ end
85
+
86
+ it 'still returns the actual attribute value' do
87
+ # Capture output but test return value
88
+ value = nil
89
+ expect {
90
+ value = product.old_price
91
+ }.to output(/READ of legacy column detected/).to_stdout
92
+ expect(value).to eq(100)
93
+ end
94
+ end
95
+ end
96
+
97
+ context 'read detection with custom message' do
98
+ before do
99
+ class Item < ActiveRecord::Base
100
+ legacy_column :old_status, message: 'Stop reading this!', detect_reads: true
101
+ end
102
+ end
103
+
104
+ describe 'read access detection with custom message' do
105
+ let(:item) do
106
+ i = Item.create
107
+ i.update_attribute(:old_status, 'active')
108
+ i
109
+ end
110
+
111
+ it 'shows custom message for read access' do
112
+ expect {
113
+ item.old_status
114
+ }.to output(/READ of legacy column detected.*Item => old_status.*Stop reading this!/m).to_stdout
115
+ end
116
+ end
117
+ end
118
+
119
+ context 'read detection disabled (default)' do
120
+ before do
121
+ class Order < ActiveRecord::Base
122
+ legacy_column :old_total # detect_reads defaults to false
123
+ end
124
+ end
125
+
126
+ it 'should not detect reads when disabled' do
127
+ expect(Order.legacy_column_detect_reads).to eq(false)
128
+ end
129
+
130
+ describe 'no read access detection' do
131
+ let(:order) do
132
+ o = Order.create
133
+ o.update_attribute(:old_total, 50)
134
+ o
135
+ end
136
+
137
+ it 'does not detect read access when disabled' do
138
+ expect {
139
+ order.old_total
140
+ }.to_not output.to_stdout
141
+ end
142
+
143
+ it 'still returns the actual attribute value' do
144
+ expect(order.old_total).to eq(50)
145
+ end
146
+ end
147
+ end
148
+
149
+ context 'combined read and write detection' do
150
+ before do
151
+ class Account < ActiveRecord::Base
152
+ legacy_column :old_balance, message: 'Legacy account field!', detect_reads: true
153
+ end
154
+ end
155
+
156
+ describe 'both read and write detection' do
157
+ let(:account) { Account.create }
158
+
159
+ it 'detects write access' do
160
+ expect {
161
+ account.update(old_balance: 1000)
162
+ }.to output("\n\nUSE of legacy column detected.\n Account => old_balance\n Legacy account field!\n\n").to_stdout
163
+ end
164
+
165
+ it 'detects read access' do
166
+ account.update_attribute(:old_balance, 1000) # Set without triggering write detection
167
+ expect {
168
+ account.old_balance
169
+ }.to output(/READ of legacy column detected.*Account => old_balance.*Legacy account field!/m).to_stdout
170
+ end
171
+ end
172
+ end
53
173
  end
data/spec/spec_helper.rb CHANGED
@@ -5,8 +5,14 @@ require "active_record"
5
5
  require "yaml"
6
6
 
7
7
  config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
8
- ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
9
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
8
+ db_config = config[ENV['DB'] || 'sqlite3']
9
+
10
+ if ActiveRecord::VERSION::MAJOR >= 6
11
+ ActiveRecord::Base.establish_connection(db_config)
12
+ else
13
+ ActiveRecord::Base.configurations = {'test' => db_config}
14
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
15
+ end
10
16
 
11
17
  # Load Test Schema into the Database
12
18
  load(File.dirname(__FILE__) + "/db/schema.rb")
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legacy_column
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksander Lopez Yazikov
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-12-30 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,28 +15,40 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: 4.0.0
18
+ version: 5.2.0
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9.0'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
26
  - - ">="
25
27
  - !ruby/object:Gem::Version
26
- version: 4.0.0
28
+ version: 5.2.0
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9.0'
27
32
  - !ruby/object:Gem::Dependency
28
33
  name: activerecord
29
34
  requirement: !ruby/object:Gem::Requirement
30
35
  requirements:
31
36
  - - ">="
32
37
  - !ruby/object:Gem::Version
33
- version: 4.0.0
38
+ version: 5.2.0
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '9.0'
34
42
  type: :runtime
35
43
  prerelease: false
36
44
  version_requirements: !ruby/object:Gem::Requirement
37
45
  requirements:
38
46
  - - ">="
39
47
  - !ruby/object:Gem::Version
40
- version: 4.0.0
48
+ version: 5.2.0
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '9.0'
41
52
  - !ruby/object:Gem::Dependency
42
53
  name: bundler
43
54
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +95,16 @@ dependencies:
84
95
  name: sqlite3
85
96
  requirement: !ruby/object:Gem::Requirement
86
97
  requirements:
87
- - - "~>"
98
+ - - ">="
88
99
  - !ruby/object:Gem::Version
89
- version: 1.4.2
100
+ version: 1.4.0
90
101
  type: :development
91
102
  prerelease: false
92
103
  version_requirements: !ruby/object:Gem::Requirement
93
104
  requirements:
94
- - - "~>"
105
+ - - ">="
95
106
  - !ruby/object:Gem::Version
96
- version: 1.4.2
107
+ version: 1.4.0
97
108
  description: A gem that will print a message if a developer is trying to use a column
98
109
  that is from a legacy system but has to stay there.
99
110
  email:
@@ -102,6 +113,7 @@ executables: []
102
113
  extensions: []
103
114
  extra_rdoc_files: []
104
115
  files:
116
+ - CLAUDE.md
105
117
  - Gemfile
106
118
  - Gemfile.lock
107
119
  - README.md
@@ -120,7 +132,6 @@ homepage: https://github.com/logicalgroove/legacy_column
120
132
  licenses:
121
133
  - MIT
122
134
  metadata: {}
123
- post_install_message:
124
135
  rdoc_options: []
125
136
  require_paths:
126
137
  - lib
@@ -135,8 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
146
  - !ruby/object:Gem::Version
136
147
  version: 1.3.4
137
148
  requirements: []
138
- rubygems_version: 3.2.27
139
- signing_key:
149
+ rubygems_version: 3.6.9
140
150
  specification_version: 4
141
151
  summary: Warning for your legacy columns.
142
152
  test_files: []