所以 Rails 不支持 :through 关联通过 habtm 关系。有一些插件可以为 Rails 2.x 添加这个,但我使用的是 Rails 3 / Edge,只需要一个特定模型的关联。所以我想我会用 Arel 的美貌自己把它难倒。
一、机型:
class CardSet < ActiveRecord::Base
has_and_belongs_to_many :cards, :uniq => true
end
class Card < ActiveRecord::Base
has_and_belongs_to_many :card_sets, :uniq => true
has_many :learnings, :dependent => :destroy
end
class Learning < ActiveRecord::Base
belongs_to :card
end
我想获得属于特定卡片组的所有知识,:through => 卡片。
这是我目前在 CardSet 模型中的内容:
def learnings
c = Table(Card.table_name)
l = Table(Learning.table_name)
j = Table(self.class.send(:join_table_name, Card.table_name, CardSet.table_name))
learning_sql = l.where(l[:card_id].eq(c[:id])).where(c[:id].eq(j[:card_id])).join(j).on(j[:card_set_id].eq(self.id)).to_sql
Learning.find_by_sql(learning_sql)
end
这给了我(该死,Arel 很漂亮!):
SELECT `learnings`.`id`, `learnings`.`card_id`, `learnings`.`user_id`, `learnings`.`ef`, `learnings`.`times_seen`, `learnings`.`next_to_be_seen`, `learnings`.`interval`, `learnings`.`reps`, `learnings`.`created_at`, `learnings`.`updated_at`, `card_sets_cards`.`card_set_id`, `card_sets_cards`.`card_id` FROM `learnings` INNER JOIN `card_sets_cards` ON `card_sets_cards`.`card_set_id` = 1 WHERE `learnings`.`card_id` = `cards`.`id` AND `cards`.`id` = `card_sets_cards`.`card_id`
这与我的目标非常接近 - 只需cards
在语句的 FROM 部分中添加表格即可。
还有我的问题:我已经查看了 Arel 源代码,而对于我的生活,我无法弄清楚如何在另一个表中添加。
作为旁注,有没有更好的方法通过 ActiveRecord 从 Arel 运行结果(它通常返回一个我不想要的 Arel::Relation),而不是渲染到 sql 并像我一样使用 find_by_sql 运行查询正在做?