I found a bug in a feature someone else made in a project I was hired to help with. The programmer who did this is unavailable, and I found nothing on the internet about this error, so I'm hoping someone here has ideas on what could be the problem.
The models involved are Project and ProjectFilter. A ProjectFilter is created via a turbo dropdown to (as the name suggests) filter existing projects according to the user's need.
Projects Controller:
def new_filter
@filter = ProjectFilter.new filter_params
respond_to do |format|
format.html { render layout: nil }
end
end
def create_filter
index
end
private
def filter_params
p = params.permit(:sort_col, :sort_dir, filter: {})
p.except(:filter).merge(p[:filter])
end
def filter_and_sort
@projects_before_filtering = @projects
filter_projects
sort_projects
end
def filter_projects
@filter = params[:filter]&.permit(:area_id, :vision, :country_code, :progress) || {}
@filter.reject! { |_k, v| v.blank? }
@projects = ProjectFilter.new(@filter).filter(@projects)
end
Here are some screenshots of how it's supposed to work:
All projects & dropdown
One filter
Two filters
The screenshots belong to a previous version of the current repository (the project was put on hold a few months ago and when it restarted, the company ditched the old repository and uploaded a new copy for some reason I'm not privy to). In this old version, the feature works. But even rollbacking to the first upload of the new one, it doesn't.
I checked the code in both repositories and found absolutely zero differences in any of the files that concern this feature: models, controller, views, even the config files.
Given this context, here comes the problem:
In the current repository, when trying to use the feature, three things happen that shouldn't be happening:
When clicking on any of the attributes of the dropdown to filter, the dropdown disappears and refuses to re-appear. Clicking the "Filters" button doesn't re-draw the dropdown. It doesn't create the filter, either.
In the Chrome console, I get a Response has no matching <turbo-frame id="filter"> element error, despite the existence of a HTML element with a id="filter" for turbo to target.
(This is the one I'm most concerned about) When clicking on any of the attributes to create a filter, I get this error in the rails server console:
Unpermitted parameters: :authenticity_token, :sort_col, :sort_dir, :filter.
Context: { controller: ProjectsController, action: create_filter, request:
#<ActionDispatch::Request:0x00007f944a714130>, params: {"authenticity_token"=>"[FILTERED]",
"sort_col"=>"", "sort_dir"=>"", "filter"=>{"vision"=>"startup", "area_id"=>"",
"country_code"=>"", "progress"=>""}, "controller"=>"projects", "action"=>"create_filter"} }
despite the params being permitted, as shown in the controller above. And how can the authenticity token be unpermitted?? Isn't that automatically permitted?
Placing a debugger in the create_filter action, below index , I got these results:
params:
#<ActionController::Parameters {"authenticity_token"=>"[FILTERED]", "sort_col"=>"",
"sort_dir"=>"", "filter"=>#<ActionController::Parameters {"vision"=>"startup", "area_id"=>"",
"country_code"=>"", "progress"=>""} permitted: false>, "controller"=>"projects",
"action"=>"create_filter"} permitted: false>
@filter:
#<ActionController::Parameters {"vision"=>"startup"} permitted: true>
Which are absolutely identical to the results of the same debugger queries in the old repository. And yet, the feature works in the old one but not in the new one.
Things I already checked:
Any ideas for anything I should check? Even long shots are welcome because I'm thoroughly stumped. Thank you!
This isn't a full answer, but I think I'm seeing a few places you can poke around.
I checked the code in both repositories and found absolutely zero differences in any of the files that concern this feature: models, controller, views, even the config files.
Compare the gemfile and gemfile.lock files. I bet you'll see breaking version changes on Turbolinks and/or Hotwire.
Also compare javascript files, it seems like the project might have switched from Turbolinks to Hotwire's Turbo at some point.
In the Chrome console, I get a Response has no matching element error, despite the existence of a HTML element with a id="filter" for turbo to target.
It can't just be any HTML element with an id="filter", it has to be a <turbo-frame> element. This is probably the reason for this issue:
When clicking on any of the attributes of the dropdown to filter, the dropdown disappears and refuses to re-appear. Clicking the "Filters" button doesn't re-draw the dropdown. It doesn't create the filter, either.
And it's not apparent because I'm guessing the project was upgraded from the old Turbolinks which used UJS tags on normal HTML elements to Hotwire's Turbo which expects specialized DOM elements (check out Hotwire if you're not familiar with it)
As to the un-permitted parameters, @engineersmnky is absolutely right, you're assuming params are permitted because you are seeing them permitted in #filter_params. But that's not the method being called:
def filter_and_sort
@projects_before_filtering = @projects
filter_projects #<- doesn't permit :authenticity_token, :sort_col, :sort_dir, :filter
sort_projects #<- not shown in your code
end
It's hard to debug further without any view or JS code, and the rest of the controller but hopefully this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With