In the episode upgrade rails 4.2 to 5.0 part 3, we convert the usage of after_commit
with on: :create
to after_create_commit
using the following Synvert snippet:
Synvert::Rewriter.new 'rails', 'use_after_commit_alias' do
if_gem 'activerecord', '>= 5.0'
within_files 'app/models/**/*.rb' do
with_node node_type: 'send', receiver: nil, message: 'after_commit',
arguments: { size: 2, '1': { node_type: 'hash', on_value: { in: %i[create update destroy] } } } do
delete 'arguments.1.on_pair', and_comma: true
replace :message, with: 'after_{{arguments.1.on_value}}_commit'
end
end
end
When you search in the VSCode Synvert extension, you will see two actions.
The first action is to replace after_commit
with after_create_commit
, and the second action is to delete on: :create
. Performing these actions one after the other can be cumbersome and may lead to mistakes.
To simplify this process, we introduced a new group
DSL. This group
groups multiple actions into a single group, allowing you to execute them in one click. Here’s how the modified snippet looks:
Synvert::Rewriter.new 'rails', 'use_after_commit_alias' do
if_gem 'activerecord', '>= 5.0'
within_files 'app/models/**/*.rb' do
with_node node_type: 'send', receiver: nil, message: 'after_commit',
arguments: { size: 2, '1': { node_type: 'hash', on_value: { in: %i[create update destroy] } } } do
group do
delete 'arguments.1.on_pair', and_comma: true
replace :message, with: 'after_{{arguments.1.on_value}}_commit'
end
end
end
end
With this modification, you can now apply both the replace and delete actions with a single click, making the process more efficient.
The grouping functionality also applies to JavaScript snippets. For instance, consider the following snippet that converts the usage of <div className="container"></div>
to <Container></Container>
:
new Synvert.Rewriter("group", "name", () => {
configure({ parser: Synvert.Parser.TYPESCRIPT });
withinFiles("**/*.jsx", () => {
withNode({ nodeType: "JsxElement", openingElement: { nodeType: "JsxOpeningElement", tagName: "div", attributes: { nodeType: "JsxAttributes", properties: { 0: { nodeType: "JsxAttribute", name: "className", initializer: { nodeType: "StringLiteral", text: "container" } }, length: 1 } } }, closingElement: { nodeType: "JsxClosingElement", tagName: "div" } }, () => {
replace("closingElement", { with: "</Container>" });
replace("openingElement", { with: "<Container>" });
});
});
});
The search results include two actions: one for replacing closing element </div>
with </Container>
and the other for replacing opening element <div className="container">
with <Container>
.
To simplify and group these two actions, you can use the group
function:
new Synvert.Rewriter("group", "name", () => {
configure({ parser: Synvert.Parser.TYPESCRIPT });
withinFiles("**/*.jsx", () => {
withNode({ nodeType: "JsxElement", openingElement: { nodeType: "JsxOpeningElement", tagName: "div", attributes: { nodeType: "JsxAttributes", properties: { 0: { nodeType: "JsxAttribute", name: "className", initializer: { nodeType: "StringLiteral", text: "container" } }, length: 1 } } }, closingElement: { nodeType: "JsxClosingElement", tagName: "div" } }, () => {
group(() => {
replace("closingElement", { with: "</Container>" });
replace("openingElement", { with: "<Container>" });
});
});
});
});
With this modification, you can now apply both the replace actions with a single click.
Share this post