简体   繁体   中英

Combine multiple queries into one active record relation?

I am trying to write a search query for my app where based on the query string it will search for groups or users matching the string.

Here is what I have written:

    def search_api
      @groups = Group.where("name ILIKE '#{params[:query]}'")
      @users = User.where("first_name ILIKE '#{params[:query]}' OR last_name ILIKE '#{params[:query]}")
    end

Is there a way to combine these two queries into one activerecord relation array? Besides the brute force iterating over both arrays and putting them into one?

I am not sure about the solution but I have a security suggestion.

Your queries are not SQL Injection safe. You could pass array instead of injecting params in SQL string.

The following queries are SQL injection safe:

@groups = Group.where("name ILIKE ?", "#{params[:query]}")
@users = User.where("first_name ILIKE ? OR last_name ILIKE ?", "#{params[:query]}")

So here is a solution. Not sure that it is better than leaving everything as it is, but formally it's the answer to a question (besides that the result is not an ActiveRecord relation):

 Group.connection.execute("(SELECT id, 'groups' as table FROM groups WHERE...) UNION (SELECT id, 'users' as table FROM users WHERE...)")

This returns an object of type PG::Result which you can treat as array of hashes. And, as it has already been said, it is good to pass arguments as an array instead of inserting them directly into SQL. Unfortunately, if You want to get a result as ActiveRecord, you may use UNION only for different queries to one table. In that case it looks like:

 Group.find_by_sql("(SELECT * FROM groups WHERE...) UNION (SELECT * FROM groups WHERE...)")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM