【问题标题】:Import CSV with Ruby on Rails使用 Ruby on Rails 导入 CSV
【发布时间】:2016-03-24 04:33:11
【问题描述】:

我想在创建或保存任何模型(联系人-父级或电子邮件-子级)之前导入 Outlook CSV 文件并根据电子邮件(子级)检查重复项

步骤(目前如何运作,但解决方案有缺陷)

  1. 导入文件 - 我保存文件
  2. 将每一行解析为字段
  3. 执行检查电子邮件地址的唯一性(我正在保存电子邮件记录以在保存父记录 - 联系人之前执行此操作)。

*问题:
(我不认为或不想这样做)

  1. 但是,如果我仅根据姓名保存联系人(例如 David 史密斯),我可能有:

    • 并根据姓名进行检查 - 在某些情况下,我认识 2 个同名的人(例如 David Smith,然后将附加 2 不同的人在一起)
    • 如果我保存所有联系人(然后检查电子邮件唯一性),我将创建很多额外的联系人。
  2. 按照目前的工作方式,检查重复电子邮件在我的整个数据库中,因为我没有联系人 ID(与 user_id aka owner_id 相关联)

  3. 我尝试先保存联系人,但后来意识到这会导致我有很多额外的记录(非常混乱)。

这是我初始处理该行的代码


  def process_row(smart_row)
    new_contact, existing_records = smart_row.to_contact

    self.contact = ContactMergingService.new(csv_file.user, new_contact, existing_records).perform
    log_processed_contacts new_contact
    init_contact_info self.contact
    self.contact.required_salutations_to_set = true # will be used for envelope/letter saluation
    if contact.first_name || contact.last_name || contact.email_addresses.first || contact.phone_numbers.first
      self.contact.save!
      csv_file.increment!(:total_imported_records)
    end
  end

这是上面调用的第一个方法(在保存联系人之前保存电子邮件)


   def to_contact
      existing_emails = existing_phone_numbers = nil
      contact = Contact.new.tap do |contact|
        initiate_instance(contact, CONTACT_MAPPING)
        address = initiate_instance(Address.new, ADDRESS_MAPPING)
        contact.addresses << address if address
        email_addresses, existing_emails = initialize_emails(EMAIL_ADDRESS_FIELDS)
        contact.email_addresses << email_addresses
        phone_numbers, existing_phone_numbers = initialize_phone_numbers(PHONE_TYPE_MAPPINGS)
        contact.phone_numbers << phone_numbers
        contact
      end
      existing_records = []
      existing_records << existing_emails
      existing_records << existing_phone_numbers
      existing_records.flatten!
      existing_records.compact!
      [contact,  existing_records]
    end

这是我保存电子邮件地址时的代码(之后我将保存联系人)


def initialize_emails email_fields
  email_addresses = []
  email_fields.each do |field|
    value = evaluate_value field
    if value.present?
      new_email = EmailAddress.find_or_create_by(email: value, primary: (primary_email_field?(field)))
      if new_email.save
        email_addresses << new_email
      end
    end
  end
  existing_emails = email_addresses.select{ |email_address| email_address.owner_id.present?}
  [email_addresses, existing_emails]
end

我有 3 个模型:

User (has many)
  has_many :contacts
  has_many :email_campaigns  has_many :email_messages

Contacts:  First Name and Last Name
  belongs_to :user, counter_cache: true
  has_many :addresses, as: :owner, dependent: :destroy
  has_many :phone_numbers, as: :owner, dependent: :destroy
  has_many :email_addresses, as: :owner, dependent: :destroy
  accepts_nested_attributes_for :email_addresses, allow_destroy: true
``
Email:  email_address - polymorphic
  belongs_to :owner, polymorphic: true, touch: true

所以我的问题是:

  • 我是否需要保存记录(联系人或电子邮件)才能 检查重复项?
  • 有没有一种方法可以处理 CSV 文件,以便在创建联系人记录或电子邮件地址记录之前根据电子邮件地址检查重复项?我想根据 contact.first_name、contact.last_name、email.address 对我现有的数据库和文件中的其他记录检查重复项

有什么想法吗? 非常感谢。 安妮

【问题讨论】:

    标签: ruby-on-rails ruby csv import


    【解决方案1】:

    我是否需要保存记录(联系人或电子邮件)才能 检查是否有重复项?

    不,只是将它们存储在变量中

    有没有一种方法可以让我处理 CSV 文件 在创建之前根据 email_address 检查重复项 联系记录还是 Email_address 记录?我想检查 与我现有的数据库和其他记录重复 基于contact.first_name、contact.last_name、email.address的文件

    find_or_create_by 专门用于执行此操作。来自文档:

    查找具有给定属性的第一条记录,或创建一条记录 如果找不到,则带有属性

    也就是说,您可以传递一个电子邮件地址,该方法将找到具有该值的记录或创建一个新记录。

    【讨论】:

    • 您好 Brito,感谢您的快速回复。我正在努力解决的问题是:如果我找到联系人(例如大卫史密斯)上的 find_or_create_by - 并找到匹配项,它可能不是真正的匹配项,因为孩子(email.address 不匹配)。所以真正的唯一标识符是孩子,因为它现在可以工作,所以我在拥有父母之前在 email.address 上执行 find_or_create (我真的不想这样做)。
    • 我会告诉你,但我想我还是被卡住了。
    猜你喜欢
    • 2012-02-14
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 2011-11-29
    • 2018-11-06
    • 2020-05-05
    相关资源
    最近更新 更多