2

I have a Product model which has name and description columns in the database.

I also have a Product.search_results_for(query), where query is a string like "Green Apple".

I need to return an ActiveRecord::Relation of the results ordered by which is the best hit. Currently, I'm setting a search_result_value to each product. search_result_value IS NOT a column in the database, and I don't want it to be.

So in essence, I have an ActiveRecord::Relation of Products that I need to order by search_result_value without changing it to an array, which is an instance variable that isn't stored in the database. How can I do this?

Something like this:

Product.order(:search_result_value)
Mavvie
  • 320
  • 3
  • 11

1 Answers1

6

If you do not put the value in a column or express the logic in search_result_value in pure SQL, then you’ll have to load all Products into memory and then sort them in Ruby using sort_by:

Product.all.to_a.sort_by(&:search_result_value)
Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
  • 1
    Thanks, but are there any ways of doing this without converting it to an array? As in, sort the ActiveRecord::Relation by the respective object's instance variables? – Mavvie Aug 18 '13 at 07:13
  • Here, the ``to_a`` call is not necessary. Now Active Record relations are lazy loaded, so calling ``sort_by`` on an active record relation will implicitely convert it to an array and then call ``sort_by`` on it. – Intrepidd Aug 18 '13 at 08:38
  • 2
    @Mavvie, the ActiveRecord::Relation is just a query, not a result set. So, you can write SQL to calculate the field for you, or you need pull the records into an array and sort them with Ruby. – cpuguy83 Aug 18 '13 at 15:16
  • 1
    @Intrepidd, I know it’s not needed, but I think it’s more clear, especially since `all` used to be an Array but is now a Relation starting in Rails 4. And no @Mavvie, there is not—the database has no idea your Ruby exists and the instance variable doesn’t exist till you’ve loaded the objects into Ruby-land. – Andrew Marshall Aug 18 '13 at 15:22
  • Thanks, sorry for forgetting about this comment. I never ended up implementing it (The fact I wanted to do an SQL order() by a ruby virtual attribute just makes no sense lol. I'm now using [Searchkick](https://github.com/ankane/searchkick), which has come a long way since I started using it last year. – Mavvie Aug 01 '14 at 14:37