2012-04-16 71 views
1

在Rails(3.2)的應用程序,我有這樣一個模型類方法:如何將此原始SQL轉換爲Arel查詢?

def import(level, max = 10) 
    db = ActiveRecord::Base.connection 
    result = db.execute("SELECT word FROM levels WHERE level == #{level} AND word NOT IN (SELECT entry FROM words) limit #{max};"); 

它只是在不爲Word記錄還不存在一個時間導入10個新詞(創建10條記錄) 。

架構看起來是這樣的:

create_table "levels", :force => true do |t| 
    t.string "word" 
    t.integer "level" 
end 

create_table "words", :force => true do |t| 
    t.string "entry" 
    t.integer "level",  :default => 0 
    t.text "definition" 
    t.string "thesaurus", :default => "none" 
end 

我是SQL菜鳥。使用rails dbconsole(sqlite3,我在服務器上也使用sqlite3),我以某種方式想出了上面的原始sql查詢。我有點知道我可以用Arel做同樣的事情。我應該如何用ActiveRecord構造查詢?

回答

1

以下(未測試)應該工作。它在子查詢中使用pluck

Level.where(:level => level).where("word NOT IN (?)", Word.pluck(:entry)).limit(max) 
+0

謝謝!我明白了,但是'Level.where(「word not in?」,「apple,banana」)'產生:'SQLite3 :: SQLException:no such table:apple,banana:SELECT「levels」。* FROM「levels 「在哪裏(不是'蘋果,香蕉'的單詞)'嗯。 – knsmr 2012-04-16 10:14:06

+0

我想如果你在最後拿出'join(「,」)'它應該可以工作。 'IN'插值需要一個數組。 – tsherif 2012-04-16 10:18:20

+0

是的,我只是想出了自己。 (Level:> level).where(「word not IN(?)」,Word.pluck(:entry))。limit(max)'作品。你也需要'()'。非常感謝! – knsmr 2012-04-16 10:27:43

0

@ Gazler的解決方案看起來像它的工作原理,但我會用MetaWhere語法這是一個比較簡潔的提供一種替代方案:

Level.where(:level => level, :word.not_in => Word.pluck(:entry)).limit(max) 
+0

美麗。但是,我得到這個錯誤:'NoMethodError:undefined method'not_in'for:word:Symbol'。這個not_in方法屬於哪裏? – knsmr 2012-04-16 10:36:45

+0

哦,我需要一個名爲[MetaWhere]的寶石(http://erniemiller.org/projects/metawhere/)?它會在不久的將來登陸Rails嗎?如果沒有,我會堅持@Gazler的解決方案。不管怎麼說,多謝拉! – knsmr 2012-04-16 10:42:19

+0

嗯......好笑。它似乎是內置於我使用的Rails版本(3.0.7)。如果它已經被取出,我必須小心... – tsherif 2012-04-16 10:56:34