【问题标题】:Load seed data from YML to db with one-to-many relation in Rails在 Rails 中使用一对多关系将种子数据从 YML 加载到 db
【发布时间】:2018-07-13 22:46:36
【问题描述】:

我是 Rails 的新手,但遇到了问题。像这样从 YML 文件加载数据的最佳方法是什么:

   projects:
 - title: 'family'
   todos:
    - text: 'Get some milk'
      isCompleted: false
    - text: 'Cook some bacon'
      isCompleted: true
    - text: 'Repair the front door'
      isCompleted: false
 - title: 'work'
   todos:
    - text: 'Call my boss'
      isCompleted: true
    - text: 'Finish my work tasks'
      isCompleted: true
    - text: 'Get fired'
      isCompleted: false
 - title: 'therest'
   todos:
    - text: 'Do something'
      isCompleted: false
    - text: 'Ask a question on stackoverflow'
      isCompleted: false

所以,我有两个模型 - 待办事项模型(文本和 isCompleted 字段)和项目模型(只有标题字段)。项目 has_many 待办事项。 我试着这样做:

seed_file = Rails.root.join('db', 'seeds', 'seeds.yml')
config = YAML::load_file(seed_file)
Project.create!(config)

但我有一个错误:

ActiveModel::UnknownAttributeError: unknown attribute 'projects' for Project.

我该如何解决这个问题?

【问题讨论】:

  • 我认为您的 YAML 中有复制粘贴错误,是吗?我认为那不是有效的语法。
  • 你的意思是这个'-'符号吗?是的,他们在这里似乎完全错了。但现在我得到另一个错误 - Psych::SyntaxError: (/Users/Aldres/Desktop/tasktracker/db/seeds/seeds.yml): did not find expected key while parsing a block mapping at line 2 column 3 /Users/Aldres/Desktop/tasktracker/db/seeds.rb:9:in '`
  • 我在想你的缩进似乎是错误的。我不知道为什么projects 像您在帖子中那样缩进。而且,如果projects 下的每一个都是project,那么您似乎需要迭代config 变量来创建您的Projects
  • 是的,类似的。虽然,您必须检查 config 的结构才能获得正确的语法。它可能类似于config[:projects].each do |project|。如果您需要更多指导,可以将config 添加到您的 OP。

标签: ruby-on-rails ruby


【解决方案1】:

正如聊天中所讨论的,您需要使用以下内容:

config[:projects].each do |project|
  todos = project[:todos]
  project.delete(:todos)
  new_project = Project.create(project)
  todos.each do |todo|
    new_project.todos.create(todo)
  end
end

假设您的 YML 格式正确。

【讨论】:

  • 没有必要迭代项目或待办事项,更不用说两者了。 @robertoplancarte 的答案更好
  • 任何情况下都不需要迭代?还是在某些情况下?如果是后者,那么什么情况下不需要迭代?
【解决方案2】:
class Project < ApplicationRecord
  has_many :todos
  accepts_nested_attributes_for :todos
end

Project.create!(title: 'family', 
                todos_attributes:[{text:'1',isCompleted:false}, 
                                 {text:'2',isCompleted:false},...])

如果您使用 YAML,则必须阅读 YAML,然后将其转换为 rails 可以从中创建实体的东西。把它放在你的种子文件中:

yaml_hash = YAML.load(File.read('db/your_yaml.yaml'))

rails_arr_of_hashes = yaml_hash['projects'].map{|p| {title: p['title'], todos_attributes: p['todos'] }

Project.create(rails_arr_of_hashes)

将你的 YAML 放入 db/your_yaml.yaml 然后运行

rails db:seed

记得将accepts_nested_attributes_for :todos 添加到项目模型中。

祝你学习 Rails 好运:)

【讨论】:

  • 问题是,我必须使用 YAML。而且我不知道,我应该如何读取这个文件并将其转换为实体。
  • 如果你保持 YAML 结构在你的问题中应该可以工作......只是缩进正确
  • 看起来合乎逻辑。但是现在有了类型。 TypeError: no implicit conversion of String into Integer /Users/Aldres/Desktop/tasktracker/db/seeds.rb:10:in []' /Users/Aldres/Desktop/tasktracker/db/seeds.rb:10:in &lt;top (required)&gt;' 第 10 行是 rails_arr_of_hashes = yaml_hash['projects'].map{|p| {title: p['title'], todos_attributes: p['todos'] }}
  • 啊,我的错。我的 YML 文件中有一点拼写错误。现在一切都好。谢谢你:)
  • 如果您无法更改 yaml 文件中的 todos 键的名称,您可以使用 gsub 将其更改为 todos_attributes before 加载文件为YAML 而不是迭代散列 afterYAML.load(File.read('projects.yml').gsub(/\:todos\:/, ':todos_attributes:'))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 1970-01-01
  • 2017-12-25
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 2013-06-21
相关资源
最近更新 更多