Rails Rake任务 - 如何删除记录

时间:2013-09-17 20:42:18

标签: ruby-on-rails rake

我正在尝试使用每日RAKE任务将我的应用中的用户表与CSV文件同步。

我的import.rake任务成功导入了表中找不到的记录(find_or_create_by_username),但我不知道如何从表中删除CSV文件中不再存在的记录。我应该使用什么而不是“find_or_create_by_username”来实现这一目标?提前谢谢。

  #lib/tasks/import.rake

  desc "Import employees from csv file"
  task :import => [:environment] do

  file = "db/testusers.csv"

usernames = [] # make an array to collect names
CSV.foreach(file, headers: true) do |row|
    Employee.find_or_create_by_username({
      # Add this line:
      username = row[0]
      :username => username,
      :last_name => row[1],
      :first_name => row[2],
      :employee_number => row[3],
      :phone => row[4],
      :mail_station => row[5]
    }
    )
    # Collect the usernames
    usernames << username
    end
# Delete the employees (make sure you fire them first)
Employee.where.not( username: usernames ).destroy_all
end

3 个答案:

答案 0 :(得分:1)

您可以通过执行以下操作来实现此目的:

#lib/tasks/import.rake
require 'csv'

desc "Import employees from csv file"
task :import => [:environment] do

    file = "db/users.csv"
    employee_ids_to_keep = []

    CSV.foreach(file, headers: true) do |row|
      attrs = {
        :username => row[0], :last_name => row[1], :first_name => row[2], 
        :employee_number => row[3], :phone => row[4],:mail_station => row[5]
      }
      # retrieves the Employee with username
      employee = Employee.where(username: attrs[:username]).first

      if employee.present? # updates the user's attributes if exists
        employee.update_attributes(attrs)
      else # creates the Employee if does not exist in the DB
        employee = Employee.create!(attrs)
      end

      # keeps the ID of the employee to not destroy it
      employee_ids_to_keep << employee.id 
    end

    Employee.where('employees.id NOT IN (?)', employee_ids_to_keep).destroy_all
end

答案 1 :(得分:0)

获取数据库中所有ID的列表,并将它们存储在一个集合中。然后,在进行导入时,从集合中删除有效的员工。完成后,需要从数据库中删除集合中剩余的任何ID。

像这样......

existing_ids = Employee.pluck(:id).to_set
CSV.foreach(file, headers: true) do |row|
  employee = Employee.find_or_create_by.....
  existing_ids.delete(employee.id)
end     
Employee.destroy(*existing_ids.to_a) unless existing_ids.empty?

答案 2 :(得分:0)

usernames = [] # make an array to collect names
CSV.foreach(file, headers: true) do |row|
    username = row[0]
    Employee.find_or_create_by_username({
      :username => username,
      :last_name => row[1],
      :first_name => row[2],
      :employee_number => row[3],
      :phone => row[4],
      :mail_station => row[5]
    }
    )
    # Collect the usernames
    usernames << username
    end
# Delete the employees (make sure you fire them first)
Employee.where.not( username: usernames ).destroy_all

where.not当然可以使用rails 4。