arql 0.4.12 → 0.4.15
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README-zh_CN.org +1 -0
- data/README.org +1 -0
- data/docs/plans/2026-04-02-rename-columns-design.md +275 -0
- data/lib/arql/definition.rb +100 -21
- data/lib/arql/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d444bc5ecc11b4c15db01b52b413341e85525d71d82f24e994315418b728a989
|
|
4
|
+
data.tar.gz: 1e69014e37aafa3974c3aae3be52c37c7f3c27db2c7b59d169caa8b4de5ce6d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0dd50276ddff1a65d3d01bc7eb8ec05dbdd59d441eb8fe2555ca3ccaf2b951650ace6b7bf5908f4eccb2f38a0dec7000130f41c63f62df74e4a8ef4c6504897d
|
|
7
|
+
data.tar.gz: ada7756d3e50fbff30e8b6581b1eceaebff35fdacb7bf76bf504348410fd7152398515799de35f355e91c3d3cb87d87646a401901da3003bb4b16c2ead88bfd5
|
data/Gemfile.lock
CHANGED
data/README-zh_CN.org
CHANGED
data/README.org
CHANGED
|
@@ -225,6 +225,7 @@
|
|
|
225
225
|
representing the constant alias (Arql) created for the model By default, aliases are also automatically created for
|
|
226
226
|
the generated model class according to certain rules, and if an alias is specified here, the user-provided value
|
|
227
227
|
will be used as the alias)
|
|
228
|
+
12. =ignored_columns= : An array of column names to be ignored when generating the model, default is an empty array
|
|
228
229
|
|
|
229
230
|
=model_names= Examples of configuration items:
|
|
230
231
|
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# rename_columns Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** Add `rename_columns` config option that creates AR-level attribute aliases for columns with conflicting names (e.g., `model_name`).
|
|
6
|
+
|
|
7
|
+
**Architecture:** In `lib/arql/definition.rb`, add `rename_columns_mapping` accessor, modify `make_model_class` to merge renamed columns into `ignored_columns` and call `alias_attribute`, and add `validate_rename_columns!` for three-layer conflict detection at startup.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Ruby, ActiveRecord `alias_attribute`, `ignored_columns`, `ActiveRecord::AttributeMethods.dangerous_attribute_methods`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### Task 1: Add `rename_columns_mapping` accessor method
|
|
14
|
+
|
|
15
|
+
**Files:**
|
|
16
|
+
- Modify: `lib/arql/definition.rb:95-97` (after `model_names_mapping`)
|
|
17
|
+
|
|
18
|
+
**Step 1: Add the method**
|
|
19
|
+
|
|
20
|
+
After line 97 (`end` of `model_names_mapping`), add:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
def rename_columns_mapping
|
|
24
|
+
@rename_columns_mapping ||= @options[:rename_columns] || {}
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This follows the exact same pattern as `model_names_mapping` on line 95.
|
|
29
|
+
|
|
30
|
+
**Step 2: Verify syntax**
|
|
31
|
+
|
|
32
|
+
Run: `ruby -c lib/arql/definition.rb`
|
|
33
|
+
Expected: `Syntax OK`
|
|
34
|
+
|
|
35
|
+
**Step 3: Commit**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git add lib/arql/definition.rb
|
|
39
|
+
git commit -m "feat: add rename_columns_mapping accessor"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### Task 2: Modify `make_model_class` to handle column renaming
|
|
45
|
+
|
|
46
|
+
**Files:**
|
|
47
|
+
- Modify: `lib/arql/definition.rb:150-175` (the `make_model_class` method)
|
|
48
|
+
|
|
49
|
+
**Step 1: Implement the rename logic inside the Class.new block**
|
|
50
|
+
|
|
51
|
+
Replace lines 150-175 with:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
def make_model_class(table_name, primary_keys)
|
|
55
|
+
options = @options
|
|
56
|
+
rename_columns = rename_columns_mapping
|
|
57
|
+
Class.new(@base_model) do
|
|
58
|
+
include Arql::Extension
|
|
59
|
+
if primary_keys.is_a?(Array) && primary_keys.size > 1
|
|
60
|
+
self.primary_keys = primary_keys
|
|
61
|
+
else
|
|
62
|
+
self.primary_key = primary_keys&.first
|
|
63
|
+
end
|
|
64
|
+
self.table_name = table_name
|
|
65
|
+
self.inheritance_column = nil
|
|
66
|
+
|
|
67
|
+
# Merge renamed column original names into ignored_columns
|
|
68
|
+
ignored = Array(options[:ignored_columns])
|
|
69
|
+
rename_columns.each do |old_name, new_name|
|
|
70
|
+
ignored << old_name.to_s
|
|
71
|
+
end
|
|
72
|
+
self.ignored_columns = ignored.uniq if ignored.present?
|
|
73
|
+
|
|
74
|
+
ActiveRecord.default_timezone = :local
|
|
75
|
+
if options[:created_at].present?
|
|
76
|
+
define_singleton_method :timestamp_attributes_for_create do
|
|
77
|
+
options[:created_at]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if options[:updated_at].present?
|
|
82
|
+
define_singleton_method :timestamp_attributes_for_update do
|
|
83
|
+
options[:updated_at]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Create alias attributes for renamed columns
|
|
88
|
+
rename_columns.each do |old_name, new_name|
|
|
89
|
+
alias_attribute new_name.to_sym, old_name.to_sym
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Key changes from the original:
|
|
96
|
+
1. `ignored_columns` now merges both `options[:ignored_columns]` and all `rename_columns` original names
|
|
97
|
+
2. `alias_attribute` is called for each rename mapping inside the `Class.new` block
|
|
98
|
+
|
|
99
|
+
**Step 2: Verify syntax**
|
|
100
|
+
|
|
101
|
+
Run: `ruby -c lib/arql/definition.rb`
|
|
102
|
+
Expected: `Syntax OK`
|
|
103
|
+
|
|
104
|
+
**Step 3: Commit**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
git add lib/arql/definition.rb
|
|
108
|
+
git commit -m "feat: integrate rename_columns into make_model_class with ignored_columns merge and alias_attribute"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Task 3: Add `validate_rename_columns!` with three-layer conflict detection
|
|
114
|
+
|
|
115
|
+
**Files:**
|
|
116
|
+
- Modify: `lib/arql/definition.rb` (add new method after `rename_columns_mapping`)
|
|
117
|
+
|
|
118
|
+
**Step 1: Add the validation method**
|
|
119
|
+
|
|
120
|
+
After the `rename_columns_mapping` method, add:
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
ARQL_EXTENSION_INSTANCE_METHODS = %i[v t vd to_insert_sql to_upsert_sql dump write_csv write_excel].freeze
|
|
124
|
+
|
|
125
|
+
def validate_rename_columns!(table_name, model_class)
|
|
126
|
+
rename_columns = rename_columns_mapping
|
|
127
|
+
table_column_names = model_class.column_names.map(&:to_s)
|
|
128
|
+
ar_reserved = ActiveRecord::AttributeMethods.dangerous_attribute_methods
|
|
129
|
+
|
|
130
|
+
rename_columns.each do |old_name, new_name|
|
|
131
|
+
old_name = old_name.to_s
|
|
132
|
+
new_name = new_name.to_s
|
|
133
|
+
|
|
134
|
+
# Check: original column must exist in the table
|
|
135
|
+
unless table_column_names.include?(old_name)
|
|
136
|
+
warn "rename_columns: column '#{old_name}' not found in table '#{table_name}', skipping"
|
|
137
|
+
next
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Check: new name must not conflict with existing column names
|
|
141
|
+
if table_column_names.include?(new_name) && new_name != old_name
|
|
142
|
+
warn "rename_columns: new name '#{new_name}' conflicts with existing column in table '#{table_name}', skipping rename of '#{old_name}'"
|
|
143
|
+
next
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Check: new name must not be an ActiveRecord reserved attribute method
|
|
147
|
+
if ar_reserved.include?(new_name)
|
|
148
|
+
raise ActiveRecord::DangerousAttributeError,
|
|
149
|
+
"rename_columns: new name '#{new_name}' is a reserved ActiveRecord method, cannot use as column alias"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Check: new name must not conflict with arql Extension instance methods
|
|
153
|
+
if ARQL_EXTENSION_INSTANCE_METHODS.include?(new_name.to_sym)
|
|
154
|
+
warn "rename_columns: new name '#{new_name}' conflicts with an arql method in table '#{table_name}', skipping rename of '#{old_name}'"
|
|
155
|
+
next
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Step 2: Verify syntax**
|
|
162
|
+
|
|
163
|
+
Run: `ruby -c lib/arql/definition.rb`
|
|
164
|
+
Expected: `Syntax OK`
|
|
165
|
+
|
|
166
|
+
**Step 3: Commit**
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
git add lib/arql/definition.rb
|
|
170
|
+
git commit -m "feat: add validate_rename_columns! with three-layer conflict detection"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Task 4: Wire up validation in `define_model_from_table` and `redefine`
|
|
176
|
+
|
|
177
|
+
**Files:**
|
|
178
|
+
- Modify: `lib/arql/definition.rb:99-114` (`define_model_from_table`)
|
|
179
|
+
- Modify: `lib/arql/definition.rb:39-53` (`redefine`)
|
|
180
|
+
|
|
181
|
+
**Step 1: Add validation call in `define_model_from_table`**
|
|
182
|
+
|
|
183
|
+
In `define_model_from_table`, after line 113 (the return hash), add the validation call. The method should become:
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
def define_model_from_table(table_name, primary_keys)
|
|
187
|
+
model_name = make_model_name(table_name)
|
|
188
|
+
return unless model_name
|
|
189
|
+
|
|
190
|
+
model_class = make_model_class(table_name, primary_keys)
|
|
191
|
+
validate_rename_columns!(table_name, model_class)
|
|
192
|
+
@namespace_module.const_set(model_name, model_class)
|
|
193
|
+
abbr_name = make_model_abbr_name(model_name, table_name)
|
|
194
|
+
@namespace_module.const_set(abbr_name, model_class)
|
|
195
|
+
|
|
196
|
+
{ model: model_class, abbr: "#@namespace::#{abbr_name}", table: table_name }
|
|
197
|
+
end
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Only change: added `validate_rename_columns!(table_name, model_class)` after `make_model_class` and before `const_set`.
|
|
201
|
+
|
|
202
|
+
**Step 2: Verify `redefine` already works**
|
|
203
|
+
|
|
204
|
+
The `redefine` method (line 39) calls `define_model_from_table`, so it automatically picks up the validation. No changes needed to `redefine`.
|
|
205
|
+
|
|
206
|
+
**Step 3: Verify syntax**
|
|
207
|
+
|
|
208
|
+
Run: `ruby -c lib/arql/definition.rb`
|
|
209
|
+
Expected: `Syntax OK`
|
|
210
|
+
|
|
211
|
+
**Step 4: Commit**
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
git add lib/arql/definition.rb
|
|
215
|
+
git commit -m "feat: wire up validate_rename_columns! in define_model_from_table"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### Task 5: Manual verification
|
|
221
|
+
|
|
222
|
+
**Files:** None (testing only)
|
|
223
|
+
|
|
224
|
+
**Step 1: Verify with a real database**
|
|
225
|
+
|
|
226
|
+
Create a test SQLite database with a `model_name` column, configure `rename_columns`, and verify:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Create test DB
|
|
230
|
+
sqlite3 /tmp/arql_test.db "CREATE TABLE test_table (id INTEGER PRIMARY KEY, model_name TEXT, name TEXT); INSERT INTO test_table VALUES (1, 'TestModel', 'Alice');"
|
|
231
|
+
|
|
232
|
+
# Create config
|
|
233
|
+
cat > /tmp/arql_test.yml << 'EOF'
|
|
234
|
+
default:
|
|
235
|
+
adapter: sqlite3
|
|
236
|
+
database: /tmp/arql_test.db
|
|
237
|
+
rename_columns:
|
|
238
|
+
model_name: record_model_name
|
|
239
|
+
EOF
|
|
240
|
+
|
|
241
|
+
# Run arql
|
|
242
|
+
arql -c /tmp/arql_test.yml -E 'puts TestTable.last.record_model_name'
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Expected output: `TestModel`
|
|
246
|
+
|
|
247
|
+
**Step 2: Verify query aliasing**
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
arql -c /tmp/arql_test.yml -S -E 'puts TestTable.where(record_model_name: "TestModel").to_sql'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Expected output contains: `WHERE "test_table"."model_name" = 'TestModel'`
|
|
254
|
+
|
|
255
|
+
**Step 3: Verify conflict detection**
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
cat > /tmp/arql_test_bad.yml << 'EOF'
|
|
259
|
+
default:
|
|
260
|
+
adapter: sqlite3
|
|
261
|
+
database: /tmp/arql_test.db
|
|
262
|
+
rename_columns:
|
|
263
|
+
model_name: save
|
|
264
|
+
EOF
|
|
265
|
+
|
|
266
|
+
arql -c /tmp/arql_test_bad.yml -E 'puts "hello"'
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Expected: `ActiveRecord::DangerousAttributeError` with message about `save` being reserved.
|
|
270
|
+
|
|
271
|
+
**Step 4: Cleanup**
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
rm /tmp/arql_test.db /tmp/arql_test.yml /tmp/arql_test_bad.yml
|
|
275
|
+
```
|
data/lib/arql/definition.rb
CHANGED
|
@@ -2,7 +2,6 @@ require 'arql/concerns'
|
|
|
2
2
|
require 'arql/vd'
|
|
3
3
|
|
|
4
4
|
module Arql
|
|
5
|
-
|
|
6
5
|
class BaseModel < ::ActiveRecord::Base
|
|
7
6
|
self.abstract_class = true
|
|
8
7
|
|
|
@@ -24,9 +23,10 @@ module Arql
|
|
|
24
23
|
|
|
25
24
|
def self.method_missing(method_name, *args, &block)
|
|
26
25
|
if method_name.to_s =~ /^(.+)_like$/
|
|
27
|
-
attr_name =
|
|
26
|
+
attr_name = ::Regexp.last_match(1).to_sym
|
|
28
27
|
return super unless has_attribute?(attr_name)
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
send(:like, ::Regexp.last_match(1) => args.first)
|
|
30
30
|
else
|
|
31
31
|
super
|
|
32
32
|
end
|
|
@@ -34,7 +34,7 @@ module Arql
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
class Definition
|
|
37
|
-
|
|
37
|
+
attr_reader :connection, :ssh_proxy, :options, :models, :namespace_module, :namespace
|
|
38
38
|
|
|
39
39
|
def redefine
|
|
40
40
|
@models.each do |model|
|
|
@@ -78,16 +78,14 @@ module Arql
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
order_column = @options[:order_column]
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
end
|
|
90
|
-
end
|
|
81
|
+
return unless order_column
|
|
82
|
+
|
|
83
|
+
@models.each do |model|
|
|
84
|
+
model_class = model[:model]
|
|
85
|
+
model_class.define_singleton_method(:implicit_order_column) do
|
|
86
|
+
return unless column_names.include?(order_column)
|
|
87
|
+
|
|
88
|
+
order_column
|
|
91
89
|
end
|
|
92
90
|
end
|
|
93
91
|
end
|
|
@@ -96,11 +94,59 @@ module Arql
|
|
|
96
94
|
@model_names_mapping ||= @options[:model_names] || {}
|
|
97
95
|
end
|
|
98
96
|
|
|
97
|
+
def rename_columns_mapping
|
|
98
|
+
@rename_columns_mapping ||= @options[:rename_columns] || {}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
ARQL_EXTENSION_INSTANCE_METHODS = %i[v t vd to_insert_sql to_upsert_sql dump write_csv write_excel].freeze
|
|
102
|
+
|
|
103
|
+
def validate_rename_columns!(table_name, model_class)
|
|
104
|
+
table_column_names_set = model_class.column_names.to_set
|
|
105
|
+
return unless table_column_names_set.intersect?(rename_columns_mapping.keys.map(&:to_s).to_set)
|
|
106
|
+
|
|
107
|
+
ar_reserved = ActiveRecord::AttributeMethods.dangerous_attribute_methods
|
|
108
|
+
|
|
109
|
+
rename_columns_mapping.each do |old_name, new_name|
|
|
110
|
+
next unless table_column_names_set.include?(old_name.to_s)
|
|
111
|
+
|
|
112
|
+
new_name = new_name.to_s
|
|
113
|
+
|
|
114
|
+
if table_column_names_set.include?(new_name) && new_name != old_name.to_s
|
|
115
|
+
warn "rename_columns: new name '#{new_name}' already exists in table '#{table_name}', skipping rename of '#{old_name}'"
|
|
116
|
+
next
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
if ar_reserved.include?(new_name)
|
|
120
|
+
raise ActiveRecord::DangerousAttributeError,
|
|
121
|
+
"rename_columns: new name '#{new_name}' is a reserved ActiveRecord method"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if ARQL_EXTENSION_INSTANCE_METHODS.include?(new_name.to_sym)
|
|
125
|
+
warn "rename_columns: new name '#{new_name}' conflicts with an arql method in table '#{table_name}', skipping rename of '#{old_name}'"
|
|
126
|
+
next
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
99
131
|
def define_model_from_table(table_name, primary_keys)
|
|
100
132
|
model_name = make_model_name(table_name)
|
|
101
133
|
return unless model_name
|
|
102
134
|
|
|
103
135
|
model_class = make_model_class(table_name, primary_keys)
|
|
136
|
+
if rename_columns_mapping.present?
|
|
137
|
+
validate_rename_columns!(table_name, model_class)
|
|
138
|
+
relevant_old_names = rename_columns_mapping.keys.select { |n| model_class.column_names.include?(n.to_s) }
|
|
139
|
+
if relevant_old_names.any?
|
|
140
|
+
model_class.define_attribute_methods
|
|
141
|
+
mod = model_class.send(:generated_attribute_methods)
|
|
142
|
+
relevant_old_names.each do |old_name|
|
|
143
|
+
old_name = old_name.to_s
|
|
144
|
+
[old_name.to_sym, :"#{old_name}=", :"#{old_name}?"].each do |m|
|
|
145
|
+
mod.send(:remove_method, m) if mod.method_defined?(m)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
104
150
|
@namespace_module.const_set(model_name, model_class)
|
|
105
151
|
abbr_name = make_model_abbr_name(model_name, table_name)
|
|
106
152
|
@namespace_module.const_set(abbr_name, model_class)
|
|
@@ -110,7 +156,7 @@ module Arql
|
|
|
110
156
|
# Object.const_set(abbr_name, model_class)
|
|
111
157
|
# end
|
|
112
158
|
|
|
113
|
-
{ model: model_class, abbr: "
|
|
159
|
+
{ model: model_class, abbr: "#{@namespace}::#{abbr_name}", table: table_name }
|
|
114
160
|
end
|
|
115
161
|
|
|
116
162
|
def make_model_abbr_name(model_name, table_name)
|
|
@@ -149,6 +195,8 @@ module Arql
|
|
|
149
195
|
|
|
150
196
|
def make_model_class(table_name, primary_keys)
|
|
151
197
|
options = @options
|
|
198
|
+
rename_columns = rename_columns_mapping
|
|
199
|
+
renamed_old_names = rename_columns.keys.map(&:to_s)
|
|
152
200
|
Class.new(@base_model) do
|
|
153
201
|
include Arql::Extension
|
|
154
202
|
if primary_keys.is_a?(Array) && primary_keys.size > 1
|
|
@@ -158,7 +206,18 @@ module Arql
|
|
|
158
206
|
end
|
|
159
207
|
self.table_name = table_name
|
|
160
208
|
self.inheritance_column = nil
|
|
209
|
+
self.ignored_columns = options[:ignored_columns] if options[:ignored_columns].present?
|
|
161
210
|
ActiveRecord.default_timezone = :local
|
|
211
|
+
|
|
212
|
+
if renamed_old_names.any?
|
|
213
|
+
define_singleton_method(:instance_method_already_implemented?) do |method_name|
|
|
214
|
+
name = method_name.to_s.sub(/[=?\z]/, '')
|
|
215
|
+
return false if renamed_old_names.include?(name)
|
|
216
|
+
|
|
217
|
+
super(method_name)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
162
221
|
if options[:created_at].present?
|
|
163
222
|
define_singleton_method :timestamp_attributes_for_create do
|
|
164
223
|
options[:created_at]
|
|
@@ -170,6 +229,26 @@ module Arql
|
|
|
170
229
|
options[:updated_at]
|
|
171
230
|
end
|
|
172
231
|
end
|
|
232
|
+
|
|
233
|
+
if rename_columns.present?
|
|
234
|
+
rename_columns.each do |old_name, new_name|
|
|
235
|
+
new_sym = new_name.to_sym
|
|
236
|
+
define_method(new_sym) { read_attribute(old_name.to_s) }
|
|
237
|
+
define_method(:"#{new_sym}=") { |value| write_attribute(old_name.to_s, value) }
|
|
238
|
+
define_method(:"#{new_sym}?") { !!read_attribute(old_name.to_s) }
|
|
239
|
+
end
|
|
240
|
+
self.attribute_aliases = rename_columns.transform_keys(&:to_sym).invert
|
|
241
|
+
|
|
242
|
+
original_inspect = instance_method(:inspect)
|
|
243
|
+
rename_columns_for_inspect = rename_columns.dup
|
|
244
|
+
define_method(:inspect) do
|
|
245
|
+
result = original_inspect.bind(self).call
|
|
246
|
+
rename_columns_for_inspect.each do |old_name, new_name|
|
|
247
|
+
result = result.sub(/\b#{Regexp.escape(old_name.to_s)}(?=:)/, new_name.to_s)
|
|
248
|
+
end
|
|
249
|
+
result
|
|
250
|
+
end
|
|
251
|
+
end
|
|
173
252
|
end
|
|
174
253
|
end
|
|
175
254
|
|
|
@@ -178,13 +257,14 @@ module Arql
|
|
|
178
257
|
Arql::SSHProxy.new(
|
|
179
258
|
ssh_config.slice(:host, :user, :port, :password)
|
|
180
259
|
.merge(forward_host: @options[:host],
|
|
181
|
-
|
|
182
|
-
|
|
260
|
+
forward_port: @options[:port],
|
|
261
|
+
local_port: ssh_config[:local_port])
|
|
262
|
+
)
|
|
183
263
|
end
|
|
184
264
|
|
|
185
265
|
def get_connection_options
|
|
186
266
|
connect_conf = @options.slice(:adapter, :host, :username, :password,
|
|
187
|
-
|
|
267
|
+
:database, :encoding, :pool, :port, :socket)
|
|
188
268
|
connect_conf.merge!(@ssh_proxy.database_host_port) if @ssh_proxy
|
|
189
269
|
connect_conf
|
|
190
270
|
end
|
|
@@ -215,8 +295,7 @@ module Arql
|
|
|
215
295
|
def create_namespace_module(namespace)
|
|
216
296
|
definition = self
|
|
217
297
|
|
|
218
|
-
Object.const_set(namespace, Module.new
|
|
219
|
-
|
|
298
|
+
Object.const_set(namespace, Module.new do
|
|
220
299
|
define_singleton_method(:config) do
|
|
221
300
|
definition.options
|
|
222
301
|
end
|
|
@@ -244,7 +323,7 @@ module Arql
|
|
|
244
323
|
define_singleton_method(:dump) do |filename, no_create_db = false|
|
|
245
324
|
Arql::Mysqldump.new(definition.options).dump_database(filename, no_create_db)
|
|
246
325
|
end
|
|
247
|
-
|
|
326
|
+
end)
|
|
248
327
|
end
|
|
249
328
|
end
|
|
250
329
|
end
|
data/lib/arql/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: arql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Liu Xiang
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: mysql2
|
|
@@ -330,6 +330,7 @@ files:
|
|
|
330
330
|
- custom-configurations.org
|
|
331
331
|
- define-associations-zh_CN.org
|
|
332
332
|
- define-associations.org
|
|
333
|
+
- docs/plans/2026-04-02-rename-columns-design.md
|
|
333
334
|
- exe/arql
|
|
334
335
|
- exe/arql_setsid_wrapper
|
|
335
336
|
- fuzzy-field-query-zh_CN.org
|