Skip to content

Instantly share code, notes, and snippets.

@kuahyeow
Last active October 2, 2020 18:03
Show Gist options
  • Select an option

  • Save kuahyeow/36d5b4ac4426f4df35aebc949532ffe9 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown
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