alba_migration 0.0.5 → 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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +12 -0
- data/lib/alba_migration/snippet/attribute_rewritable.rb +110 -120
- data/lib/alba_migration/snippet/if_rewritable.rb +77 -0
- data/lib/alba_migration/snippet/superclass_rewritable.rb +6 -0
- data/lib/alba_migration/snippet/superclass_rewriter.rb +82 -0
- data/lib/alba_migration/snippet.rb +5 -2
- data/lib/alba_migration/version.rb +1 -1
- data/sig/generated/alba_migration/snippet/if_rewritable.rbs +10 -0
- data/sig/generated/alba_migration/snippet/superclass_rewriter.rbs +10 -0
- data/sig/generated/alba_migration/snippet.rbs +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4363f4b67228f48ef7986a8cfcc678ab88ed8a752809361de7aa249e0889ae52
|
4
|
+
data.tar.gz: 41947e0ad9125fcb418fe71053483dccc7b8370210fcdc9cb081571d7a524ec7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 162e777325e434a0d9ec8b6f129b7911ef75a3d62edd729c0c1e9f1623aeb8fed03c52b2d0e1f34c637da7537a980f64ca16dd1a50c01867f2d7ad42b2a4ef84
|
7
|
+
data.tar.gz: d5a5a6d48bf7b068edfd7ddf0ec9749d06a946edda20a11c759c1ff886a5168106079e08dfef9ce062b49ab4f126a70cdd266cd561d9eec086b35804e5316af9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# GHANGELOG
|
2
2
|
|
3
|
+
## 0.0.6 (2024-06-08)
|
4
|
+
|
5
|
+
- Implement if condition lambda-to-proc conversion in AMS to Alba migration
|
6
|
+
- Improve conditional attribute handling for better Alba compatibility
|
7
|
+
|
3
8
|
## 0.0.5 (2024-06-08)
|
4
9
|
|
5
10
|
- --add_on option to CLI for custom snippet support
|
data/README.md
CHANGED
@@ -39,6 +39,17 @@ If you are using Bundler:
|
|
39
39
|
bundle exec alba_migration app/serializers/**/*.rb
|
40
40
|
```
|
41
41
|
|
42
|
+
#### Custom Snippet Support (`--add_on` option)
|
43
|
+
|
44
|
+
You can specify a custom snippet Ruby file to extend or override the default migration behavior using the `--add_on` option:
|
45
|
+
|
46
|
+
```bash
|
47
|
+
alba_migration --add_on path/to/custom_snippet.rb path/to/your/serializer.rb
|
48
|
+
```
|
49
|
+
|
50
|
+
- The custom snippet file should define a Synvert rewriter object.
|
51
|
+
- This allows you to add your own migration logic in addition to the built-in conversion.
|
52
|
+
|
42
53
|
#### Example
|
43
54
|
|
44
55
|
**Before:**
|
@@ -65,6 +76,7 @@ Currently, AlbaMigration supports the following AMS syntax:
|
|
65
76
|
- `class ... < ActiveModel::Serializer` with `attributes ...` inside the class body
|
66
77
|
- Only the conversion of the class definition and `attributes` is supported at this time
|
67
78
|
- Attribute methods (e.g. `attribute :foo do ... end`) are now automatically converted
|
79
|
+
- Conditional attributes with `if` option are converted from lambda to proc syntax
|
68
80
|
- Other AMS features (e.g., associations, custom methods) are **not** yet supported
|
69
81
|
|
70
82
|
## Contributing
|
@@ -15,7 +15,7 @@ module AlbaMigration
|
|
15
15
|
Synvert::Core::Rewriter.new "alba_migration", "rewrite_attribute_method" do
|
16
16
|
description <<~EOS
|
17
17
|
It migrates ActiveModelSerializers attribute syntax to Alba attribute syntax.
|
18
|
-
|
18
|
+
|
19
19
|
Example:
|
20
20
|
|
21
21
|
# 1. Simple attribute methods grouped
|
@@ -119,6 +119,7 @@ module AlbaMigration
|
|
119
119
|
superclass_node = node.children[1]
|
120
120
|
superclass_src = superclass_node ? " < #{superclass_node.loc.expression.source}" : ""
|
121
121
|
class_body = node.children[2]
|
122
|
+
|
122
123
|
# If class_body is a :begin node, loop through its children. Otherwise, treat it as a single node in an array.
|
123
124
|
body_nodes = if class_body && class_body.type == :begin
|
124
125
|
class_body.children
|
@@ -128,56 +129,52 @@ module AlbaMigration
|
|
128
129
|
[]
|
129
130
|
end
|
130
131
|
|
131
|
-
#
|
132
|
-
|
132
|
+
# Pre-collect conversion data
|
133
|
+
attribute_blocks = {} # Conversion results for block-based attributes
|
134
|
+
attr_names = {} # Combination of attribute :name + def name
|
135
|
+
attributes_groups = {} # Grouped attributes :a, :b
|
136
|
+
def_method_names = [] # List of def method names
|
137
|
+
|
138
|
+
# 0. Pre-collect def method names
|
133
139
|
body_nodes.each do |child|
|
134
140
|
next unless child.is_a?(Parser::AST::Node)
|
135
|
-
if child.type == :
|
136
|
-
|
141
|
+
if child.type == :def
|
142
|
+
def_method_names << child.children[0].to_s
|
137
143
|
end
|
138
144
|
end
|
139
145
|
|
140
|
-
# 1
|
141
|
-
attribute_blocks = []
|
146
|
+
# 1. Collect attribute(:xxx) { ... } blocks
|
142
147
|
body_nodes.each do |child|
|
143
148
|
next unless child.is_a?(Parser::AST::Node)
|
144
149
|
if child.type == :block &&
|
145
150
|
child.children[0] && child.children[0].is_a?(Parser::AST::Node) && child.children[0].type == :send &&
|
146
151
|
child.children[0].children[1] == :attribute
|
147
152
|
|
148
|
-
# Process arguments
|
149
153
|
arg_node = child.children[0].children[2]
|
150
154
|
arg = if arg_node.is_a?(Parser::AST::Node) && arg_node.type == :sym
|
151
155
|
":#{arg_node.children[0]}"
|
152
156
|
else
|
153
|
-
|
157
|
+
arg_node.to_s
|
154
158
|
end
|
155
159
|
|
156
|
-
# Process block parameters
|
157
160
|
block_params = child.children[1] ? child.children[1].children.map { |c| c.children[0].to_s }.join(", ") : ""
|
158
|
-
|
159
|
-
# Process block body
|
160
161
|
block_body = child.children[2] ? child.children[2].loc.expression.source : ""
|
161
162
|
|
162
|
-
# Add 'object' to parameters if used in block body
|
163
163
|
if block_params.strip.empty? && block_body.include?("object")
|
164
164
|
block_params = "object"
|
165
165
|
end
|
166
166
|
|
167
|
-
|
168
|
-
|
169
|
-
"attribute #{arg} do\n#{block_body}\nend"
|
167
|
+
converted = if block_params.strip.empty?
|
168
|
+
" attribute #{arg} do\n #{block_body}\n end"
|
170
169
|
else
|
171
|
-
"attribute #{arg} do |#{block_params.strip}|\n#{block_body}\
|
170
|
+
" attribute #{arg} do |#{block_params.strip}|\n #{block_body}\n end"
|
172
171
|
end
|
172
|
+
|
173
|
+
attribute_blocks[child] = converted
|
173
174
|
end
|
174
175
|
end
|
175
176
|
|
176
|
-
#
|
177
|
-
attr_names = {}
|
178
|
-
other_methods = []
|
179
|
-
|
180
|
-
# First, collect attribute :name
|
177
|
+
# 2. Collect attribute :name + def name combinations
|
181
178
|
body_nodes.each do |child|
|
182
179
|
next unless child.is_a?(Parser::AST::Node)
|
183
180
|
if child.type == :send &&
|
@@ -187,141 +184,134 @@ module AlbaMigration
|
|
187
184
|
child.children[2].type == :sym
|
188
185
|
|
189
186
|
attr_name = child.children[2].children[0].to_s
|
190
|
-
attr_names[attr_name] =
|
187
|
+
attr_names[attr_name] = child
|
191
188
|
end
|
192
189
|
end
|
193
190
|
|
194
|
-
#
|
195
|
-
|
196
|
-
attributes_methods = {}
|
191
|
+
# 3. Process attributes :a, :b grouping
|
192
|
+
standalone_attributes = []
|
197
193
|
body_nodes.each do |child|
|
198
194
|
next unless child.is_a?(Parser::AST::Node)
|
199
|
-
# attribute :xxx
|
200
195
|
if child.type == :send && child.children[1] == :attribute && child.children.length == 3 && child.children[2].is_a?(Parser::AST::Node) && child.children[2].type == :sym
|
201
196
|
method_name = child.children[2].children[0].to_s
|
202
197
|
unless body_nodes.any? { |c| c.is_a?(Parser::AST::Node) && c.type == :def && c.children[0].to_s == method_name }
|
203
|
-
|
198
|
+
standalone_attributes << ":#{method_name}"
|
204
199
|
end
|
205
|
-
# attributes :xxx, :yyy, ...
|
206
200
|
elsif child.type == :send && child.children[1] == :attributes
|
207
|
-
|
208
|
-
if child.children.length == 3 && child.children[2].is_a?(Parser::AST::Node)
|
201
|
+
if child.children.length >= 3 && child.children[2].is_a?(Parser::AST::Node)
|
209
202
|
arg_node = child.children[2]
|
203
|
+
attrs_from_this_node = []
|
210
204
|
if arg_node.type == :array
|
211
205
|
syms = arg_node.children.select { |n| n.is_a?(Parser::AST::Node) && n.type == :sym }
|
212
|
-
syms.each { |sym_node|
|
206
|
+
syms.each { |sym_node| attrs_from_this_node << ":#{sym_node.children[0]}" }
|
213
207
|
elsif arg_node.type == :sym_array
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
child.children[2..].each do |a|
|
221
|
-
if a.is_a?(Parser::AST::Node) && a.type == :sym
|
222
|
-
method_name = a.children[0].to_s
|
223
|
-
def_node = body_nodes.find { |c| c.is_a?(Parser::AST::Node) && c.type == :def && c.children[0].to_s == method_name }
|
224
|
-
if def_node
|
225
|
-
method_body = def_node.children[2]
|
226
|
-
method_src = method_body ? method_body.loc.expression.source : ""
|
227
|
-
attributes_methods[method_name] = "attribute :#{method_name} do |object|\n#{method_src}\nend"
|
228
|
-
else
|
229
|
-
attributes_group << ":#{method_name}"
|
208
|
+
arg_node.children.each { |sym_lit| attrs_from_this_node << ":#{sym_lit}" }
|
209
|
+
else
|
210
|
+
# For multiple arguments case (attributes :a, :b)
|
211
|
+
child.children[2..].each do |arg|
|
212
|
+
if arg.is_a?(Parser::AST::Node) && arg.type == :sym
|
213
|
+
attrs_from_this_node << ":#{arg.children[0]}"
|
230
214
|
end
|
231
215
|
end
|
232
216
|
end
|
217
|
+
|
218
|
+
# Keep only those not converted by def methods
|
219
|
+
remaining_attrs = attrs_from_this_node.reject do |attr_name|
|
220
|
+
method_name = attr_name[1..] # Remove :
|
221
|
+
def_method_names.include?(method_name)
|
222
|
+
end
|
223
|
+
|
224
|
+
attributes_groups[child] = remaining_attrs
|
233
225
|
end
|
234
226
|
end
|
235
227
|
end
|
236
228
|
|
237
|
-
#
|
229
|
+
# Main processing: process body_nodes sequentially
|
238
230
|
new_lines = ["class #{class_name}#{superclass_src}"]
|
239
231
|
|
240
|
-
# Add include Alba::Resource first if present
|
241
|
-
if include_line
|
242
|
-
new_lines << include_line
|
243
|
-
new_lines << ""
|
244
|
-
end
|
245
|
-
|
246
|
-
# Add attributes group after include
|
247
|
-
unless attributes_group.empty?
|
248
|
-
new_lines << " attributes #{attributes_group.join(", ")}"
|
249
|
-
new_lines << ""
|
250
|
-
end
|
251
|
-
|
252
|
-
# Add attribute blocks (no extra blank lines)
|
253
|
-
new_lines.concat(attribute_blocks)
|
254
|
-
|
255
|
-
# Convert attribute :name + def name ... end pairs
|
256
|
-
attributeized_method_names = []
|
257
232
|
body_nodes.each do |child|
|
258
233
|
next unless child.is_a?(Parser::AST::Node)
|
259
|
-
next unless child.type == :def
|
260
|
-
method_name = child.children[0].to_s
|
261
|
-
method_body = child.children[2]
|
262
|
-
method_src = method_body ? method_body.loc.expression.source : ""
|
263
|
-
# attribute :name + def name ... end
|
264
|
-
if attr_names.key?(method_name)
|
265
|
-
attr_names[method_name] = "attribute :#{method_name} do |object|\n#{method_src}\nend"
|
266
|
-
attributeized_method_names << method_name
|
267
|
-
attributes_group.delete(":#{method_name}")
|
268
|
-
next
|
269
|
-
end
|
270
|
-
# attributes :name + def name ... end
|
271
|
-
if attributes_methods.key?(method_name)
|
272
|
-
new_lines << attributes_methods[method_name]
|
273
|
-
attributeized_method_names << method_name
|
274
|
-
attributes_group.delete(":#{method_name}")
|
275
|
-
next
|
276
|
-
end
|
277
|
-
# def name ... object.xxx ... end
|
278
|
-
if method_src.strip.start_with?("object.")
|
279
|
-
new_lines << "attribute :#{method_name} do |object|\n#{method_src}\nend"
|
280
|
-
attributeized_method_names << method_name
|
281
|
-
attributes_group.delete(":#{method_name}")
|
282
|
-
next
|
283
|
-
end
|
284
|
-
# def accounts ... object.account_id ... end (plural method names are converted as-is to attribute)
|
285
|
-
if method_name.end_with?("s") && method_body
|
286
|
-
new_lines << "attribute :#{method_name} do |object|\n#{method_src}\nend"
|
287
|
-
attributeized_method_names << method_name
|
288
|
-
attributes_group.delete(":#{method_name}")
|
289
|
-
next
|
290
|
-
end
|
291
|
-
# All other methods go to other_methods (excluding those already converted to attribute)
|
292
|
-
unless attributeized_method_names.include?(method_name)
|
293
|
-
method_src_full = child.loc.expression.source
|
294
|
-
other_methods << method_src_full
|
295
|
-
end
|
296
|
-
end
|
297
234
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
235
|
+
case child.type
|
236
|
+
when :send
|
237
|
+
if child.children[1] == :include
|
238
|
+
# include Alba::Resource
|
239
|
+
new_lines << " " + child.loc.expression.source
|
240
|
+
new_lines << ""
|
241
|
+
elsif child.children[1] == :attribute && child.children.length == 3 && child.children[2].is_a?(Parser::AST::Node) && child.children[2].type == :sym
|
242
|
+
# attribute :xxx
|
243
|
+
method_name = child.children[2].children[0].to_s
|
244
|
+
def_exists = body_nodes.any? { |c| c.is_a?(Parser::AST::Node) && c.type == :def && c.children[0].to_s == method_name }
|
245
|
+
|
246
|
+
if def_exists
|
247
|
+
# Do nothing if def method exists (convert at def processing)
|
248
|
+
next
|
249
|
+
elsif child.children.length > 3
|
250
|
+
# Unsupported attribute with options
|
251
|
+
new_lines << " " + child.loc.expression.source
|
252
|
+
else
|
253
|
+
# Output as standalone attribute grouping (only once)
|
254
|
+
unless standalone_attributes.empty?
|
255
|
+
new_lines << " attributes #{standalone_attributes.join(", ")}"
|
256
|
+
new_lines << ""
|
257
|
+
standalone_attributes.clear
|
258
|
+
end
|
259
|
+
end
|
260
|
+
elsif child.children[1] == :attributes
|
261
|
+
# attributes :xxx, :yyy, ...
|
262
|
+
if attributes_groups[child]
|
263
|
+
unless attributes_groups[child].empty?
|
264
|
+
new_lines << " attributes #{attributes_groups[child].join(", ")}"
|
265
|
+
new_lines << ""
|
266
|
+
end
|
267
|
+
else
|
268
|
+
# Unsupported attributes syntax
|
269
|
+
new_lines << " " + child.loc.expression.source
|
270
|
+
end
|
271
|
+
else
|
272
|
+
# Other method calls (including unsupported syntax)
|
273
|
+
new_lines << " " + child.loc.expression.source
|
274
|
+
end
|
275
|
+
|
276
|
+
when :block
|
277
|
+
new_lines << (attribute_blocks[child] || " " + child.loc.expression.source)
|
278
|
+
|
279
|
+
when :def
|
280
|
+
method_name = child.children[0].to_s
|
281
|
+
method_body = child.children[2]
|
282
|
+
method_src = method_body ? method_body.loc.expression.source : ""
|
283
|
+
|
284
|
+
if attr_names.key?(method_name)
|
285
|
+
# Convert attribute :name + def name
|
286
|
+
new_lines << " attribute :#{method_name} do |object|"
|
287
|
+
new_lines << " #{method_src}"
|
288
|
+
new_lines << " end"
|
289
|
+
elsif method_src.strip.start_with?("object.") || (method_name.end_with?("s") && method_body)
|
290
|
+
# Convert def methods containing object.xxx
|
291
|
+
new_lines << " attribute :#{method_name} do |object|"
|
292
|
+
new_lines << " #{method_src}"
|
293
|
+
new_lines << " end"
|
294
|
+
else
|
295
|
+
# Non-convertible def methods
|
296
|
+
new_lines << " " + child.loc.expression.source
|
297
|
+
end
|
298
|
+
|
299
|
+
else
|
300
|
+
# Other nodes
|
301
|
+
new_lines << " " + child.loc.expression.source
|
307
302
|
end
|
308
303
|
end
|
309
|
-
new_lines.concat(attr_blocks)
|
310
|
-
# Add other methods (def not corresponding to attribute) (no extra blank lines)
|
311
|
-
filtered_other_methods = other_methods.reject do |src|
|
312
|
-
attributeized_method_names.any? { |name| src.match?(/def\s+#{name}\b/) }
|
313
|
-
end
|
314
|
-
new_lines.concat(filtered_other_methods)
|
315
304
|
|
316
305
|
new_lines << "end"
|
317
306
|
|
318
|
-
# Remove consecutive blank lines
|
307
|
+
# Remove consecutive blank lines
|
319
308
|
final_code = new_lines.each_with_object([]) do |line, arr|
|
320
309
|
if line.strip.empty? && arr.last&.strip&.empty?
|
321
310
|
next
|
322
311
|
end
|
323
312
|
arr << line
|
324
313
|
end.join("\n")
|
314
|
+
|
325
315
|
replace_with final_code
|
326
316
|
end
|
327
317
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
5
|
+
require "synvert/core"
|
6
|
+
require "standard"
|
7
|
+
|
8
|
+
module AlbaMigration
|
9
|
+
class Snippet
|
10
|
+
module IfRewritable
|
11
|
+
# @rbs return: Synvert::Core::Rewriter
|
12
|
+
def if_rewriter
|
13
|
+
migrate_file_path = @migrate_file_path
|
14
|
+
|
15
|
+
Synvert::Core::Rewriter.new "alba_migration", "rewrite_if" do
|
16
|
+
description <<~EOS
|
17
|
+
It migrates if syntax to Alba syntax.
|
18
|
+
|
19
|
+
Example:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class AttributesResource < ActiveModel::Serializer
|
23
|
+
attributes :id, if: -> { true }
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
=>
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class AttributesResource
|
31
|
+
include Alba::Resource
|
32
|
+
|
33
|
+
attributes :id, if: proc { true }
|
34
|
+
end
|
35
|
+
```
|
36
|
+
EOS
|
37
|
+
|
38
|
+
configure(parser: "prism")
|
39
|
+
|
40
|
+
within_files migrate_file_path do
|
41
|
+
# Convert lambda syntax to proc syntax in if option
|
42
|
+
with_node node_type: "lambda_node" do
|
43
|
+
body_src = node.body ? node.body.to_source : ""
|
44
|
+
replace_with "proc { #{body_src} }"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Convert attribute method to attributes method only if it has an if condition
|
48
|
+
with_node node_type: "call_node", receiver: nil, message: "attribute" do
|
49
|
+
# Check if this attribute call has an 'if' argument
|
50
|
+
has_if_option = false
|
51
|
+
if node.arguments&.arguments
|
52
|
+
node.arguments.arguments.each do |arg|
|
53
|
+
if arg.type == :keyword_hash_node && arg.elements
|
54
|
+
arg.elements.each do |element|
|
55
|
+
if element.type == :assoc_node && element.key.type == :symbol_node && element.key.unescaped == "if"
|
56
|
+
has_if_option = true
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
if has_if_option
|
65
|
+
# Get all arguments
|
66
|
+
args = node.arguments ? node.arguments.arguments.map(&:to_source).join(", ") : ""
|
67
|
+
replace_with "attributes #{args}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Standard::Cli.new(["--fix", Array(migrate_file_path).join(" ")]).run
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -42,6 +42,12 @@ module AlbaMigration
|
|
42
42
|
body_src = node.body ? node.body.to_source : ""
|
43
43
|
replace_with "class #{node.constant_path.to_source}\ninclude Alba::Resource\n\n#{body_src}\nend"
|
44
44
|
end
|
45
|
+
|
46
|
+
# Convert lambda syntax to proc syntax in if option
|
47
|
+
with_node node_type: "lambda_node" do
|
48
|
+
body_src = node.body ? node.body.to_source : ""
|
49
|
+
replace_with "proc { #{body_src} }"
|
50
|
+
end
|
45
51
|
end
|
46
52
|
|
47
53
|
Standard::Cli.new(["--fix", Array(migrate_file_path).join(" ")]).run
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
5
|
+
require "synvert/core"
|
6
|
+
require "standard"
|
7
|
+
|
8
|
+
module AlbaMigration
|
9
|
+
class Snippet
|
10
|
+
module SuperclassRewritable
|
11
|
+
# @rbs return: Synvert::Core::Rewriter
|
12
|
+
def superclass_rewriter
|
13
|
+
migrate_file_path = @migrate_file_path
|
14
|
+
|
15
|
+
Synvert::Core::Rewriter.new "alba_migration", "rewrite_superclass" do
|
16
|
+
description <<~EOS
|
17
|
+
It migrates ActiveModelSerializers syntax to Alba syntax.
|
18
|
+
|
19
|
+
Example:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class AttributesResource < ActiveModel::Serializer
|
23
|
+
attributes :id, :name
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
=>
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class AttributesResource
|
31
|
+
include Alba::Resource
|
32
|
+
|
33
|
+
attributes :id, :name
|
34
|
+
end
|
35
|
+
```
|
36
|
+
EOS
|
37
|
+
|
38
|
+
configure(parser: "prism")
|
39
|
+
|
40
|
+
within_files migrate_file_path do
|
41
|
+
with_node node_type: "class_node", superclass: "ActiveModel::Serializer" do
|
42
|
+
body_src = node.body ? node.body.to_source : ""
|
43
|
+
replace_with "class #{node.constant_path.to_source}\ninclude Alba::Resource\n\n#{body_src}\nend"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Convert lambda syntax to proc syntax in if option
|
47
|
+
with_node node_type: "lambda_node" do
|
48
|
+
body_src = node.body ? node.body.to_source : ""
|
49
|
+
replace_with "proc { #{body_src} }"
|
50
|
+
end
|
51
|
+
|
52
|
+
# Convert attribute method to attributes method only if it has an if condition
|
53
|
+
with_node node_type: "call_node", receiver: nil, message: "attribute" do
|
54
|
+
# Check if this attribute call has an 'if' argument
|
55
|
+
has_if_option = false
|
56
|
+
if node.arguments&.arguments
|
57
|
+
node.arguments.arguments.each do |arg|
|
58
|
+
if arg.type == :keyword_hash_node && arg.elements
|
59
|
+
arg.elements.each do |element|
|
60
|
+
if element.type == :assoc_node && element.key.type == :symbol_node && element.key.unescaped == "if"
|
61
|
+
has_if_option = true
|
62
|
+
break
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if has_if_option
|
70
|
+
# Get all arguments
|
71
|
+
args = node.arguments ? node.arguments.arguments.map(&:to_source).join(", ") : ""
|
72
|
+
replace_with "attributes #{args}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
Standard::Cli.new(["--fix", Array(migrate_file_path).join(" ")]).run
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
# rbs_inline: enabled
|
4
4
|
|
5
|
-
require_relative "snippet/superclass_rewritable"
|
6
5
|
require_relative "snippet/attribute_rewritable"
|
6
|
+
require_relative "snippet/if_rewritable"
|
7
|
+
require_relative "snippet/superclass_rewritable"
|
7
8
|
|
8
9
|
module AlbaMigration
|
9
10
|
class Snippet
|
10
11
|
include SuperclassRewritable
|
11
12
|
include AttributeRewritable
|
13
|
+
include IfRewritable
|
12
14
|
|
13
15
|
# @rbs migrate_file_path: String
|
14
16
|
# @rbs return: Array[Synvert::Core::Rewriter]
|
@@ -16,7 +18,8 @@ module AlbaMigration
|
|
16
18
|
snippet_creator = new(migrate_file_path:)
|
17
19
|
[
|
18
20
|
snippet_creator.superclass_rewriter,
|
19
|
-
snippet_creator.attribute_method_rewriter
|
21
|
+
snippet_creator.attribute_method_rewriter,
|
22
|
+
snippet_creator.if_rewriter
|
20
23
|
]
|
21
24
|
end
|
22
25
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Generated from lib/alba_migration/snippet/superclass_rewriter.rb with RBS::Inline
|
2
|
+
|
3
|
+
module AlbaMigration
|
4
|
+
class Snippet
|
5
|
+
module SuperclassRewritable
|
6
|
+
# @rbs return: Synvert::Core::Rewriter
|
7
|
+
def superclass_rewriter: () -> Synvert::Core::Rewriter
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alba_migration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ShoheiMitani
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: synvert-core
|
@@ -69,13 +69,17 @@ files:
|
|
69
69
|
- lib/alba_migration/cli.rb
|
70
70
|
- lib/alba_migration/snippet.rb
|
71
71
|
- lib/alba_migration/snippet/attribute_rewritable.rb
|
72
|
+
- lib/alba_migration/snippet/if_rewritable.rb
|
72
73
|
- lib/alba_migration/snippet/superclass_rewritable.rb
|
74
|
+
- lib/alba_migration/snippet/superclass_rewriter.rb
|
73
75
|
- lib/alba_migration/version.rb
|
74
76
|
- sig/generated/alba_migration.rbs
|
75
77
|
- sig/generated/alba_migration/cli.rbs
|
76
78
|
- sig/generated/alba_migration/snippet.rbs
|
77
79
|
- sig/generated/alba_migration/snippet/attribute_rewritable.rbs
|
80
|
+
- sig/generated/alba_migration/snippet/if_rewritable.rbs
|
78
81
|
- sig/generated/alba_migration/snippet/superclass_rewritable.rbs
|
82
|
+
- sig/generated/alba_migration/snippet/superclass_rewriter.rbs
|
79
83
|
- sig/generated/alba_migration/version.rbs
|
80
84
|
homepage: https://github.com/ShoheiMitani/alba_migration
|
81
85
|
licenses:
|