模拟Rails 3中通过行为嵌套的has_and_belongs_to_many [英] Simulating has_and_belongs_to_many nested through behavior in Rails 3

查看:62
本文介绍了模拟Rails 3中通过行为嵌套的has_and_belongs_to_many的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,Rails不支持通过habtm关系的关联.有一些插件可以将其添加到Rails 2.x中,但是我使用的是Rails 3/Edge,并且只需要一种特定模型的关联.所以我想我会以Arel的美丽为自己绊倒.

So Rails doesn't have support for :through associations through a habtm relationship. There are plugins out there that will add this in for Rails 2.x, but I'm using Rails 3 / Edge, and only need the association for one particular model. So I thought I'd stump it out myself with the beauty that is 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 =>卡片.

I want to get all the learnings that belong to a particular card set, :through => cards.

这是我到目前为止在CardSet模型中所拥有的:

This is what I have so far in my CardSet model:

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

这给了我(该死,阿雷尔很漂亮!):

which gives me (damn, Arel is beautiful!):

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`

这与我要达到的目标非常接近-只需在语句的FROM部分中的cards表中添加.

which is oh so close to what I'm aiming for - just needs to add in the cards table in the FROM part of the statement.

还有一个问题:我浏览了Arel的源代码,对于我的一生,我不知道如何在另一个表中进行添加.

And there's my question: I've looked through the Arel source, and for the life of me I can't figure out how to add in another table.

作为一个旁注,除了呈现到sql并使用find_by_sql作为查询来运行查询之外,还有一种更好的方法可以通过ActiveRecord从Arel运行结果(通常返回一个Arel :: Relation,我不希望这样做).我在干嘛?

As a sidenote, is there a better way to run the result from Arel (which usually returns an Arel::Relation, which I don't want) through ActiveRecord, other than rendering to sql and running the query with find_by_sql as I'm doing?

推荐答案

在我了解了Rails如何封装Arel从而不需要直接构建查询之后,这比我上面写的要容易.

This is easier than what I wrote above, after I learned how Rails encapsulates Arel so you don't need to build the query directly.

如果您要在CardSet模型中对嵌套的habtm进行存根处理,也称为:

If you're trying to stub nested habtm in the CardSet model, a.k.a.:

has_many :learnings, :through => :cards

然后您可以使用它来模拟行为:

then you can use this to simulate the behaviour:

class CardSet < ActiveRecord::Base

  has_and_belongs_to_many :cards, :uniq => true

  def learnings
    Learning.joins(:card).where(:cards => { :id => self.card_ids })
  end
end

然后这样的查询将起作用:

then a query like this will work:

CardSet.first.learnings

这篇关于模拟Rails 3中通过行为嵌套的has_and_belongs_to_many的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆