代码之家  ›  专栏  ›  技术社区  ›  Trenton Tyler

将多个连接合并为一个方法

  •  0
  • Trenton Tyler  · 技术社区  · 6 年前

    我的应用程序中有一个用户可以有多个评估、计划和材料。在我的数据库中,它们之间已经存在关系。我想在一个选项卡中显示所有这些,而不必查询数据库太多次。

    我试着做一个方法,把它们全部合并到一个表中,但是没有成功。返回的错误如下: undefined method 'joins' for #<User:0x007fcec9e91368>

    def library
      self.joins(:materials, :assessments, :plans)
    end
    

    我的最终目标是只覆盖从连接返回的所有对象,这样它们就可以被显示,而不是有三个不同的变量需要被查询以减慢加载时间。你知道这怎么可能吗?

    class User < ApplicationRecord
      has_many :materials, dependent: :destroy
      has_many :plans, dependent: :destroy
      has_many :assessments, dependent: :destroy
    end 
    
    class Material < ApplicationRecord
      belongs_to :user
    end
    
    class Assessment < ApplicationRecord
      belongs_to :user
    end
    
    class Plan < ApplicationRecord
      belongs_to :user
    end
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Mate Solymosi    6 年前

    如果您只想预加载关联,请使用 includes :

    class User < ApplicationRecord
      # ...
    
      scope :with_library, -> { includes(:materials, :assessments, :plans) }
    end
    

    像这样使用:

    User.with_library.find(1)
    User.where(:name => "Trenton").with_library
    User.all.with_library
    # etc.
    

    一旦这些关联被预加载,您就可以将其用于 library 方法用特定用户的所有材料、评估和计划填充单个数组:

    class User < ApplicationRecord
      # ...
    
      def library
        [materials, assessments, plans].map(&:to_a).flatten(1)
      end
    end
    

    示例用例:

    users = User.all.with_library
    users.first.library
    # => [ ... ]
    

    更多信息: https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

        2
  •  0
  •   matthewd    6 年前

    喜欢 includes 结束 joins 除非你有特殊的理由这么做。 包括 将消除N+1查询,同时仍在关联中构造可用记录:然后可以像其他情况一样循环遍历所有内容。

    然而 ,在这种情况下,听起来你是从一个 User 实例:在这种情况下, 包括 (或 连接 )真的帮不上忙——没有N+1查询要消除。

    虽然避免在显示的每行中运行查询(N+1)很重要,但是一个查询和三个查询之间的差异可以忽略不计。(把所有东西挤在一起会增加开销。)对于这种用法,这是不必要的。