1

I'm trying to iterate through database file with gdbm, create objects with values I get and assign them to an array. The problem is I can't seem to get index of iteration and I need it for my array. Here is the code:

bots_directory = "../data/bots.db"

bots = Array.new

GDBM.new(bots_directory).each_pair.with_index do |nickname, password, index|
   bots[index] = Bot.new(nickname, password)
end

Error I get:

`[]=': no implicit conversion from nil to integer (TypeError)

Also, will database file close after the block is executed?

PoVa
  • 995
  • 9
  • 24
  • This is a simple misunderstanding of how the arguments are yielded to the block and how parallel assignment works. your code will yield `[[key,value],index]` this means that nickname is now `[key,value]`, password is `index`, and index is nil. To split out key value you need to wrap nickname and password in parentheses to have them split it then becomes `nickname,password = [key,value]` and `index = index`.But @spickermann has suggested far better ways to accomplish this such as map. For a quick understanding try this in irb `a,b,c = [["k","v"],1]` then try `(a,b),c = [["k","v"],1]` – engineersmnky Oct 29 '15 at 19:51

1 Answers1

2

I would use each_with_index instead of each_pair.with_index:

bots_directory = "../data/bots.db"
bots = []

GDBM.new(bots_directory).each_with_index do |(nickname, password), index|
  bots[index] = Bot.new(nickname, password)
end

Or even simpler, since the index starts from 0 and increases by 1 anyway:

bots_directory = "../data/bots.db"
bots = []

GDBM.new(bots_directory).each_pair do |nickname, password|
  bots << Bot.new(nickname, password)
end

Perhaps map is also an option?

bots_directory = "../data/bots.db"

bots = GDBM.new(bots_directory).map do |nickname, password|
  Bot.new(nickname, password)
end
spickermann
  • 100,941
  • 9
  • 101
  • 131