【问题标题】:Simulating has_and_belongs_to_many nested through behavior in Rails 3通过 Rails 3 中的行为模拟 has_and_belongs_to_many
【发布时间】:2010-07-30 01:54:47
【问题描述】:

所以 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`

这与我的目标非常接近 - 只需在语句的 FROM 部分中添加 cards 表即可。

还有我的问题:我查看了 Arel 的源代码,但在我的一生中,我无法弄清楚如何添加到另一个表中。

作为旁注,除了渲染到 sql 并使用 find_by_sql 作为我在做什么?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 has-and-belongs-to-many has-many-through arel


    【解决方案1】:

    我不熟悉 Arel,但不会处理:

    l.includes(:card)
    

    【讨论】:

    • 这将提取所有学习,而不仅仅是与 card_set 相关联的卡片相关联的学习(也称为嵌套 habtm)。
    【解决方案2】:

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

    如果您尝试在 CardSet 模型中存根嵌套的 habtm,也就是:

    has_many :learnings, :through => :cards
    

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

    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
    

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

    CardSet.first.learnings
    

    【讨论】:

      猜你喜欢
      • 2012-01-14
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多