Ruby 2.3.0,Rails 4.2.4,实际上使用的是postgreSQL而不是SQLite
为清晰起见而更新
我有一个大的csv文件(每天外部更新和下载),并编写了一个更新Rails数据库表的方法。 我不希望该方法在不验证唯一性的情况下将所有行附加到数据库,因此我将这个出色的解决方案(How do I make a column unique and index it in a Ruby on Rails migration?)与add_index
一起使用。
我正在使用rake文件来存储可执行更新代码,并在我的终端中输入$ rake update_task
(如果表与导入的csv行没有重复,则可以正常工作)。这个问题是数据库ABORTS(rake aborted!
)在遇到第一个重复条目(ERROR: duplicate key value violates unique constraint
)时的rake。
如何在避免中止/失败的同时删除/不保存任何重复项?我不能简单地删除数据库表并每天重新加载它。这是架构:
ActiveRecord::Schema.define(version: 20160117172450) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "tablename", force: :cascade do |t|
t.string "attr1"
t.string "attr2"
t.string "attr3"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "tablename", ["attr1", "attr2", "attr3"], name: "index_tablename_on_attr1_and_attr2_and_attr3", unique: true, using: :btree
end
和我的rake任务在lib / tasks / file_name.rake内容中:
desc "Download data and update database table"
task :update_task => :environment do
u = CorrectClassName.new
u.perform_this
end
和CorrectClassName
位于app / directory1中的.rb文件中:
class CorrectClassName
def perform_this
something = ClassWithUpdateCode.new
something.update_database
end
end
和ClassWithUpdateCode
位于app / directory2中的.rb文件中:
require 'csv'
class ClassWithUpdateCode
def update_database
csv_update = File.read(Rails.root.join('lib', 'assets', "file_name.csv"))
options = {:headers => true}
csv = CSV.parse(csv_update, options)
csv.each do |row|
tm = TableModel.new
tm.attr1 = row[0]
tm.attr2 = row[1]
tm.attr3 = row[2]
tm.save # maybe I can use a different method or if statement here?
end
end
end
更新:@ Kristan的解决方案在下面工作,但这里是开始/救援/结束处理的地方:
在app / directory2中的.rb文件中:
require 'csv'
class ClassWithUpdateCode
def update_database
csv_update = File.read(Rails.root.join('lib', 'assets', "file_name.csv"))
options = {:headers => true}
csv = CSV.parse(csv_update, options)
csv.each do |row|
tm = TableModel.new
begin
tm.attr1 = row[0]
tm.attr2 = row[1]
tm.attr3 = row[2]
tm.save
rescue ActiveRecord::RecordNotUnique
end
end
end
end
答案 0 :(得分:1)
rake
正在淘汰,因为当您尝试保存违反表格唯一性约束的记录时会引发异常。防止这种情况的最简单方法是捕获并忽略异常。我假设您的记录是在u.perform_this
期间创建的。
task :update_task => :environment do
u = CorrectClassName.new
begin
u.perform_this
rescue ActiveRecord::RecordNotUnique
# move on
end
end
另一种选择是在您的Rails模型中添加uniqueness validation,然后在保存之前检查valid?
或致电create
(不是create!
),而不是class CorrectClassName < ActiveRecord::Base
validates_uniqueness_of :attr1, scope: [:attr2, :attr3]
end
。提高验证例外。
task :update_task => :environment do
u = CorrectClassName.new(data)
u.perform_this if u.valid?
end
{{1}}