Rails加入表问题

时间:2010-10-08 20:54:46

标签: mysql ruby-on-rails join

我正在开发一个rails项目,并且遇到以下连接的一些问题:

@page = Page.find(params[:id], :joins => "LEFT JOIN page_translations ON page_translations.page_id = pages.id")

出于某种原因,它只会从Pages表中撤回所有内容。

这是我的Page

模型
class Page < ActiveRecord::Base
  has_many :users_pages
  has_many :users, :through => :users_pages
  has_many :page_translations
  has_many :categories
  accepts_nested_attributes_for :page_translations
  accepts_nested_attributes_for :categories
end

这是我的PageTranslation模型

class PageTranslation < ActiveRecord::Base
  belongs_to :pages
end

提前感谢所有帮助!

编辑(@thenduks)

日志运行两个单独的查询:

Page Load (0.5ms)  SELECT `pages`.* FROM `pages` WHERE (`pages`.`id` = 1) LIMIT 1

PageTranslation Load (0.5ms) SELECT `page_translations`.* FROM `page_translations` WHERE (`page_translations`.page_id = 1)

以下是我的控制器的样子:

@page = Page.find(params[:id], :include => :page_translations)

2 个答案:

答案 0 :(得分:2)

我对同样的事情感到难过,浪费了几个小时试图解决这个问题。事实证明,使用查询接口的joins方法不会初始化与正在连接的表相关的模型。您可以通过在服务器控制台中查看SQL语句,甚至在Rails控制台中将ActiveRecord日志记录重定向到STDOUT来查看。

我非常对此感到失望。它似乎不像joins方法应该如何工作 - 它肯定不是我所期待的。我期待它急于加载,因为它是在Edge Guides的急切负载部分。

无论如何,我不能再浪费时间去解决它,所以我做的是使用花式查询界面来简单地构建我的查询,使用to_sql来获取我的查询的SQL,然后将SQL传递给select_all,它返回一个哈希数组,其中数组中的每个元素(每个哈希)代表一行。

示例:

query = Post.joins("LEFT JOIN categories ON post.category_id = categories.id")
query.select("posts.*, category.category_name")
con = ActiveRecord::Base.connection
results = con.select_all(query.to_sql)

结果:

[{"id": 1, "title": "joins, why have you forsaken me", "category_name": "frustration"},{"id": 2, "title": "pizza", "category_name": "food"}]

说实话,我仍然想知道是否可以按照认为它应该工作的方式,或者应该的方式来做到这一点工作。否则,除了帮助我们构建查询之外,我认为没有理由使用joins方法。因此,如果有任何Rails专家知道如何使用joins填充与这些表相关的模型,请告诉我(美国)知道!

无论如何,我希望这可以帮助你现在继续前进。


更新:所以我想我刚想通了。我偶然发现了blog post。事实证明,当使用查询接口的joins方法时,Rails实际上会将您从连接表中选择的列添加为要连接的模型的属性方法

使用上面的相同示例,我只需拨打category_name即可访问每个帖子的post.category_name #$%! 难以置信的简单,但没有关于此的任何文档!

这是再一次:

query = Post.joins("LEFT JOIN categories ON post.category_id = categories.id")
query.select("posts.*, category.category_name")
posts = query.all

# access a post's category name
puts posts[0].category_name

# this is what I thought I would be able to do
# without Rails making another query to the database
puts posts[0].category.category_name

我希望这有帮助! :)

答案 1 :(得分:0)

怎么样:

Page.find( params[:id], :include => :page_translations )

修改

好的,所以最近有一段时间ActiveRecord在连接/包含时的行为似乎已经改变了。这些指南仍然指的是能够通过两个关联来实现这一点,如has_many :orders, :include => :line_items和类似...但是包括来自has_many的记录......在咨询{{3}之后我们遇到了co-worker。似乎单个整体查询变得过于复杂和丑陋,并且它导致了ActiveRecord为您提供的一些更好的细节问题以及重复的行,这类事情。

TL; DR:它不再那样了。预计会有2个查询。