Ruby on rails 基于第三个HABTM模型的标准,从两个模型收集单个ActiveRecord

Ruby on rails 基于第三个HABTM模型的标准,从两个模型收集单个ActiveRecord,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,我有一个通讯簿,由地址、企业和个人组成。这三个模型都有HABTM关系,因为现实就是这样运作的 每个地址也有地理坐标(地址.纬度和地址.经度) 我想在一个特殊的地点(/london)为我的Rails控制器收集一个集合,在一个集合中,所有在伦敦有地址的企业和个人都会出现在传单地图上 但我也不想要伦敦以外的地址 目前, class Individual < ActiveRecord::Base has_and_belongs_to_many :addresses, join_table: :

我有一个通讯簿,由
地址
企业
个人
组成。这三个模型都有HABTM关系,因为现实就是这样运作的

每个地址也有地理坐标(
地址.纬度
地址.经度

我想在一个特殊的地点(
/london
)为我的Rails控制器收集一个集合,在一个集合中,所有在伦敦有地址的企业和个人都会出现在传单地图上

但我也不想要伦敦以外的地址

目前,

class Individual < ActiveRecord::Base
  has_and_belongs_to_many :addresses, join_table: :addresses_individuals
  has_and_belongs_to_many :businesses, join_table: :businesses_individuals

  scope :london, -> { joins(:addresses).where("addresses.latitude < ? AND addresses.latitude > ? AND addresses.longitude < ? AND addresses.longitude > ?", $London[:north], $London[:south], $London[:east], $London[:west]).distinct }

  def js_slug
    "#{self.first_name}_#{self.last_name}".parameterize.underscore.camelize(:lower)
  end
end
现在

@individuals = Address.london.map{ |a| a.individuals }
接近我想要的,至少在控制台中,但当我将其放入控制器时:

class Frontend::FrontendController < ApplicationController

  layout :resolve_layout

  respond_to :html

  def london
    @individuals = Address.london.map{ |a| a.individuals }
    # @individuals = Individual.london
    @fitbounds = [[$London[:south], $London[:west]], [$London[:north], $London[:east]]]
    @circle_markers = nil
    render "city"
  end
当我使用
@personals=Individual.london
时,对
js_slug
的调用效果很好,但是我得到了地图上不在伦敦的所有地址

因此,在通过
@personals=Individual.london
进行收集并将地址丢弃到伦敦以外的地方后,如果不迭代每个地址,我如何获得如此有限的地址集

那么,当我对企业做同样的事情时,如何将其与个人集合合并/加入


谢谢

问题在于Address.london.map{| a | a.personals}返回单个元素,即个人集合(try@personals.count,应等于1)

基本上,我们在这里要寻找的是joins表中的所有记录,其中address_id属于伦敦的一个地址,我们想显示属于individual_id的个体。因此,我认为我们可以使用joins表中的作用域得到您想要的结果,如下所示

# address_individual model (sim for business)
class AddressIndividual < ActiveRecord::Base
  scope :london, -> { where("address_id in (?)", Address.london.map(&:id)) }
end
#地址#个人型号(商业sim卡)
类AddressIndividual{where(“address_id in(?)、address.london.map(&:id))}
结束
然后我们可以在控制器中调用它。为了避免混淆,我会使用与“个人”不同的名称(我们将在下面的视图中定义个人)。我只会用“个人地址”

# individual controller
class Frontend::FrontendController < ApplicationController

  layout :resolve_layout
  respond_to :html

  def london
    @address_individuals = AddressIndividual.london

    @fitbounds = [[$London[:south], $London[:west]], [$London[:north], $London[:east]]]
    @circle_markers = nil
    render "city"
  end
end
#单个控制器
类前端::前端控制器<应用程序控制器
布局:解析布局
回复:html
def伦敦
@address_personals=AddressIndividual.london
@fitbounds=[$London[:south]、$London[:west]、[$London[:north]、$London[:east]]
@圆圈=零
渲染“城市”
结束
结束
然后我们可以在视图中引用它,只需要一个额外的步骤来显示个人

<table class="table table-striped table-hover table-condensed table-responsive">
  <tbody>
    <% @address_individuals.each do |ai| %>
      <% individual = Individual.find(ai.individual_id)
      <tr>
        <td id="<%= individual.js_slug %>">
          <%= link_to "#{individual.first_name} #{individual.last_name}", [:frontend, individual] %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>


我想这对你很有帮助。你可以为企业做同样的事情。我不确定如何将它们组合到单个作用域或活动记录查询中-我只想在视图中为每个查询执行两个循环。

我将从底部开始

当问题不存在时是最好的,对吗?与其寻找一种方法来合并两个不同模型的集合,不如问问自己:首先将它们分开是否值得

我不是说让它们成为一个模型,不是。我说的是单表继承,这将有效地允许您将这两个模型存储在一个表中(通过让这两个模型继承拥有该表的模型,而不是
AR::Base
)。这意味着单个表需要两个模型的字段和一个
类型的
字段。如果它们已经很相似了,你会没事的,如果不是,就取决于“值得吗”。这将允许您仅在某些查询可能同时导致个人和企业的情况下查询“根模型”:ActiveRecord将实例化正确的对象。把普通的东西分解到基本模型中是非常枯燥的

现在是主要问题

您似乎还没有确定在控制器中需要哪些列表,在示例代码中,您只提到了个人,您的抱怨基本上是您得到了不需要的地址。这是公平的,您没有显式地查询地址,而是基于另一个数据集获取地址,而该数据集不具备构建它所使用的条件。听起来比实际情况更复杂

首先,将“伦敦”留给地址模型,并从其他地方引用它,如:

scope :london, -> { joins(:addresses).merge(Address.london).distinct }
其次,如果需要地址列表,请查询addreses:

@addresses = Address.london
如果您需要关联的个人,当
每个
ing时,您会遇到N+1查询问题,请像这样绕过它:

@addresses = Address.london.includes(:individuals)
这与上面的代码几乎相同。这不明显吗?好的,这个来自视图的片段如何(这里使用Slim/HAML以简化):


除了第二行之外,完全相同,因为您已经将地址映射到控制器中的集合(而不是个人本身!)。这也是@FunTimeFreddie所说的,他是正确的。

您能给我们控制器代码、视图逻辑和地址模型(其上的关系)吗?谢谢。我试着在原来的问题上加上这个。我改变了我看到的错误,因为视图中最初的错误是针对一个正在构建javascript的助手的。这是非常基本的。该范围目前不必要地执行两个查询。请尝试加入(:address)。合并(address.london)
谢谢。我这样做了,现在我得到了多个条目,上面有两个伦敦地址,在伦敦以外的地图上仍然有点显示。在我之前的系统中,至少个人不会被复制。伦敦地址正确吗?如果是的话,我不明白为什么伦敦不会。不确定地图上的点与列表的关系如何,以及您希望它看起来如何-我想知道是否最好为每个点创建一个单独的变量?你最初的个人。伦敦和地址。伦敦会这样做。比
scope :london, -> { joins(:addresses).merge(Address.london).distinct }
@addresses = Address.london
@addresses = Address.london.includes(:individuals)
- @addresses.each do |address|
  - address.individuals.each do |individual|
    = individual.whatever