Using a loop to run similar commands

Hi again,

Is there a neater way to do this, by using a loop?

create1 = agent.get(t1)
create2 = agent.get(t2)
create3 = agent.get(t3)
create4 = agent.get(t4)
create5 = agent.get(t5)
create6 = agent.get(t6)
create7 = agent.get(t7)
create8 = agent.get(t8)
create9 = agent.get(t9)
create10 = agent.get(t10)
create11 = agent.get(t11)
create12 = agent.get(t12)

Thanks guys,

Dwight

Yes, use arrays.

ts = [ … ] # however you create these objects

creates = ts.map{|t| agent.get(t) }

– Matma R.

create9 = agent.get(t9)
create10 = agent.get(t10)
create11 = agent.get(t11)
create12 = agent.get(t12)

There’s a lot of variable name repetition going on here. Instead I’d
recommend using an array:

t = [val1, val2…]

Then you can store the end results in an array as well. Here is a more
simplified example showing the basis of what you’re trying to do:

irb(main):006:0> test = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):007:0> create = test.each_with_object([]) { |element, holder|
holder << element.to_s }
=> [“1”, “2”, “3”, “4”]

In this case, you have an array with all the objects you want to run
agent.get on. Then you loop through them using each_with_object, which
passes in an array holder which has the results of calling a method on
each element (in this case to_s). The result of this call will be a new
array with the results of to_s called on each element.

Regards,
Chris W.
http://www.twitter.com/cwgem

On Tue, Sep 13, 2011 at 11:14, dwight schrute [email protected]
wrote:

Hi again,

Is there a neater way to do this, by using a loop?

create1 = agent.get(t1)
create2 = agent.get(t2)

create12 = agent.get(t12)

To expand a bit on what the others have said:

Kudos to you for recognizing that the above was “not neat”. Any time
you have to append something such as a serial number to differentiate
a bunch of data items that are essentially the same, it’s a code
smell.

But don’t feel too bad for having done it that way; I saw some actual
Rails production code recently at a major company, that had eight
weekly timestamps in a class, and then tons of validations on them,
not only in relation but individually. And then they used fancy
trickery with send in a loop, to address them individually. IMHO they
should have been broken out into a separate class…

-Dave

On Tue, Sep 13, 2011 at 10:14 AM, dwight schrute [email protected]
wrote:

create7 = agent.get(t7)

Posted via http://www.ruby-forum.com/.

Yes, but it’s flagrantly wrong. You’re creating consecutive variable
names,
thus using the current binding as if it were a hash or an array
(depending
on how literally you want to interpret it). What you should be doing is
using an actual hash or array. Here is an example:

agent will be a hash that represents

whatever your agent is in your use case

agent = {
‘t0’ => ‘value for t0’,
‘t1’ => ‘value for t1’,
‘t2’ => ‘value for t2’,
‘t3’ => ‘value for t3’,
}

give it a get method so it looks like your agent

class <<agent
alias_method :get, :fetch
end

instead of local variables t1, t2, …, tn

use an array named t, and put the values in there

at the appropriate indexes

t = [‘t0’, ‘t1’, ‘t2’, ‘t3’]

instead of local variables create1, create2, …, createn

use an array named create, and put the values in there

create = []

for each of the values of t, get them from agent

and put them into create

t.each do |t_i|
create << agent.get(t_i)
end

and now the create hash holds all the values that

the local variables would have had to hold

create # => [“value for t0”, “value for t1”, “value for t2”, “value for
t3”]

I actually played around a bit and then did this:

1.upto(12) do
|i| eval “create#{i} = agent.get(t#{i})”
end

Thank you all for these excellent suggestions - I will explore them
further. This is by far the most helpful and useful web community that
I have come across. - Hopefully I’ll get to the point soon where I can
even throw the odd suggestion of my own in!

Dwight.

On 14.09.2011 14:22, dwight schrute wrote:

I actually played around a bit and then did this:

1.upto(12) do
|i| eval “create#{i} = agent.get(t#{i})”
end

I still would encourage you to learn more – or at least something
about arrays¹ and other containers. You’re not gonna become a good Ruby
coder
with eval in your 2nd line of code.

– Matthias

1: Programming Ruby: The Pragmatic Programmer's Guide

On Wed, Sep 14, 2011 at 7:22 AM, dwight schrute [email protected]
wrote:

I actually played around a bit and then did this:

1.upto(12) do
|i| eval “create#{i} = agent.get(t#{i})”
end


Posted via http://www.ruby-forum.com/.

In the same way that you can store a variable named “create1” in your
local
binding, you can store it in a hash, or you can use indexes rather than
suffixes and store it in an array. This is safer (you can’t accidentally
execute arbitrary code), faster (you don’t have to parse source code),
much
more robust (arrays and hashes are used everywhere, but it would be a
nightmare to pass bindings all over the place, evaling on them to get
the
values you need).

Please check out my above example again, or check out hashes.

In Ruby Kickstart, we talk about Arrays in session 2
http://ruby-kickstart.com/#session2 and Hashes in session 3
http://ruby-kickstart.com/#session3

We might go a bit quick for a beginner, I’m not sure, but seeing the
examples might be helpful.