簡體   English   中英

將ActiveRecord habtm查詢轉換為Arel

[英]Convert ActiveRecord habtm query to Arel

我有一個很常見habtm關系:

Photo has_and_belongs_to_many :tags
Tag has_and_belongs_to_many :photos

在我的Photo模型中,我有一個“帶標簽”的方法,我用它來查找用一組給定的tag_ids標記的照片。 此查詢只需匹配具有所有給定標記的照片,但無需考慮是否存在任何其他標記。 這是我的方法:

def self.with_terms( array )
  select('distinct photos.*').joins(:tags).where('tags.id' => array).group("photos." + self.column_names.join(', photos.')).having("count(*) = #{array.size}")
end

這按預期工作。

現在,為了更好地與我正在使用的其他庫集成,我需要在Arel中重寫它。 (使它成為Arel節點?,不確定你通常稱之為什么)。

我一直在嘗試這個,但說實話我以前從未嘗試過使用過Arel,所以我有點失落。 我一直在試驗控制台並嘗試:

t = Photo.arel_table
q = t.join(:tags).on(t[:tags_id].in(array))
Photo.where(q)

但是,(1)我認為q首先不是正確的查詢,並且(2)它創建了一個Arel::SelectManager ,當它傳遞到where調用引發時Cannot visit Arel::SelectManager 所以,顯然我做錯了。

更新:只是為了在這里特別具體,我希望返回一個Arel節點,因為我正在使用一個gem(ransack),希望你傳遞它的搜索方法的Arel節點。 Ransack將此Arel節點與其他節點鏈接在一起,以生成復雜的搜索查詢。

Arel大師可以告訴我這是怎么做的嗎?

很難找到好的Arel文檔,但@ Philip C已經匯總了一些有用的幻燈片 ,在他對這個問題的回答中提到了

以下應該是您正在尋找的:

photos = Arel::Table.new(:photos)
tags = Arel::Table.new(:tags)
photo_tags = Arel::Table.new(:photo_tags)

q = photos[:id].in(
   photos.project(photos[:id])
  .join(photo_tags).on(photos[:id].eql(photo_tags[:photo_id]))
  .join(tags).on(photo_tags[:tag_id].eql(tags[:id]))
  .where(tags[:id].in(array))
  .group(photos.columns)
  .having(tags[:id].count.eq(array.length))
)

這導致了一個Arel::Nodes::In實例,你應該可以像在Photo.where(q)Photo.where(q)直接使用它。


更新:

在查看了文檔和一些搜索源之后,似乎沒有任何自然的方法來定義涉及子查詢的自定義謂詞,這在您的情況下是必需的(因為謂詞必須符合where子句)。 解決此問題的一種方法可能是利用謂詞使用的:formatter ,如下所示:

Ransack.configure do |config|
  config.add_predicate 'with_tag_ids',
                   :arel_predicate => 'in',
                   :formatter => proc {|tag_ids| tags_subquery(tag_ids) },
                   :validator => proc {|v| v.present?},
                   :compounds => true
end

您可以將tags_subquery(tag_ids)定義為一個生成上述arel節點的方法,但在返回之前將array替換為tag_ids並在其上調用.to_sql (格式化程序需要返回字符串,而不是節點)。

我沒試過這個,所以如果它有效我會很激動!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM