在将YAML文件加载到Rails之前,是否可以检查YAML文件是否已更新?

时间:2016-05-27 03:11:26

标签: ruby-on-rails yaml

我有一个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控制台中手动执行此操作。

1 个答案:

答案 0 :(得分:1)

使用find_or_initialize_by

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编辑记录(或者让实习生去做)......