代码之家  ›  专栏  ›  技术社区  ›  lurker

基于使用同一表的多个关联的条件选择记录

  •  0
  • lurker  · 技术社区  · 5 年前

    我有一个Rails中的常见情况,我有一个有两个关联的模型。我希望能够根据一个或两个关联的条件搜索由模型定义的特定记录。

    问题是这两个关联使用同一个表。

    主要车型如下:

    class Resource < ActiveRecord::Base
      belongs_to :primary_item, class_name: 'Item', foreign_key: 'primary_item_Id'
      belongs_to :secondary_item, class_name: 'Item', foreign_key: 'secondary_item_Id'
      ...
    

    Item 型号:

    class Item < ActiveRecord::Base
      has_many :res_primary, class_name: 'Resource', foreign_key: 'primary_item_Id'
      has_many :res_secondary, class_name: 'Resource', foreign_key: 'secondary_item_Id'
      ...
    

    让我们假设一个 项目 有一个名为 name

    @resources.joins(:primary_item)
              .where("#{Item.table_name}.name like #{primary_search_string}")
    

    这个 primary_search_string 只是我想在 名称 . 这个很好用。类似的搜索也适用于辅助项。

    现在假设我希望用户能够搜索具有给定的主项名称、按名称指定的辅助项或两者(每个都有自己的名称)的资源。我会有一个 主搜索\u字符串 和一个 secondary_search_string nil 这就意味着我不想根据这个字符串缩小搜索范围。我想要的是根据它们是否是字符串,按其中一个或两个字符串筛选资源

    @resources = <some query that obtains an active record relation of resources>
    
    if primary_search_string then
      @resources = @resources.joins(:primary_item)
                             .where("#{Item.table_name}.name like #{primary_search_string}")
      if secondary_search_string then
        @resources = @resources.joins(:secondary_item)
                               .where("secondary_items_#{Item.table_name}.name like #{secondary_search_string}")
      end
    elsif secondary_search_string then
      @resources = @resources.joins(:secondary_item)
                            .where("#{Item.table_name}.name like #{secondary_search_string}")
    end
    

    请注意,如果我只连接一个表,那么表的名称是由 Item.table_name . 但是,如果我必须连接两个表,那么Rails必须通过使用关联名称进一步指定名称来区分表的第二个实例: secondary_items_#{Item.table_name} .

    我的问题是是否有一种更简单的方法来处理这个问题,它不需要引用 where 条款?因为我引用的是关联的表名,表名可能会有所不同,这取决于我是加入其中一个还是两个关联,所以最后我检查了搜索字符串以查找关联 ,这是确定我是否加入 项目 不止一次。在这个特殊的程序示例中,我可以检查它并忍受它的尴尬。但如果我不知道 @resources 以前加入了主要项目,我想根据次要项目进行筛选?在这种情况下,我不知道在 哪里 因为我不知道它是否已经存在了 join 不管你是不是被解雇了。

    我怀疑这里可能有更好的方法,这是我问题的本质。

    1 回复  |  直到 5 年前
        1
  •  0
  •   dlehman    5 年前

    如果您有两个独立的关联,但它们都属于同一类型的子对象(例如Resource),那么您可以将精力集中在查找 Resource primary_item_id secondary_item_id 父母的 Item

    Rails3/4本机不支持或查询,但一种强制执行的方法是查找 Resources 属于 项目

    ids = Resource.where(primary_item_id: @item.id).map(&:id)
    ids << Resource.where(secondard_item_id: @item.id).map(&:id)
    @special_resources = Resource.where(id: ids, name: 'Some Special Name')
    

    Rails 5支持“or”查询,因此更简单:

    resources = Resource.where(primary_item_id: @item.id).or(secondary_item_id: @item.id)
    @special_resources = resources.where(name: 'Some Special Name')