0

I have the following code:

3.times do |n|
    "project#{n}" = FactoryGirl.create(:project, :title => "Project #{n}")
end

That obviously doesn't work... Does anyone know how to make loop where I can make variable name that will change with 'local loop variable' to make a lot of variables like project1, project2, projekt3?

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
Filip Bartuzi
  • 5,711
  • 7
  • 54
  • 102
  • 2
    see: http://stackoverflow.com/questions/3864488/dynamically-creating-local-variables-in-ruby – Zoltán Haindrich Jul 17 '13 at 18:51
  • 1
    What *specifically* are you trying to do? Creating arbitrary variables seems a bit silly, since your source code would either (a) need to change based on the number of factories, or (b) use `send` with dynamically-constructed names all the time. What's the point? **Also**, [Factory Girl has sequences](https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#sequences) already and you shouldn't even need to do this manually. – Dave Newton Jul 17 '13 at 18:59
  • The best way is to use array and create it by `FactoryGirl.create_list(:project)`. – Hauleth Jul 17 '13 at 20:57
  • I promise you, even if you are *absolutely sure* you need to create variable identifiers dynamically, you are very, very wrong. – Borodin Jul 17 '13 at 21:23
  • Also possible duplicate of http://stackoverflow.com/questions/4963678/dynamically-set-local-variables-in-ruby. – Richard Cook Jul 17 '13 at 21:25

3 Answers3

6

Can you use Hashes?

project = {}
3.times do |n|
    project[n] = FactoryGirl.create(:project, :title => "Project #{n}")
end

You get access to the data with project[1] ...

knut
  • 27,320
  • 6
  • 84
  • 112
  • 3
    A hash with different key/value pairs is often way easier to work with than the *pile of variables* anti-pattern. In this case even an `Array` would be better since the keys are always numbers. – tadman Jul 17 '13 at 18:54
  • and if you want some sugar `project["project#{n}".to_sym] = ....` then you can access it as project[:project1], project[:project2], etc... – Doon Jul 17 '13 at 18:59
4

You could use Hashes, as knut suggested, or you can use an array -- since you're starting at 0 and moving consecutively upward.

project = Array.new(3)
3.times do |n|
  project[n] = FactoryGirl.create(:project, :title => "Project#{n}")
end

Or, more simply:

project = []
3.times do |n|
  project << FactoryGirl.create(:project, :title => "Project#{n}")
end
Translunar
  • 3,739
  • 33
  • 55
1

This provides an illusion of what you're asking...

eigenclass = class << self; self; end
3.times do |n|
  eigenclass.class_eval { attr_accessor "project#{n}" }
  eval "self.project#{n} = FactoryGirl.create(:project, :title => \"Project #{n}\")"
end

But please don't do this. It's actually creating a property accessor on Kernel, one for each value of n.

Here's my reference.

Richard Cook
  • 32,523
  • 5
  • 46
  • 71