适当的嵌套循环,回到基本

时间:2013-08-15 07:41:07

标签: ruby-on-rails ruby

使用Rails 3.2。我想了解如何编写正确的递归循环。这是关联和控制器:

# country.rb
class Country < ActiveRecord::Base
  has_many :states
end

# state.rb
class State < ActiveRecord::Base
  belongs_to :country
  has_many :zones
  has_many :cities, :through => :zones
end

# zone.rb
class Zone < ActiveRecord::Base
  belongs_to :state
  belongs_to :city
end

# city.rb
class City < ActiveRecord::Base
   has_many :photos, :as => :attachable
end

# photo.rb
class Photo < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true
  has_attached_file :data, :options
end

# countries_controller.rb
class CountriesController < ApplicationController
  def show
    @country = Country.find(params[:id], :includes => [:states => [:cities => :photos]])
    @photos = @country.country_photos
  end
end

我将在下面写一个愚蠢的递归循环来解释我想要实现的目标:从城市获取照片:

# countries/show.html.erb
<%= @country.country_photos.inspect # just to test %>

# country.rb
class Country < ActiveRecord::Base
  def country_photos
    all_photos = []
    self.states.each do |state|
      state.cities.each do |city|
        city.photos.each do |photo|
          all_photos << photo
        end
      end
    end
  end
end
# Expected output: [photo_object_1, photo_object_2]

我尝试在map中使用country_photos

if (photos = state.map(&:cities).flatten.map(&:photos).flatten)
  photos
end

但它存在性能问题:执行400毫秒。

编写递归循环的正确方法是什么?欣赏是否给出了逐步说明。感谢。

2 个答案:

答案 0 :(得分:2)

使用has_many:through,您已经使用过它。

# country.rb
class Country < ActiveRecord::Base
  has_many :states
  has_many :cities, :through => :states
  has_many :photos, :through => :cities
end

# state.rb
class State < ActiveRecord::Base
  belongs_to :country
  has_many :zones
  has_many :cities, :through => :zones
end

# zone.rb
class Zone < ActiveRecord::Base
  belongs_to :state
  belongs_to :city
end

# city.rb
class City < ActiveRecord::Base
   has_many :photos, :as => :attachable
end

# photo.rb
class Photo < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true
  has_attached_file :data, :options
end

# countries_controller.rb
class CountriesController < ApplicationController
  def show
    @country = Country.find(params[:id])
    @photos = @country.photos
  end
end

答案 1 :(得分:0)

不确定性能,但您可能会尝试设置基准:

def country_photos
    Photo.where("city_id IN (select id from cities where cities.state_id IN (select states.id from states where country_id = ?))", self.id)
end

如果您的城市表包含country_id,则可以将其写为:

def country_photos
   Photo.where("city_id IN (select id from cities where cities.country_id = ?)", self.id)
end