Rails:这个多重关联条件连接有什么问题?

4

以下是我的模型:

class Deck < ActiveRecord::Base
  belongs_to :game
  has_many :deck_cards
end

class DeckCard < ActiveRecord::Base
  belongs_to :card
  belongs_to :deck
end

class Card < ActiveRecord::Base
end

这是我尝试找到的结果:

DeckCard.all :joins => [:card, :deck], :conditions => {{:decks => {:game_id => @game.id}}, {:cards => {:present => true}}}

我一直收到错误信息:undefined method for all for #Class:0x4b2a98>。我猜测这是从解析我的条件中产生的误导性错误。我遵循Active Record Query的指南。我不确定是否要使用关联的单数或复数形式。看起来,当使用belongs_to时,应在:joins哈希中使用单数形式,但我不确定在:conditions哈希中是否也需要使用单数形式,因此我尝试了两种方式,但都没有成功。
如果不清楚,我想在SQL中做的事情是:
SELECT * from DeckCards  
INNER JOIN decks on decks.id = deck_cards.deck_id  
INNER JOIN cards on card.id = deck_cards.card_id  
WHERE decks.game_id = 4  
AND cards.present = true

目前我可以通过使用DeckCard.find_by_sql来解决这个问题,但弄清为什么关联的连接和条件不起作用会更好。

我正在使用Windows上的InstantRails-2.0,其中使用的是Rails 2.0.2版本。

编辑:使用DeckCard.find(:all ...)取得了一些进展。我还根据另一个答案修改了括号。我的最新代码如下:

DeckCard.find :all, :joins => [:card, :deck], :conditions => {:deck => {:game_id => @game.id}, :cards => {:present => true}}  

产生以下错误:

Unknown column 'deck_cards.decks' in 'where clause': SELECT `deck_cards`.* FROM `deck_cards`   INNER JOIN `cards` ON `cards`.id = `deck_cards`.card_id  INNER JOIN `decks` ON `decks`.id = `deck_cards`.deck_id  WHERE (`deck_cards`.`decks` = '--- \n- :game_id\n- 5\n' AND `deck_cards`.`cards` = '--- \n- :present\n- true\n')  

连接看起来是正确的,但WHERE条件不正确。我尝试了几种不同的方法,例如在条件子句中使用:deck:decks,但没有成功。这可能是当前的ActiveRecord查询接口文档和2.0.2中执行条件的方式之间的另一个区别吗?
谢谢!

这仍然让我觉得它是语法错误,因为它甚至无法按名称识别DeckCard类。您能发布DeckCard.all行的周围方法吗? - Pesto
请查看我的更新答案,另有建议。 - Sarah Mei
6个回答

3

您需要完成与Card模型的关联:

class Card < ActiveRecord::Base
  has_many :deck_cards
end

编辑2: 尝试这个:

 DeckCard.find :all, :joins => [:card, :deck], :conditions => ["decks.game_id = ? and cards.present = ?", @game.id, true]

#all 是 #find :all 的别名。它们没有区别。 - Pesto
哦,我也被这个错误误导了!我以前从没见过 #all 这种用法。谢谢。 - Sarah Mei
我尝试了这个方法,除了Pesto的建议之外,仍然没有起作用。 - user26270

1

你的:conditions包含了2个哈希。这是错误的。你应该有两个键(:decks:cards),每个都应该有一个哈希值。请把你的改正为如下所示:

:conditions => {:decks => {:game_id => @game.id}, :cards => {:present => true}}

我尝试了这个,无论是在卡片模型上采用Sarah的建议还是不采用,它仍然无法工作。 - user26270

1

我没有测试过这个,但是如果你使用...

DeckCard.find(:all, :include => [:cards, :deck], :conditions => {:deck => {:game_id => @game.id}, :cards => {:present => true}})

这越来越接近了;.find(:all...)是2.0.2的正确方法;我现在可以看到生成的SQL语句了;JOIN是正确的,但WHERE子句条件不对;我已经没有空间了,必须在另一个评论或编辑的帖子中显示错误。 - user26270

1

使用的是哪个版本的Rails?ActiveRecord#all方法在2.0.2之后添加。

puts DeckCard.respond_to?(:all)的结果是什么?


抱歉,我忘记提到我正在使用InstantRails-2.0,其中包含Rails 2.0.2;我还没有将其更新到最新的Rails(2.3?);DeckCard.respond_to?(:all)返回false;我猜编译器是对的,“all”方法未定义!那么在2.0.2中应该使用什么?还是要升级? - user26270
对于2.0.2版本,请使用find(:all, ...blahblah...),正如@danengle所提到的那样。如果可以升级到2.2.2版本,我建议这么做。 - wombleton

0

你的语法也是反过来的。我认为连接(和连接表)需要按字母顺序排列。因此应该是card_decks。我相信这是Rails的默认配置。在我开始使用has_many => :through之前,我曾经遇到过类似的问题。


0

@game.deck.deckcards.joins(:cards).where('cards.present' => true)

Rails 4 的语法更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接