我有一个YAML文件,它将一组问题加载到我的rails DB中。偶尔我会对Question.yml文件进行更改(例如,我可能想稍微更改问题文本),并且由于我将这些加载到rails问题模型的方式,数据库拒绝更新(因为我的数据库中已经存在一个带有该ID的问题)。我现在对问题进行更频繁的更改并希望它更灵活,因此我可以在上传之前检查YAML文件以查看是否例如最后保存的时间已经改变,那么只有在发生这种情况时才真正更新数据库?
一个示例问题:
- id: 1
question_text: Why does this company need to buy your products or services?
answer_type: Text Field
next_question_id_yes: 2
next_question_id_no: ~
collectable: ~
sale_stage: Need
文件当前如何加载到数据库中:
File.open("#{Rails.root}/config/initializers/questions.yml", 'r') do |file|
YAML::load(file).each do |record|
Question.create(record) unless Question.exists?(record)
end
end
这种方法可以快速检查记录是否已经存在(因为exists?方法只检查问题的ID),但没有用,因为我没有改变问题ID - 只有另一个DB下面的字段。正如您所看到的,我需要id保持静态,因为这构成了决策树的一部分,每个问题都需要知道跟随它的问题ID(取决于answer_type和提供的答案)。
目前,当我尝试更新YAML文件然后在应用程序中使用它时,我收到以下错误:
ActiveRecord::RecordNotUnique: PG::Error: ERROR: duplicate key value violates unique constraint "questions_pkey"
DETAIL: Key (id)=(1) already exists.
: INSERT INTO "questions" ("answer_type", "created_at", "id", "next_question_id_yes", "question_text", "sale_stage", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"
我是否可以通过某种方式存储YAML文件本身的状态,如果已经更新,那么我可以销毁所有旧记录并将新的YAML文件作为福音上传?
P.S。如果由于某些原因我无法想到这是一个愚蠢的想法,请也让我知道。这似乎有点浪费资源,但我希望将来会添加更多问题并为用户更新,所以我需要这种灵活性,而无需在rails控制台中手动执行此操作。
答案 0 :(得分:1)
File.open("#{Rails.root}/config/initializers/questions.yml", 'r') do |file|
YAML::load(file).deep_symbolize_keys.each do |record|
q = Question.find_or_initialize_by(id: record[:id]))
q.assign_attributes( record.except(:id) )
q.save! if q.new_record? || q.changed?
end
end
虽然从长远来看,创建一个基本的CRUD控制器可能要容易得多,这样你就可以通过GUI编辑记录(或者让实习生去做)......