如何在Rails中收集?

时间:2011-06-17 08:07:46

标签: ruby-on-rails

baza_managers = BazaManager.find(:all, 
  :conditions => ["or_unit_id != ?", 1]).collect { 
      |mou| [mou.email, mou.or_unit_id]}

respondent_emails = Respondent.find(:all).collect {|r| r.email }

ERROR:

from lib/scripts/baza_sync.rb:26:in `each'
from lib/scripts/baza_sync.rb:26

26行↓

baza_managers.each do |moi|
  if !respondent_emails.include?(moi)
    Respondent.create(:email => moi, :user_id => 1, :respondent_group_id => moi)
  end
end

错误我获取:

undefined method `email' for ["vadasd@test.test.com", 8]:Array (NoMethodError)

我不知道为什么我会收到此错误。

4 个答案:

答案 0 :(得分:1)

尝试:

baza_managers = BazaManager.find(:all, 
  :conditions => ["or_unit_id != ?", 1]).collect { 
      |mou| [mou.email, mou.or_unit_id]}

respondent_emails = Respondent.find(:all).collect {|r| r.email }

baza_managers.each do |moi|
  if !respondent_emails.include?(moi[0])
    Respondent.create(:email => moi[0], :user_id => 1, :respondent_group_id => moi[1])
  end
end

答案 1 :(得分:1)

使用以下代码修复您的代码:

if !respondent_emails.include?(moi[0])
  Respondent.create(:email => moi[0], :user_id => 1, :respondent_group_id => moi[1])
end

答案 2 :(得分:1)

我认为至少有一个错误不在于你使用collect的方式,而是在你通过baza_managers数组时在最后几行写的逻辑中。

使用此代码,条件respondent_emails.include?(moi)将始终为false,因为respondent_emails是一组电子邮件地址,但moi是一个类似["vadasd@test.test.com", 8]的数组,因此它们永远不会匹配。

我认为这个错误让你在行中犯了一个错误:

Respondent.create(:email => moi, :user_id => 1, :respondent_group_id => moi)

因为此行将被评估为(例如):

Respondent.create(:email => ["vadasd@test.test.com", 8], :user_id => 1, :respondent_group_id => ["vadasd@test.test.com", 8])

这可能不是你想要的。

最后,我建议你阅读the debugger rails guide,我经常使用调试器来确定这种代码和错误中的问题所在和哪里。

答案 3 :(得分:1)

我会按如下方式重写您的代码:

baza_managers = BazaManager.all(:conditions => ["or_unit_id != ?", 1]).
                  collect { |mou| [mou.email, mou.or_unit_id]}

respondent_emails = Respondent.find(:all).collect {|r| r.email }

baza_managers.each do |email, unit_id|
  unless respondent_emails.include?(email)
    Respondent.create(:email => email, :user_id => 1, 
      :respondent_group_id => unit_id)
  end
end

使用OUTER JOIN检测丢失的Respondents

,可以进一步优化此解决方案
BazaManager.all(
  :include    => "OUTER JOIN respondents A ON baza_managers.email = A.email",
  :conditions => ["baza_managers.or_unit_id != ? AND A.id IS NULL", 1]
).each do |bm|
  Respondent.create(:email => bm.email, :respondent_group_id => bm.or_unit_id,
    :user_id => 1)
end        

通过添加associationsnamed_scope可以使解决方案更加优雅和优化。

class BazaManager

  has_many :respondents, :foreign_key => :email, :primary_key => :email  

  named_scope :without_respondents, :include => :respondents, 
    :conditions =>["baza_managers.or_unit_id != ? AND respondents.id IS NULL", 1]

end

现在named_scope可以按如下方式使用:

BazaManager.without_respondents.each do |bm|
  Respondent.create(:email => bm.email, :respondent_group_id => bm.or_unit_id,
    :user_id => 1)
end