【问题标题】:Rails: preloading a has_many through relation in the controllerRails:通过控制器中的关系预加载has_many
【发布时间】:2015-12-09 01:28:04
【问题描述】:

希望我能解释清楚。

  • 用户有_many 个通知和has_many 电影通过 通知。一部电影有_许多预告片。

  • Notifications 有 3 列:user_id、movie_id 和 website。

  • 在预告片#index 上,我正在渲染 @trailers 并且每个 @trailer 都会渲染 3 x ajax notification_forms(每个表单只是一个按钮,一个用于 每个“网站”选项。当用户点击这个按钮时,会发送一个ajax请求来创建一个新的通知记录)

  • 我会跟踪按下了哪些按钮(通过查看该用户/电影是否存在通知)

我担心的是,因为我只预加载了@trailers,所以我目前正在对预告片的每次迭代进行 3 次新的数据库调用。

_notification_form.html.erb(在每个预告片上被调用 3 次)

<% if trailer.movie.tracked?(current_user, "netflix") %>
   ## do some css stuff on the button to show notification already set

电影.rb:

def tracked?(user, website)
    user.notifications.where(movie_id: self.id, website: website).first
  end

因此,每次渲染部分预告片时,我都会进行 3 次 DB 调用。处理这种情况的正确方法是什么?

【问题讨论】:

    标签: ruby-on-rails ajax


    【解决方案1】:

    由于您只检查current_user 的状态,并且每个Trailer 都知道它的movie_id,因此您只需加载UserNotifications 并检查它们是否有Trailers 'movie_ids:

    tracked = current_user.notifications
    tracked.detect { |n| n.movie_id == trailer.movie_id && n.website == 'netflix' }
    

    如果User 可能为Notifications,您可以将集合限制为仅Notifications 用于您正在显示的页面上的Trailers:

    tracked = current_user.notifications.where(movie_id: trailers.map(&:movie_id))
    

    加载它,然后在决定如何呈现按钮时检查它。您可以通过创建包含 [movie_id, website] 对的 Set 来提高效率,这将在恒定时间内进行查找。

    tracked = Set.new(
      current_user.nofications
        .where(movie_id: trailers.map(&:movie_id))
        .pluck(:movie_id, :website)
    )
    tracked.include?([trailer.movie_id, 'netflix'])
    

    此策略对您来说很快,因为它完全适合您检查的数据。如果您需要更灵活的东西来最大限度地减少数据库查询,请查看热切加载与includespreloadeager_load 的关联。 3 ways to do eager loading (preloading) in Rails 3 & 4 很好地描述了这些方法之间的差异。这些都在您的初始关系加载期间工作(也就是说,如果您还没有加载任何内容),但是当您已经加载了部分数据时(例如,您有 Trailers 但没有 Moviess 或 @ 987654347@s),您可以使用ActiveRecord::Associations::Preloader 有效地加载其余部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      相关资源
      最近更新 更多