0

I have a set of objects through ActiveRecord, and need to iterate through them to ID a set of conditions.

def get_smith_listings
  Listing.joins(:spec).where('specs.broker ilike ?', '%smith%')
end

@listings = Listings.all #actually a built query

@listings.sort_by { |item| item.get_smith_listings? ? 0 : 1 }

=> EXPLAIN for: SELECT "listings".* FROM "listings" INNER JOIN "specs" ON "specs"."listing_id" = "listings"."id" WHERE (specs.agent ilike '%smith%')
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Nested Loop  (cost=0.28..848.56 rows=1 width=668)
   ->  Seq Scan on specs  (cost=0.00..840.25 rows=1 width=4)
         Filter: ((agent)::text ~~* '%smith%'::text)
   ->  Index Scan using listings_pkey on listings  (cost=0.28..8.30 rows=1 width=668)
         Index Cond: (id = specs.listing_id)

(the nature of the question has changed slightly as I've zeroed in on the method required)

I'm having trouble structuring this in a way that a) gets my method recognized (new to helpers) and sets up the query to sort using the boolean.

UPDATE: For this seeking clarification, this is the direction I'm trying to take on this problem: https://www.mateoclarke.com/blog/2015/10/14/what-i-learned-boolean-ruby/

7
  • don't know if I got it right... you want an array where the first ones have agent like smith and the last ones who don't? Commented Apr 25, 2018 at 19:56
  • Yup - I want to take everything that fits 'group' and move it to the beginning of the array. Commented Apr 25, 2018 at 19:57
  • so you want just order? like [ 'agent like smith true', 'agent like smith false']? Commented Apr 25, 2018 at 20:00
  • Yeah - like, if group? then unshift. Commented Apr 25, 2018 at 20:01
  • made an answer... don't know if I got it right, but take a look Commented Apr 25, 2018 at 20:04

2 Answers 2

2

Enumerable#partition does that: it results in an array of 2 arrays. The first contains all items for which the block is true, the second are the falses.

Sign up to request clarification or add additional context in comments.

4 Comments

so (@listing).partition { |v| v.group? } ?
I'm just guessing here ( have no data and no Rails) , I would try groups = @listings.partition.joins(:spec).where('specs.agent ilike ?', '%smith%')
that wouldn't work... you can't apply joins on an enumerable. Also, partition needs a block with the condition to separate the objects based on that condition, and it's applied over each record, so you can't use where. So, something like this could work: @listings.includes(:spec).partition{|l| l.spec.agent.include?("smith")}
@RonanLopes Even without Rails knowledge, yours seems to make much more sense.
1

You can do it like this:

group = Listings.all.joins(:spec).where('specs.agent ilike ?', '%smith%') +
 Listings.all.joins(:spec).where.not('specs.agent ilike ?', '%smith%')

So it will put on the group variable first the ones that match the condition, and after those, the ones that doesn't

EDIT: don't know exactly why you need a separate method to do that (since the way I showed before would give you the correct order anyway). But there's a problem with the syntax you showed on edit: you're trying to call a instance method that calls the whole ActiveRecord method where (same problem as the answer of steenslag). If you wanna do the way you presented, I think this way should work better:

#this method should be on Listing model
def get_smith_listings?
  self.spec.broker.to_s.include?("smith")
end

@listings = Listings.includes(:spec).all #important to avoid n+1 queries

# here the 0 or 1 position will depende the true/false order you want
@listings.sort_by { |item| item.get_smith_listings? ? 0 : 1 }

I still don't got why you wanna do it that way and guess there's probably a better way to do what you want... but for now I can't help more than that. Good luck!

6 Comments

This is good, but I need to be able to set group = @listings.joins(:spec).where('specs.agent ilike ?', '%smith%') as a condition to be called - hence the need for a boolean
@Boucherie don't got it right so. Can you explain with more details what you're trying to do? please update the question
Updated the question.
Damn...yeah, the dev who set this up agrees - just got pointed to ransack gem docs
Okay, this is right, and I'm going to mark it right, but my strategy shifted considerably - this helped parse through different methodologies though, so thanks :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.