在数组中将值设置为boolean并在ruby中更改位置(Rails 5)

时间:2018-04-25 19:53:51

标签: ruby-on-rails ruby activerecord

我有一组通过ActiveRecord的对象,需要迭代它们以识别一组条件。

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)

(问题的性质已经略有改变,因为我已经对所需的方法进行了调整)

我无法以这样的方式构建它:a)我的方法被识别(对助手来说是新的)并设置查询以使用布尔值进行排序。

更新:为了寻求澄清,这是我试图解决这个问题的方向:https://www.mateoclarke.com/blog/2015/10/14/what-i-learned-boolean-ruby/

2 个答案:

答案 0 :(得分:2)

Enumerable#partition这样做:它产生一个包含2个数组的数组。第一个包含块为true的所有项目,第二个包含falses。

答案 1 :(得分:1)

你可以这样做:

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

所以它会先将组变量放在符合条件的组变量上,然后再将那些变量放在组变量上

编辑: 我不知道为什么你需要一个单独的方法来做到这一点(因为我之前展示的方式无论如何都会给你正确的顺序)。但是您在编辑时显示的语法存在问题:您正在尝试调用调用整个ActiveRecord方法的实例方法(与steenslag的答案相同)。如果你想按照你提出的方式行事,我认为这种方式应该更好:

#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 }

我仍然不知道为什么你想这样做,并猜测那可能是一个更好的方式来做你想要的......但是现在我不能帮助更多。祝你好运!