如何改进这段代码

时间:2011-10-21 12:50:18

标签: ruby-on-rails ruby activerecord enumerator

我正在经营一家网上手提包商店,手提包可以是四种颜色 - 黑色,棕色,橙色和红色。我注意到黑色手袋比棕色手袋等卖得更早。这意味着人们最喜欢黑色手提包。

在网上商店的主页上,我想选择并以网格布局显示10个包。所以我从选择黑色袋子开始。如果我的库存中有10个或更多的黑色袋子,那么我就停下来,不要寻找其他颜色的其他袋子。但是,如果我有5个黑色袋子,那么我会继续寻找棕色袋子。如果我还没有10个袋子,那么在添加那些棕色袋子后,我会寻找橙色袋子等等。

以下是我尝试将解决方案实现为Rails模型方法:

class Handbag < ActiveRecord::Base
  belongs_to :store
  attr_accessor :color
end

class Store < ActiveRecord::Base
  has_many :handbags

  def handags_for_display
    selected_handbags = []
    ["black", "brown", "orange", "red"].each do |color|
      bags = get_handbags_by_color(color)
      selected_bags += bags
      if selected_bags.size >= 10
        selected_handbags = selected_handbags[0..9]
        break
      end
    end
    selected_handbags
  end

  private
  def get_handbags_by_color(color)
    handbags.where("color = ?", color).limit(10)
  end
end

虽然这有效,但我很好奇是否有更好的方法来编写它。特别是,我认为这段代码可以转换为使用Ruby的枚举器。

3 个答案:

答案 0 :(得分:0)

您应该立即查询数据库:

@page_offset = ((params[:page].to_i-1)*10) || 0
Handbag.order("color ASC").limit(10).offset(@page_offset)

幸运的是,颜色已经按字母顺序排列。

答案 1 :(得分:0)

您可以尝试这样的递归函数。这可以按预期工作(运行它会给你{:black => 1, :brown => 8, :orange => 1}),你可以改变get_handbags_by_color来改为使用Rails。

@bags = {
  :black => 1,
  :brown => 8,
  :orange => 10,
  :red => 10
}

@handbag_order = [:black, :brown, :orange, :red]
@max_bags = 10

def get_handbags_by_color(color,limit)
  num = @bags[color]
  num > limit ? limit : num
end

def handbags_for_display(index = 0, total = 0)
  color = @handbag_order[index]
  return {} unless color
  handbags = {color => get_handbags_by_color(color,@max_bags - total)}
  total += handbags.values.inject{|sum,x| sum+x}

  handbags.merge!(handbags_for_display(index+1, total)) unless(total >= @max_bags)
  handbags
end

handbags = handbags_for_display

答案 2 :(得分:-1)

def handags_for_display
     handbags = Array.new
     [{ :color => 'black', :count => 5 }, { :color => 'brown' , :count => 2 }, { :color => 'orange', :count => 1 }, { :color => 'red', :count => 1}].each do |handbag|
          handbags+=Handbag.where("color = ?", handbag[:color]).limit(handbag[:count])
     end
     handbags
end