Skip to content

Smart field searching broken in rails 7.2.2 #703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jordanell opened this issue Dec 4, 2024 · 3 comments
Open

Smart field searching broken in rails 7.2.2 #703

jordanell opened this issue Dec 4, 2024 · 3 comments

Comments

@jordanell
Copy link
Contributor

jordanell commented Dec 4, 2024

Expected behavior

Following this documentation https://docs.forestadmin.com/documentation/reference-guide/smart-fields#searching-sorting-and-filtering-on-a-smart-field should produce the expected results as outline in the docs.

Actual behavior

However, after upgrading to Rails 7.2.2 and ForestLiana 9.5.4 it won't work.

I believe what has happened is Rails 7.2 changed the way some of their internal APIs work and broke the way forest was doing this custom searching with the ActiveRecord::Relation::WhereClause predicates. I guess this is the risk of trying to manipulate internal APIs to begin with, you are subject to their breaking changes.

Failure Logs

I've modified the documentation example to show logging to show that the query is not being edited as predicted.

search_fullname = lambda do |query, search|
  firstname, lastname = search.split

  puts 'Query before edit', query

  query.where_clause.send(:predicates)[0] << " OR firstname = '#{firstname}' AND lastname = '#{lastname}')"

  puts 'Query after edit', query

  query
end

which produces:

Query before edit
User Load (0.9ms)  SELECT "users".* FROM "users" WHERE (LOWER("users"."firstname") LIKE $1 OR LOWER("users"."lastname") LIKE $2)  [[nil, "%homer simpson%"], [nil, "%homer simpson%"]]

Query after edit
SQL (1.8ms)  SELECT "users"."id" AS t0_r0, "users"."firstname" AS t0_r1, "users"."lastname" AS t0_r2 WHERE (LOWER("users"."firstname") LIKE $1 OR LOWER("users"."lastname") LIKE $2 ORDER BY "users"."id" DESC LIMIT $4 OFFSET $5  [[nil, "%homer simpson%"], [nil, "%homer simpson%"], ["LIMIT", 15], ["OFFSET", 0]]

I slightly modified the output to just remove the additional column that my database actually has.

Context

  • Package Version: 9.5.4
  • Rails Version: 7.2.2
  • Database Dialect: PostgreSQL
  • Database Version: 13.18
@nicolasalexandre9
Copy link
Member

Hi @jordanell , thanks for your feedback.

Instead of using where_clause, you can directly use the or method to add conditions to the query.

Here's an example:

 search_fullname = lambda do |query, search|
    firstname, lastname = search.split

    # Injects your new filter into the query.
    query.or(User.where("first_name = '#{firstname}' AND last_name = '#{lastname}'"))
  end

The documentation will be updated soon.

@bolinkd
Copy link

bolinkd commented Dec 17, 2024

Hey @nicolasalexandre9
Started looking into this fix and it appears to not be working exactly as we would like it too
An example below, we have some event architecture that stores the class_name and id in a jsonb column and we want to be able to search by these two attributes. We implemented filtering below, which works, but the searching is not working.

search_properties_class_name = lambda do |query, search|
      query.or(::Event.where('events.properties->>\'class_name\' = ?', search))
    end
    filter_properties_class_name = lambda do |condition, _where|
      value = condition['value']

      case condition['operator']
      when 'equal'
        "events.properties->>'class_name' = '#{value}'"
      end
    end
    field :properties_class_name, type: 'String', search: search_properties_class_name, is_filterable: true, filter: filter_properties_class_name do
      object&.properties_class_name
    end

    search_properties_id = lambda do |query, search|
      query.or(::Event.where('events.properties->>\'id\' = ?', search))
    end
    filter_properties_id = lambda do |condition, _where|
      value = condition['value']

      case condition['operator']
      when 'equal'
        "events.properties->>'id' = '#{value}'"
      end
    end
    field :properties_id, type: 'String', search: search_properties_id, is_filterable: true, filter: filter_properties_id do
      object&.properties_id
    end

The query snippet I can see in the logs says that the generated SQL query looks something like

SELECT events.* FROM events WHERE ( OR (events.name...

Which is telling me that it is putting the filter inside the where clause which generated invalid SQL.

@nicolasalexandre9
Copy link
Member

Hi @bolinkd,

Could you share the request payload and the SQL query ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants