Rails 3的外连接方式

4

i have 3 models like :

location, user, discovered_location(location_id,user_id)

我认为我需要一个外连接来获取所有位置,并包括已被用户发现的discovered_location模型。
我需要类似这样的东西:{location1, location2, location3: 包含 discovered_location, location4 ...}
有没有Rails 3的方法可以做到这一点?如果没有,什么是最好的方法?
编辑
我想要获取上述指定的位置,针对某个用户。更好地说明一下,它应该是:
用户{location1、location2、location3: 包括发现的位置,location4...}
(一个用户有很多发现的位置)
3个回答

8

在Rails中,只能通过在joins方法中使用SQL语句来执行外连接:

joins("OUTER JOIN table2 on table2.column = table1.column")

4
如果您在使用includes方法并对一个已包含的表格使用条件,AR将执行外连接。 - Dave Pirotte
1
谢谢,这似乎像BossLocation.joins("LEFT OUTER JOIN discovered_locations ON discovered_locations.boss_location_id = boss_locations.id")一样有效。 - Spyros
Dave,我无法找到正确的包含/连接组合来获取类似于MySQL的外部连接:SELECT boss_locations.discovered_locations. FROM boss_locations LEFT OUTER JOIN discovered_locations ON discovered_locations.boss_location_id = boss_locations.id; - Spyros
我还编辑了我的问题,以更好地说明我正在寻找什么。 - Spyros
你需要指定 where("user_id = ? OR user_id IS NULL", @user_id) 来限制特定用户。这对你可能有效,但不如使用 Ruby 那么干净。此外,像这样使用 SQL 可能会在意想不到的情况下给你带来麻烦...所以最好不要走这条路,除非你必须这样做(而你并不必须这样做)。如果你看一下我的答案,用你要查找的用户 ID 替换掉 User.first.id,你就可以开始了。 - Dave Pirotte
显示剩余2条评论


3

您需要检查您的discovered_locations表中的用户ID是否等于所询问的用户ID,或者为空。这可以通过meta_where gem轻松实现。给定以下模型:

class User < ActiveRecord::Base
  has_many :discovered_locations
  has_many :locations, :through => :discovered_locations
end

class Location < ActiveRecord::Base
  has_many :discovered_locations
  has_many :users, :through => :discovered_locations
end

class DiscoveredLocation < ActiveRecord::Base
  belongs_to :user
  belongs_to :location
end

插入一些虚拟数据,然后执行类似于这样的语句:

Location.includes(:discovered_locations).where(
  {:discovered_locations => {:user_id => User.first.id}} | 
  {:discovered_locations => {:user_id => nil}}
).each do |loc|
  puts "#{loc.name} #{loc.discovered_locations.empty? ? 'not visited' : 'visited'}"
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接