Skip to content

Instantly share code, notes, and snippets.

@kuahyeow
Created November 8, 2017 08:11
Show Gist options
  • Save kuahyeow/0a83a85a66dfc88aaa7f2287d3b91f1c to your computer and use it in GitHub Desktop.
Save kuahyeow/0a83a85a66dfc88aaa7f2287d3b91f1c to your computer and use it in GitHub Desktop.
Extracts `render :update` blocks from controllers
require 'parser/current'
class ExtractRenderUpdate < Parser::Rewriter
attr_reader :current_action
attr_reader :extracted_sources
def on_block(node)
replace_with_render_file(node)
super
end
def on_def(node)
@current_action = node.children.first
super
end
protected
def replace_with_render_file(node)
if render_update?(node.children.first)
@extracted_sources ||= {}
raise "Action #{current_action} already taken !" if @extracted_sources[current_action]
@extracted_sources[current_action] = node.children[2..-1].map{|p| p.loc.expression.source}.join("\n")
replace(node.loc.expression, "render")
end
end
def render_update?(node)
receiver, method_name, *args = *node
receiver.nil? && method_name == :render && args[0] && args[0].to_a[0] == :update
end
end
filepaths = ARGV
filepaths.each do |filepath|
view_folderpath = filepath.sub('controllers', 'views').sub('_controller.rb', '')
raise "#{view_folderpath} does not exist" unless Dir.exists?(view_folderpath)
# find the action and the render :update or render(:update)
# extract the block,
# put it into a new file called action.rjs
# replace with a call to render the file
buffer = Parser::Source::Buffer.new(filepath).read
parser = Parser::CurrentRuby.new
ast = parser.parse(buffer)
rewriter = ExtractRenderUpdate.new
rewritten_source = rewriter.rewrite(buffer, ast)
rewriter.extracted_sources.each do |action, source|
view_filepath = File.join(view_folderpath, "#{action}.js.erb")
puts "File #{view_filepath} already exists!" if File.exists?(view_filepath)
File.open(view_filepath, 'w+') {|f| f << source}
end
File.open(filepath, 'w') {|f| f << rewritten_source}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment