使用Ruby on Rails导入CSV

时间:2015-12-17 16:07:25

标签: ruby-on-rails ruby csv import

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

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

  1. 导入文件 - 我保存文件
  2. 将每一行解析为字段
  3. 执行检查电子邮件地址的唯一性(我保存电子邮件记录,以便在保存父记录 - 联系人之前执行此操作)。
  4. *问题:
     4.在我保存电子邮件地址记录时,它缺少联系人ID /所有者 - 如果在创建联系人之前进程失败,则可能会创建孤立情况),因为它在保存联系人之前保存了孩子(电子邮件)(和我不认为或想做这个)

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

      • 并根据姓名进行检查 - 有些情况下,我知道2个同名的人(例如David Smith,然后会追加2个人) 不同的人在一起)
      • 如果我保存所有联系人(然后检查电子邮件唯一性),我将创建大量额外的联系人。
    2. 因为它目前有效,检查重复的电子邮件是在我的整个数据库上,因为我没有contact_id(与user_id aka owner_id相关联)

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

    4. 这是我初始处理行的代码

        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文件,以便在创建联系人记录或Email_address记录之前可以检查基于email_address的重复项?我想根据contact.first_name,contact.last_name,email.address
      • 检查我现有数据库和文件中其他记录的重复项。

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

1 个答案:

答案 0 :(得分:0)

  

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

不,只需将它们存储在变量

  

我是否可以通过这种方式处理CSV文件   在创建之前检查基于email_address的重复项   联系记录或Email_address记录?我想检查一下   与我现有的数据库和其他记录重复   文件基于contact.first_name,contact.last_name,email.address

find_or_create_by意味着要做到这一点。来自文档:

  

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

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