Ruby对象工厂循环似乎会覆盖部分实例,而不是全部

时间:2019-12-22 13:55:08

标签: arrays ruby loops parsing hash

我在红宝石循环中挣扎。我从网站上以字符串形式捕获了一组102个项目。在这些字符串中列出了有关该项目的特征。我想解析字符串,并将某些项目特征放入哈希中。每个哈希都应作为我的Item类的一个实例。 kinda 下面的代码有效(意味着没有用),因为它确实以预期的方式创建了一些Item类对象。但是它并没有捕获全部102。相反,它似乎仅捕获了一个子集。我认为它正在覆盖一些早期的迭代。我很沮丧我是新手,这是我从事的最艰巨的项目,因此欢迎所有建议并给予赞赏!

这是我的类定义,保存在由require_relative拉入的单独文件中:

class Item
    attr_accessor :char1, :char2, :char4, :char6, :char8, :char10, :char11 
    def initialize(args)
        @char2  = args[:char2]
        @char1  = args[:char1]
        @char4  = args[:char4]
        @char6  = args[:char6] || 4
        @char8  = args[:char8]
        @char10 = args[:char10]
end

在IRB中运行我的脚本文件,我得到:

2.6.3 :028 > @item_cards.count
 => 102
2.6.3 :030 > @item_cards.first.text
 => "42\Characteristic1\Characteristic2\Characteristic3\Characteristic4\Characteristic1\Characteristic5\Characteristic6\Characteristic7\Characteristic8\Characteristic9\Characteristic10\"

然后我解析该字符串以获取我所关心的特征,将其放入数组中,然后尝试使用该数组在Item类中构建对象。

def factory 
     @item_cards.each do |x|  
            s = x.text
            arry = {
            :char2 => s.split(%'\')[2].strip,
            :char1 => s.split(%'\')[1].strip,
            :char4 => s.split(%'\')[4].strip,
            :char6 => s.split(%'\')[6].strip,
            :char8 => s.split(%'\')[8].strip,
            :char10 => s.split(%'\')[10].strip,
                }   

     @item = Item.new(char2: arry[:char2], char1: arry[:char1], char4: 
     arry[:char4], char6: arry[:char6], sqft: char8[:char8], char10: 
     arry[:char10])

            puts "** here is the new Item CLASS object #{@item.inspect}" 
            puts "*** there are #{Item.count} Item Objects now"
            puts "*** Against this many @item_cards #{@item_cards.count}"
            puts "*** end of this iteration of loop ***"
     end

    puts "********** OUT OF THE LOOP NOW **********" 
    puts "There are this many Item objects: #{Item.all.count}"

end

在循环的每次迭代过程中,我认为(1)文本正确解析,并且(2)数据已正确捕获在@item变量中。但是,有时#{Item.count}代码不会增加。例如,它将创建具有该项目特征的第三个Item对象,但随后似乎用第四个Item对象覆盖了第三个Item对象。正确创建了其他Item对象。最终结果是,与最初捕获的@item_cards数量(即少于102个)所建议的数量相比,Item对象的数量更少。

当我在IRB中运行工厂命令时,这就是我得到的结果,到结束时已跳过或覆盖了30项:

 here is the initial array {#parsing correctly for item 71}
*** And here is the New Item CLASS object #<Item:0x00007f96c25162c8 @char2="Item 71's Char2", @char1="Item 71's Char1", "#and so on...">
*** there are 71 Item Objects now
*** Against this many @item_cards 102
*** end of this iteration of loop ***
Return value is: nil
 here is the initial array {#parsing correctly for item 72}
*** And here is the New Item CLASS object #<Item:0x00007f96c454a6c0 @char2="Item 72's Char 2", @char1="Item 72's Char 1", #and so on...>
*** there are 71 Item Objects now
*** Against this many @item_cards 102
*** end of this iteration of loop ***
Return value is: nil

#then process repeats, working correctly to create new Item object.

*** there are 72 Item Objects now
*** Against this many @item_cards 102
*** end of this iteration of loop ***
Return value is: nil

********** OUT OF THE LOOP NOW **********

There are this many Item objects: 72
Return value is: nil

我希望这很清楚,即使不是很简洁。非常新手,因此欢迎所有输入/更正。

2 个答案:

答案 0 :(得分:0)

Array#each只是迭代集合。相反,您需要将输入映射到解析后返回的某些数据。就是说,类似下面的东西会起作用。

def factory 
  @items = # an array of items!
    @item_cards.map do |x|  
      ...
      Item.new(...) # should be the last line in a loop
    end
  # @items contains the array of `Item` objects now
end

答案 1 :(得分:-1)

您的问题是,您仅在初始化具有某些属性的新Item对象,而没有将其保存到数据库中。每次执行@item = Item.new时,都会覆盖@item的先前版本。假设您的new通过验证,将create更改为Item应该可以解决您的问题:

def factory 
  @item_cards.each do |x|  
    s = x.text
    arry = {
      :char2 => s.split(%'\')[2].strip,
      :char1 => s.split(%'\')[1].strip,
      :char4 => s.split(%'\')[4].strip,
      :char6 => s.split(%'\')[6].strip,
      :char8 => s.split(%'\')[8].strip,
      :char10 => s.split(%'\')[10].strip,
    }   

    @item = Item.create(                         # <-- Change this bit here
      char2: arry[:char2],
      char1: arry[:char1],
      char4: arry[:char4],
      char6: arry[:char6],
      sqft: char8[:char8],
      char10: arry[:char10]
    )

    puts "** here is the new Item CLASS object #{@item.inspect}" 
    puts "*** there are #{Item.count} Item Objects now"
    puts "*** Against this many @item_cards #{@item_cards.count}"
  end

  puts "********** OUT OF THE LOOP NOW **********" 
  puts "There are this many Item objects: #{Item.all.count}"
end
相关问题