4

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:

  1. 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.

  2. 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.

  3. (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:

  • Config file: raise error on unpermitted parameters, not present in either repository.
  • .gitignore, for any config file that may have been overlooked when changing repository
  • the HTML IDs for the turbo frame, they're all present as far as I can tell. Though I might be wrong on this one, I'm new to turbo-rails. I've been focusing on the unpermitted params error.

Any ideas for anything I should check? Even long shots are welcome because I'm thoroughly stumped. Thank you!

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Camila
  • 41
  • 4
  • 2
    `create_filter` calls `index` (not shown). Additionally `:sort_col, :sort_dir, filter: {}` are only permitted in `filter_params` not in `filter_projects` which appears to be what is being called based on your output. – engineersmnky May 05 '23 at 15:07
  • Thank you for the idea, I'll definitely be checking it out. However, it wouldn't explain why it worked before, would it? – Camila May 06 '23 at 22:47
  • So your comment gave me an idea, and I checked the index action... Where I found the problem. A respond_to that redirected to another section of the app with an unless statement. Placing the unless before the respond_to fixed the entire issue. Thank you so much for your input, it pointed me in the right direction! – Camila May 08 '23 at 13:20
  • 2
    Welcome to Stack Overflow! Please don't add "solved" to your question title or body. See [what should I do when someone answers](https://stackoverflow.com/help/someone-answers) on how to show you've solved your problem. If you found your own answer, great! Do add it as such. [Answering your own question is allowed and even encouraged](https://stackoverflow.com/help/self-answer). – Adriaan May 08 '23 at 13:31

2 Answers2

2

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.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Chiperific
  • 4,428
  • 3
  • 21
  • 41
0

Engineersmnky's comment gave me an idea, and I checked the index action... Where I found the problem. A respond_to that redirected to another section of the app with an unless statement. Placing the unless before the respond_to fixed the entire issue.

Camila
  • 41
  • 4