Ruby on rails 包含条件,但始终显示主表结果
我有一个类似于:Ruby on rails 包含条件,但始终显示主表结果,ruby-on-rails,Ruby On Rails,我有一个类似于: # get all locations, if the user has discovered them or not def self.getAll(user) self.find(:all, :order => 'min_level asc', :include => 'discovered_locations', :conditions => [ "discovered_locations.user_id = ? OR discovered_l
# get all locations, if the user has discovered them or not
def self.getAll(user)
self.find(:all, :order => 'min_level asc', :include => 'discovered_locations',
:conditions => [ "discovered_locations.user_id = ? OR discovered_locations.id is null", user.id] )
end
self实际上是BossLocation模型。如果我的用户发现了bosslocation和发现的位置,我希望获得该位置的结果集。但是,如果它没有被发现,我仍然需要bosslocation和no object作为发现的位置。有了上面的代码,如果用户没有发现任何东西,我根本就不会得到bosslocations
编辑:
我的联想是:
class BossLocation < ActiveRecord::Base
has_many :discovered_locations
has_many :users, :through => :discovered_locations
class DiscoveredLocation < ActiveRecord::Base
belongs_to :user
belongs_to :boss_location
class User < ActiveRecord::Base
has_many :discovered_locations
has_many :boss_locations, :through => :discovered_locations
class-BossLocation:发现了\u位置
类DiscoveredLocation:已发现\u位置
“如果我的用户发现了bosslocation和发现的位置,则该位置和发现的位置的结果集。”这不是左外联接。您将随时获得所有bosslocation。因此,您的条件是错误的!这将获取已发现位置的bosslocation。user\u id=user.id或已发现位置的id为null。在这种情况下,对于一条sql语句来说,这可能很困难。您也可以在find_by_sql中使用union,但我建议您使用双查找函数。我认为问题在于您在where条件中指定了用户id,而不是在join条件中指定。只有在用户发现或根本没有用户发现的情况下,您的查询才会提供BossLocation
要使数据库查询符合您的需要,可以将include更改为以下联接:
:joins => "discovered_locations ON discovered_locations.boss_location_id = boss_locations.id
AND discovered_locations.user_id = '#{user.id}'"
但是,我认为这不会有多大帮助,因为当使用像这样的连接而不是include时,急切地加载Rails将不起作用
如果我在哪里做类似的事情,我可能会把它分开。可能通过如下方式为用户添加关联:
class User < ActiveRecord::Base
has_many :disovered_locations
has_many :discovered_boss_locations, :through => :discovered_locations
@locations = BossLocation.all
@discovered = current_user.discovered_locations.all.group_by(&:boss_location_id)
<% @locations.each do |location| %>
<h1><%= location.name %></h1>
<% unless @discovered[location.id].nil? %>
<p>Discovered at <%= @discovered[location.id].first.created_at %></p>
<% end %>
<% end %>
要在循环它们时使用它们,请执行以下操作:
class User < ActiveRecord::Base
has_many :disovered_locations
has_many :discovered_boss_locations, :through => :discovered_locations
@locations = BossLocation.all
@discovered = current_user.discovered_locations.all.group_by(&:boss_location_id)
<% @locations.each do |location| %>
<h1><%= location.name %></h1>
<% unless @discovered[location.id].nil? %>
<p>Discovered at <%= @discovered[location.id].first.created_at %></p>
<% end %>
<% end %>
发现于
它将所有发现的位置分组到一个散列中,其中键是boss\u location\u id。因此,当您循环遍历所有boss\u位置时,您只需查看发现的散列中是否有与boss\u id匹配的条目。hmm,实际上我已经有了这些关联。您的代码非常符合逻辑,但问题是解析结果。你看,我需要有静态的boss位置信息,以及这个boss位置是否为用户解锁。我可能会做一个@location.each并打印每个位置的静态信息,并指定为用户锁定的位置。我认为单独使用@bl和@dbl会很乏味。我正在粘贴原始问题中代码中的关联。当您执行@location.each时,您可以轻松检查每个位置是否存在于已发现的位置中。所有人都在我的帖子中进行更新。两个find表示'@locations=BossLocation.All@discovered=DiscoveredLocation.find(..)':P