Skip to content

Instantly share code, notes, and snippets.

@kuahyeow
Last active October 2, 2020 18:03
Show Gist options
  • Save kuahyeow/36d5b4ac4426f4df35aebc949532ffe9 to your computer and use it in GitHub Desktop.
Save kuahyeow/36d5b4ac4426f4df35aebc949532ffe9 to your computer and use it in GitHub Desktop.
a rewriter to upgrade to Rails 5.1 style controller test actions
=begin
USAGE: ruby-rewrite -l controller_actions_keyword_args.rb -m <FILE>
This rewriter moves your Rails controller tests from `get action, params, session, flash` to
`get action, params: params, session: session, flash: flash`.
Which is needed if you see the following message in your Rails 5.0 tests :
DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated,
in favor of keyword arguments, and will be removed in Rails 5.1.
Deprecated style:
get :show, { id: 1 }, nil, { notice: "This is a flash message" }
New keyword style:
get :show, params: { id: 1 }, flash: { notice: "This is a flash message" },
session: nil # Can safely be omitted.
=end
class ControllerActionsKeywordArgs < Parser::Rewriter
CONTROLLER_TEST_ACTIONS = %i(get post put patch delete head)
def on_send(node)
rewrite_controller_test_action(node)
write_out_xhr_test_calls(node)
super
end
def rewrite_controller_test_action(node)
receiver_node, method_name, *arg_nodes = *node
if receiver_node.nil? && CONTROLLER_TEST_ACTIONS.include?(method_name)
action, *further_args = arg_nodes
unless kwarg_request?(further_args)
parameters, session, flash = further_args
transform_into_kwarg(parameters, "params") if parameters
transform_into_kwarg(session, "session") if session
transform_into_kwarg(flash, "flash") if flash
end
end
end
def write_out_xhr_test_calls(node)
receiver_node, method_name, *arg_nodes = *node
if receiver_node.nil? && %i(xhr xml_http_request).include?(method_name)
http_method, action, *further_args = arg_nodes
http_method_name = http_method.children[0]
range = Parser::Source::Range.new(node.loc.expression.source_buffer, node.loc.expression.begin_pos, action.loc.expression.begin_pos)
replace(range, http_method_name.to_s + " ")
unless kwarg_request?(further_args)
parameters, session, flash = further_args
transform_into_kwarg(parameters, "params") if parameters
transform_into_kwarg(session, "session") if session
transform_into_kwarg(flash, "flash") if flash
end
end
#TODO Add `xhr: true` at the end of the statement
end
protected
def transform_into_kwarg(node, keyword)
if node.type == :hash && !node.loc.expression.source.match(/\A{.*}\z/m)
insert_before node.loc.expression, "#{keyword}: {"
insert_after node.loc.expression, "}"
else
insert_before node.loc.expression, "#{keyword}: "
end
end
REQUEST_KWARGS = %i(params session flash method body xhr)
FORMAT_KWARGS = %i(format as)
def kwarg_request?(args)
return true if args.empty?
return false unless args.size == 1 && args[0].type == :hash
hash = args[0]
hash_pairs = hash.children
hash_keys = hash_pairs.map{|n| n.children.first}.flat_map(&:children)
hash_keys.all? { |k| FORMAT_KWARGS.include?(k) } ||
hash_keys.any? { |k| REQUEST_KWARGS.include?(k) }
end
end
@kuahyeow
Copy link
Author

kuahyeow commented Nov 5, 2017

Needs attention to local variables. Do remember to transform them to something that the view can assess. The traditional way is @instance_var

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment