选择distinct,包括来自不同模型/表的值

时间:2013-12-03 15:39:32

标签: sql ruby-on-rails postgresql activerecord

  • 我有2个模特/桌子:

    class CollectionPoint < ActiveRecord::Base
       belongs_to :collection_type
    ...
    
    class CollectionType < ActiveRecord::Base
      has_many :collection_points
    ...
    
  • 每个CollectionPoint都有一个城市(列)

  • 每个CollectionType都有一个名称(列)

我想在每个城市获取所有不同的集合类型名称,以便在我的视图中显示这样的目录:

  • 城市A

    • collection_type.name A
    • collection_type.name B
    • collection_type.name C
    • ...
  • B市

    • collection_type.name A
    • collection_type.name B
    • collection_type.name C
    • ...
  • C市

    • collection_type.name A
    • collection_type.name B
    • collection_type.name C
    • ... ...

最好的事情是按城市分组的数组,以便我可以在我看来这样:

    @cities.each do |city|
       ...
       city.each do |collection_type_name|
          ...
       end
    end

所以我试过这个:

    CollectionPoint.select("DISTINCT city, collection_type_id")

但是我只得到集合类型ID,而不是集合类型名称。此外,我不需要收集点ID(无论如何在查询结果中都是nil),所以我尝试了这个:

    CollectionPoint.includes(:collection_type).select("DISTINCT city, collection_types.name").references(:collection_types)

但这并没有把我带到任何地方。

我很沮丧,因为我知道必须有一个解决方案,我没有任何线索。也许你可以帮助我?

干杯

解决方案A

解决这个问题的最简单方法是将这行代码添加到我的控制器中:

    @cities = CollectionPoint.includes(:collection_type).select("DISTINCT city, collection_type_id").order(:city).group_by(&:city)

所以我可以相应地在我的视图中显示结果:

    - @cities.each do |city, collection_points|
        %h2
            = city
        = content_tag :ul, title: "... " + city do
            %li
                = link_to "... " + city, "/.../" + city
            - collection_points.each do |cp|
                %li
                    = link_to cp.collection_type.name + " in " + city, "/" + cp.collection_type.name + "/" + city

解决方案B

我想最好的解决方案是创建一个单独的城市模型并重新编写您的协议:

    class City < ActiveRecord::Base
       has_many :collection_points
   has_many :collection_types, through: :collection_points
    ...
    class CollectionPoint < ActiveRecord::Base
   belongs_to :collection_type
   belongs_to :city
    ...
    class CollectionType < ActiveRecord::Base
   has_many :collection_points
   has_many :cities, through: :collection_points
    ...

然后你可以做各种各样的事情,例如找到特定城市的所有收藏类型:

    City.where(name: "Cologne").first.collection_types

要列出所有不同城市中的所有不同集合类型,控制器操作如下所示:

    @cities = City.includes(:collection_types).distinct

在视图中你可以像:

    @cities.each do |city|
       city.name
       city.collection_types.each do |collection_type|
          collection_type.name
       end
    end

有关这方面的更多信息,请访问: Rails Model Assosiations

感谢您的帮助,伙计们!

2 个答案:

答案 0 :(得分:1)

您的CollectionName和CollectionType模型是否拥有并属于许多记录?如果是这样,这是我建议的设置:

<强> Collector.rb

class Collector < ActiveRecord::Base
   attr_accessible :collection_point_id, :collection_type_id
   belongs_to :collection_point
   belongs_to :collection_type
end

<强> CollectionPoint.rb

class CollectionPoint < ActiveRecord::Base
   attr_accessible :city
   has_many :collectors
   has_many :collection_types, :through => :collectors
end

<强> CollectionType.rb

class CollectionType < ActiveRecord::Base
   attr_accessible :name
   has_many :collectors
   has_many :collection_points, :through => :collectors
end

然后,您可以使用新的ActiveRecord关联,并使用组方法选择不同的记录:

@cities = CollectionPoint.select("DISTINCT(CITY)").all

然后用每个do方法打印@cities对象。

@cities.each do |city|
  ...
  city.collection_types.each do |collection_type_name|
    ...
  end
end

答案 1 :(得分:0)

如何使用活动记录 -

grouped_by_city = CollectionPoint.all.group_by { |cp| cp.city }

将返回

{ :city =>{stuff in here}}

然后你可以这样做:

- grouped_by_city.each do |city, info|

  %p= city

    %ul
      %li= info.collection_type.name #not sure what this should be?  depends on your models

如果你玩了一下我觉得它会对你有用。 irb是你最好的朋友!