【问题标题】:Best way to refactor this without making as many calls as I am?最好的方法来重构它而不像我一样拨打电话?
【发布时间】:2011-04-01 19:07:08
【问题描述】:

我正在尝试循环浏览其中的一些块。他们基本上缩小了满足一系列属性的人的数量。

如果这看起来真的很混乱,我深表歉意,但我的数据库确实在处理这个问题,而且我知道有更好的方法。我现在只是迷失了策略。

我的代码:

def count_of_distribution

#beginning with an array..
array_of_users = []

# any matching zip codes? ..
# zip_codes
@zip_codes = self.distributions.map(&:zip_code).compact
unless @zip_codes.nil? || @zip_codes.empty? 
  @matched_zips = CardSignup.all.map(&:zip_code) & @zip_codes
  @matched_zips.each do |mz| 
    CardSignup.find(:all, :conditions => ["zip_code = ?", mz]).each do |cs|
     array_of_users << cs.id
    end
  end
end

# any matching interests?..
# interest
@topics = self.distributions.map(&:me_topic).compact
unless  @topics.nil? || @topics.empty?
  @matched_topics = MeTopic.all.map(&:name) & @topics
  @matched_topics.each do |mt|
    MeTopic.find(:all, :conditions => ["name = ?", mt]).each do |mt2|
      mt2.users.each do |u|
        array_of_users << u.card_signup.id if u.card_signup
      end
    end
  end
end

# any matching sexes?..
# sex
@sexes = self.distributions.map(&:sex).compact
unless @sexes.nil? || @sexes.empty?
  @matched_sexes = CardSignup.all.map(&:sex) & @sexes
  @matched_sexes.each do |ms|
    CardSignup.find(:all, :conditions => ["sex = ?", ms]).each do |cs|
      array_of_users << cs.id
    end
  end
end

  total_number = array_of_users.compact.uniq

  return total_number
end

这是有史以来最尴尬的结果:

Completed in 51801ms (View: 43903, DB: 7623) | 200 OK [http://localhost/admin/emails/3/distributions/new]

更新的答案它被截断但仍然对数据库造成巨大的损失

  array_of_users = []

  @zip_codes = self.distributions.map(&:zip_code).compact
  @sexes = self.distributions.map(&:sex).compact

  @zips_and_sexes = CardSignup.find(:all, :conditions => ["gender IN (?) OR zip_code IN (?)", my_sexes, my_zips])
  @zips_and_sexes.each{|cs| array_of_users << cs.id }

  @topics = self.distributions.map(&:me_topic).compact
  @all_topics = MeTopic.find(:all, :conditions => ["name IN (?)", @topics])
  array_of_users << CardSignup.find(:all, :conditions => ["user_id IN (?)", @all_topics.map(&:users)]).map(&:id)

【问题讨论】:

标签: ruby-on-rails ruby arrays activerecord refactoring


【解决方案1】:

您正试图让 rails 通过一系列循环来完成所有计算;难怪需要这么长时间。

这很难理解,但也许不要使用.each 循环,而是尝试立即取出你想要的所有内容,然后使用.group_by(&amp;:attribute)

或者,如果您的最终结果只是卡注册。

您似乎正试图让所有用户都拥有想要的东西、zip、主题或性别。所以,让数据库来做吧。

my_zips = @zip_codes = self.distributions.map(&amp;:zip_code).compact.join(", ") my_sexes = @sexes = self.distributions.map(&amp;:sex).compact.join(", ")

all_cards = CardSignup.find(:all, :conditions =&gt; ["sex IN (?) OR zip_code IN (?)", my_sexes, my_zips])

my_topics = @topics = self.distributions.map(&amp;:me_topic).compact.join(", ") all_topics = MeTopic.find(:all, :conditions =&gt; ["name = ?", my_topics])

more_cards = all_topics.map{|x| x.users}.map{|n| n.card_signup} total_number = (all_cards + more_cards).flatten.uniq

我希望这是一个更好的答案。

【讨论】:

  • group_by 如何节省计算时间?
  • 您要寻找的最终结果究竟是什么?
  • 分布是发送电子邮件的特征选择。当人们注册订阅时,他们会选择自己的特征。我正在尝试将分发中选择的特征与 CardSignups 中的属性匹配
  • @Trip 通过发布您的数据库架构一些示例数据以及您尝试实现的查询结果类型,您可能会获得更好的结果。
  • 是的,我想我错过了你的追求。
【解决方案2】:

来了。它现在运行速度超快:

array_of_users = []

# zips and sexes
@zip_codes = self.distributions.map(&:zip_code).compact
@sexes = self.distributions.map(&:sex).compact
@zips_and_sexes = CardSignup.find(:all, :conditions => ["gender IN (?) OR zip_code IN (?)", @sexes, @zip_codes])
@zips_and_sexes.each{|cs| array_of_users << cs.id }

# interest
@topics = self.distributions.map(&:me_topic).compact
@selected_topics = MeTopic.find(:all, :conditions => ["name in (?)", @topics]).map(&:id)
@matched_users = ActiveRecord::Base.connection.execute("SELECT * FROM `me_topics_users` WHERE (me_topic_id IN ('#{@selected_topics.join("', '")}') )")
@list_of_user_ids = []
@matched_users.each{|a| @list_of_user_ids << a[0] }
@list_of_user_ids.uniq!
array_of_users << CardSignup.find(:all, :conditions => ["user_id IN (?)", @list_of_user_ids]).map(&:id)

# age
@ages = self.distributions.map(&:age).compact
@ages_array = []
@ages.each{|a| @ages_array << how_old(a) }
@ages_array.each{|aa| array_of_users << aa.id}

array_of_users << CardSignup.all.map(&:id) if array_of_users.flatten.empty?
total_number = array_of_users.flatten.uniq

return total_number

【讨论】:

    猜你喜欢
    • 2012-04-07
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多