Ruby on rails RubyonRails中更好的递归循环

Ruby on rails RubyonRails中更好的递归循环,ruby-on-rails,ruby,Ruby On Rails,Ruby,使用Rails 3.2。假设我想要两个选项: 获取所有旅行照片 获取第一张旅行照片 我有以下代码: # trip.rb class Trip < ActiveRecord::Base has_many :trip_days def trip_photos if (photos = trip_days.map(&:spots).flatten.map(&:photos).flatten.map) photos.each do |photo|

使用Rails 3.2。假设我想要两个选项:

  • 获取所有旅行照片
  • 获取第一张旅行照片
  • 我有以下代码:

    # trip.rb
    class Trip < ActiveRecord::Base
      has_many :trip_days
    
      def trip_photos
        if (photos = trip_days.map(&:spots).flatten.map(&:photos).flatten.map)
          photos.each do |photo|
            photo.url(:picture_preview)
          end
        end 
      end
    
      def trip_photo
        trip_photos.first
      end
    end
    
    # trip_day.rb
    class TripDay < ActiveRecord::Base
      belongs_to :trip
      has_many :trip_day_spots
      has_many :spots, :through => :trip_day_spots
    end
    
    # trip_day_spot.rb
    class TripDaySpot < ActiveRecord::Base
      belongs_to :trip_day
      belongs_to :spot
    end
    
    #spot.rb
    class Spot < ActiveRecord::Base
    end
    
    # trips_controller.rb
    class TripsController < ApplicationController
      def index    
        @trips = Trip.public.paginate(:page => params[:page], :per_page => 25)
      end
    end
    
    #trip.rb
    类Trip:行程\u天\u点
    结束
    #trip\u day\u spot.rb
    类TripDaySpotparams[:page],:per_page=>25)
    结束
    结束
    

    正如所料,
    trip\u photos
    方法会生成大量SQL查询。我想知道是否有更好的方法可以做到这一点?

    这是因为N+1查询。在这种情况下,我们需要急切地加载基本对象的所有关联,这样当您调用其关联对象时,它不会触发任何获取它们的查询,只是从缓存对象中获取它们

    希望这能起作用,但不需要测试。我假设并编写了以下查询

    def trip_photos
      user_trip_days = trip_days.includes(:spots => :photos)
      photos = user_trip_days.collect {|trip_day| trip_day.spots.map(&:photos).flatten}.flatten
      photos.each do |photo|
        photo.url(:picture_preview)
      end if photos
    end
    
    如果您有任何错误,请告诉我

    有关在ActiveRecord中加载关联对象的详细信息,请浏览


    而且

    这可能不是最简单的rails-y方式,但是如果你真的想在一次点击中获得所有的位置,你可以做如下事情:

    def spots
     Spot.joins("join trip_days_spots on spots.id = trip_days_spots.spot_id join trip_days on trip_days.id = trip_days_spots.trip_day_id join trips on trips.id = trip_days.trip_id").where("trips.id = ?", self.id)
    end
    
    然后将循环更改为:

    def trip_photos
      spots.map(&:photos).flatten.each do |photo|
        photo.url(:picture_preview)
      end
    end
    

    代码工作正常,但要快速加载,只需添加
    :include

    # trips_controller.rb
    class TripsController < ApplicationController
      def index    
        @trips = Trip.public.paginate(:include => [:trip_days => [:spots => :photos]], :page => params[:page], :per_page => 25)
      end
    end
    
    #trips_controller.rb
    类TripsController<应用程序控制器
    def索引
    @trips=Trip.public.paginate(:include=>[:Trip\u days=>[:spots=>:photos]],:page=>params[:page],:per\u page=>25)
    结束
    结束
    
    谢谢。通过
    trip\u photos
    运行
    trip\u photo
    时,我得到了类似
    的东西,但由于我要出去,所以没有时间修复它。它应该返回
    .url(:picture\u preview
    )。