ActiveRecords从连接表返回模型对象

时间:2012-11-20 20:00:12

标签: ruby-on-rails activerecord ruby-on-rails-3.1

我有以下数据库用于我正在构建的简单闪存卡示例:

create_table "card_associations", :force => true do |t|
  t.integer  "card_id"
  t.integer  "deck_id"
end

create_table "cards", :force => true do |t|
  t.string   "question"
  t.string   "answer"
end

create_table "decks", :force => true do |t|
  t.string   "name"
  t.string   "description"
end

我在所有模特中通过关系设置了has_many。 现在我希望能够从连接表中返回所有卡的列表,给定甲板ID。 如果我运行查询:

  

CardAssociation.find_by_deck_id(3).card

它使用deck_id为3重新打造第一张牌。但是当我尝试时。

  

CardAssociation.find_all_by_deck_id(3).card

我收到错误

  

NoMethodError:#

的未定义方法`card'

有人可以帮我吗?我觉得我犯了一个非常简单的错误。

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

find_all_ *方法总是返回一个数组(可能为空)!

CardAssociation.find_all_by_deck_id(3) # => Array of results
CardAssociation.find_all_by_deck_id(3).first # => first result of the Array or nil if no result

我建议你先阅读Ruby on Rails Style Guide,然后使用Rails3的方式在ActiveRecord中查找对象:

CardAssociation.where(:deck_id => 3) # => Array of results
CardAssociation.where(:deck_id => 3).first # => first result of the Array if exists

在您的情况下,可以在卡片型号上设置范围:

你说:“现在我希望能够从连接表中返回所有卡的列表,给出甲板ID

class Card < ActiveRecord::Base
  scope :for_deck, lambda { |deck| joins(:card_associations).where('card_associations.deck_id = ?', deck.try(:id) || deck) }
end

此范围可以使用如下:

Card.for_deck(deck) # returns an Array of Card objects matching the deck.id

根据范围中的定义,Card.for_deck(deck)的参数可以是deck对象甲板上的ID(类型为整数)

希望这有帮助!