Last active
June 24, 2024 06:39
-
-
Save ziaulrehman40/6b61837627d97d3702e98209b7a214eb to your computer and use it in GitHub Desktop.
Ruby codemod: transformto rails 7.2 enum syntax with validate options to avoid argumentErrors on assignment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Transforms | |
# From: enum name: values | |
# To: enum :name, values, validate: { allow_nil: true } | |
# Also removes _ from prefix and suffix for the new syntax to avoid un-intended bugs | |
# You can modify this tranformer in transform_enum method as per your needs | |
# USAGE: | |
# 1. gem install parser | |
# 2. run this file providing a single file or parent folder like: ruby tranform_enums.rb myApp/app/models OR ruby tranform_enums.rb myApp/app/models/user.rb | |
require 'parser/current' | |
require 'find' | |
class EnumTransformer < Parser::TreeRewriter | |
def on_send(node) | |
if node.children[1] == :enum && node.children[2].type == :hash | |
replace(node.loc.expression, transform_enum(node)) | |
end | |
super(node) | |
end | |
private | |
def transform_enum(node) | |
# map name | |
name = node.children[2].children.first.children.first.children[0] | |
# map value hash/array | |
values = node.children[2].children.first.children.last.loc.expression.source | |
# map additional params | |
additionals = (node.children[2].children.slice(1..).map { _1.loc.expression.source }).join(', ') | |
# transform _prefix to prefix | |
additionals.gsub!('_prefix', 'prefix') | |
# transform _suffix to suffix | |
additionals.gsub!('_suffix', 'suffix') | |
additionals = additionals + ', ' if additionals != '' | |
"enum :#{name}, #{values}, #{additionals}validate: { allow_nil: true }" | |
end | |
end | |
def process_file(file_path) | |
puts "Checking #{file_path}" | |
buffer = Parser::Source::Buffer.new(file_path) | |
buffer.source = File.read(file_path) | |
parser = Parser::CurrentRuby.new | |
ast = parser.parse(buffer) | |
transformer = EnumTransformer.new | |
new_source = transformer.rewrite(buffer, ast) | |
File.write(file_path, new_source) | |
end | |
def process_directory(directory_path) | |
Find.find(directory_path) do |path| | |
if FileTest.directory?(path) | |
next | |
elsif path.end_with?('.rb') | |
process_file(path) | |
end | |
end | |
end | |
target_path = ARGV[0] | |
unless target_path && File.exist?(target_path) | |
puts 'Please provide a valid file or directory path.' | |
exit 1 | |
end | |
if File.directory?(target_path) | |
process_directory(target_path) | |
else | |
process_file(target_path) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
👍