ActiveRecord::Relation 连接的条件不仅仅是外键
有没有一种方法可以使用 ActiveRecord::Relation 为左外连接指定多个条件?
以下面的SQL语句为例。如何使用 ActiveRecord::Relation 对象重写它?
SELECT `texts`.*, `text_translations`.translation FROM `texts` LEFT OUTER JOIN `text_translations` ON `text_translations`.`id` = `texts`.`id` AND `text_translations`.`locale` = 'en'
在ActiveRecord 3.0.3+下有什么办法可以做到这一点吗?
提前致谢。
Is there any way to specify more than one conditions for a left outer join using ActiveRecord::Relation?
Take the following SQL statement for example. How can anyone rewrite this using ActiveRecord::Relation objects?
SELECT `texts`.*, `text_translations`.translation FROM `texts` LEFT OUTER JOIN `text_translations` ON `text_translations`.`id` = `texts`.`id` AND `text_translations`.`locale` = 'en'
Is there any way to do this under ActiveRecord 3.0.3+?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先您应该考虑使用rails/activerecord 一致性关系。这意味着 text_translations 表中的外键应称为 text_id
像这样创建模型和关联:
以及
如何使用:
现在谈谈优点和缺点,使用 LEFT OUTER join 的方式将加载您全部即使没有所需语言的文本翻译。缺点是您不会获得“TextTranslation”模型对象。
另一种方法是仅加载具有所需翻译的文本。您可以这样做:
现在
texts[i].text_translations
将返回一个数组,其中包含与语言环境“en”匹配的此文本的所有 TextTranslations 模型对象。但在语言环境“en”中没有翻译的文本将不会显示。编辑
连接到您的评论:
在关系上使用
.join(:tablename)
的问题是,它将导致 INNER JOIN,因此这不是一个选项。您必须显式声明 LEFT 连接。另一件事是,如果您使用类似Text.includes(:text_translations).where(['text_translations.locale = ?', 'en'])
的条件,该条件将应用于 SQL 查询,如下所示整体而不是可能的 LEFT 连接本身。您实际上可以做的是声明这样的关联:这样您就可以通过急切加载来仅加载英文翻译(根本不需要任何连接):
检查一下:
first you should consider to use rails/activerecord conform relations. This means the foreign key in the text_translations table should be called text_id
Create your models and associations like this:
and
How to use:
Now to the pro and cons, the way using LEFT OUTER join will load you all texts even if there isn't a translation for a text in the desired language. The con is that you won't get the "TextTranslation" model object.
Anotherway is to load only the text which have the desired translation. You can do it like:
now
texts[i].text_translations
will return an array with all TextTranslations model object for this text matching the locale 'en'. But texts without a translation in the locale "en" won't show up.Edit
Connected to your comment:
The problem about using
.join(:tablename)
on a relation is that, it will result in an INNER JOIN so this is not an option. You have to explicitly declare the LEFT join. Another thing is that if you use something likeText.includes(:text_translations).where(['text_translations.locale = ?', 'en'])
the condition will be applied to the SQL query as whole and not on the possible LEFT join itself. What you actually can do is to declare associations likeThis way you can manage to load only english translations by eager loading (without any joins at all):
Checkt this out: