I’m trying to work through a feature and I’m afraid that I’m getting stuck. I have an app where users can purchase icon sets. A purchase has many icons_sets (through a join) and a purchase belongs to a user.
In a dashboard I have a list of purchases that is both searchable and filterable by a timeframe (today, this week, last week, etc). Normally I wouldn’t have trouble to implement one or the other, and I’ve implemented something similar using a tool like Elasticsearch, but I feel that would be overkill.
I know that I need to use a class method such as
Purchase.search_and_filter so that I can have a collection to actually search and filter. I also wanted to separate this out into two methods to keep things readable and organized.
The first problem I’m running into is that calling the method
filter_by_timeframe throws an error:
undefined method `filter_by_timeframe' for #<Purchase::ActiveRecord_Relation:0x007f929f5644b8>
In my understanding, I’m wanting to send a collection through
search_and_filter, doing a search if needed, and then filtering the returned search collection.
Would anyone be willing to give me a push in the right direction?
Ooooook! I figured it out.
Updated gist: https://gist.github.com/seanwash/65b39a4491d48f596ebf
I was on the right track. I made
filter_by_timeframe a class method since it was being used on a purchase collection (which inherits from Purchase model). The problem I then ran into was an ambiguous pg error:
PG::AmbiguousColumn: ERROR: column reference "created_at" is ambiguous
LINE 4: OR lower(name) LIKE '%sean%') AND (created_at >= '20...
: SELECT "purchases".* FROM "purchases" INNER JOIN "users" ON "users"."id" = "purchases"."user_id" INNER JOIN "purchase_icon_sets" ON "purchase_icon_sets"."purchase_id" = "purchases"."id" INNER JOIN "icon_sets" ON "icon_sets"."id" = "purchase_icon_sets"."icon_set_id" WHERE (lower(first_name) LIKE '%sean%'
OR lower(last_name) LIKE '%sean%'
OR lower(email) LIKE '%sean%'
OR lower(name) LIKE '%sean%') AND (created_at >= '2015-02-23 00:00:00.000000') ORDER BY created_at DESC LIMIT 15 OFFSET 0
This was happening because now it didn’t know which model to query for
created_at since a join was used. I fixed that by specifying the table name for created at.
Works like a charm! Again, if anyone sees anything that can be improved, please please please let me know!
I made a few comments on the gist. Let me know here if you don’t understand them.
@benorenstein you’re totally right. I actually just watched the method extraction video yesterday. I’m traveling today but I’ll refactor these methods and post an updated gist.