We debugged a fun one today.
There’s a method provided by Rails called tag, and it provides a way to write HTML tags.
We were using it like this:
def react_component(component_name, props, options = {})
tag.div({
data: {
react_component: component_name,
props: props.to_json,
}
}.merge(options)) { "" }
end
Did you spot the bug? We didn’t for a while. The symptom was that we were seeing completely blank <div></div> tag, when we were expecting them to have at least the data attributes populated.
The issue here has to do with how Ruby 3 has changed how it processes keyword arguments. In Ruby 2.7, the argument passed to react_component was interpreted as keyword arguments. In Ruby 3, it’s interpreted as a regular argument, where the value of that argument is a Hash object.
This means that when the TagHelper#method_missing method is called in Action View, the parameters of this are:
called: “div”*args:[{data: { react_component: component_name, props: props.to_json }}]`**options: {}
The fix for this is to tell Ruby that we mean to use keyword arguments here, rather than a Hash argument:
def react_component(component_name, props, options = {})
react_options = {
data: {
react_component: component_name,
props: props.to_json,
}
}.merge(options)
tag.div(**react_options) { "" }
end