2017-02-01 37 views
0

我有这段代码。第一个和第二个命令钢轨工作良好,但“项目.todos < todo”部分ruby解释器视为错误。Rails seed.db语法

NoMethodError: undefined method `todos' for nil:NilClass 

我该如何解决?当我把seeds.rb文本这样的,一切都很好,但它的代码无法正常工作:

#work 
project = Project.create title: "Family" 
todo = Todo.create text: "Buy milk", isCompleted: true 
project.todos << todo 

#code 
require 'yaml' 
yhash = YAML.load_file(File.open("#{Rails.root}/db/seeds.yml")) 
yhash.each do |key, value| 
    value.each do |k, v| 
    k.each do |ke, proj| 
     if proj.class.name == 'String' 
     project = Project.create title: proj 
     elsif proj.class.name == 'Array' 
     proj.each do |todo| 
      i = 0 
      tmp = '' 
      todo.each do |to| 
      to.each do |t| 
       if i == 0 
       i = 1 
       elsif i == 2 
       i = 3 
       elsif i == 1 
       tmp = t 
       i = 2 
       elsif i == 3 
       if t == false 
        bool = 'false' 
       else 
        bool = 'true' 
       end 
       todo = Todo.create text: tmp, isCompleted: bool 
       project.todos << todo 
       i = 0 
       tmp = '' 
       end 
      end 
      end 
     end 
     end 
    end 
    end 
end 

回答

2

简短的回答

你真的应该改变你的YAML结构,这将让一切变得更加容易。

--- 
projects: 
- title: Family 
    todos: 
    - text: Buy milk 
    is_completed: true 
    - text: Todo2 
    is_completed: false 
- title: Project2 
    todos: 
    - text: Todo3 
    is_completed: true 
    - text: Todo4 
    is_completed: false 

你可以在几行解析它:

yaml = YAML.load(File.read('test.yaml')) 

yaml['projects'].each do |project| 
    title = project['title'] 
    p title 
    # Create project here 
    project['todos'].each do |todo| 
    p todo 
    # Create todo here 
    # Add todo to project 
    end 
end 

NoMethodError

NoMethodError: undefined method 'todos' for nil:NilClass 

意味着上todos被称为(project)的对象是不确定的。

事实上,project没有定义,但proj是,那么你应该创建一个名为Project第一project

命名对象

为了避免混淆:

  • project_name可以是包含该项目名称
  • project_names可以是项目名称的数组字符串
  • project可以是Project对象
  • todos可能是一个数组Todo小号

你的代码表示proj被用于不同的目的:

project = Project.create title: proj 
proj.each do |todo| 

那些2个proj S的关系是具有不同的变量名不同的对象,并应分别初始化。

在YAML中编写嵌套散列很容易,一个散列可能代表Project s,另一个可能代表Todo s。

块变量

如果创建一个Project例如在第一次迭代过程中调用project一个循环中,它不会提供给下一个迭代:如果你想有一个project变量

[1, 2, 3].each do |i| 
    if i==1 
    project = "my project" 
    end 
    p i 
    p project 
end 
# 1 
# "my project" 
# 2 
# nil 
# 3 
# nil 

对所有迭代都可用,你应该创建它外部的环:

project = "my project" 
[1, 2, 3].each do |i| 
    p i 
    p project 
end 
# 1 
# "my project" 
# 2 
# "my project" 
# 3 
# "my project" 

另一种可能性是使用@project而不是project

[1,2,3].each do |i| 
    if i==1 
    @project = "my project" 
    end 
    p i 
    p @project 
end 
# 1 
# "my project" 
# 2 
# "my project" 
# 3 
# "my project" 

情况下

相反的:

if proj.class.name == 'String' 
     project = Project.create title: proj 
     elsif proj.class.name == 'Array' 

你可以使用:

case proj 
when String 
    # proj is a String 
when Array 
    # proj is an Array 
end 
+0

'凸出' 是红宝石阵列。 'project' - 类的rails实例。他已经创建在块'如果proj.class.name =='String'' –

+0

但我有几个不同的项目。 例如: '项目 - 标题: '家庭' 待办事项: - 文字: '买牛奶' isCompleted:假 - 文字: '去剧场' - isCompleted:假 - 标题:“工作' todos: - text:'Create code' - isCompleted:false ...' –

+0

这不是纯粹的红宝石。这是对rails db:seed的命令,但是纯ruby阻止这个命令,因为是ruby class的东西。 –