[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Dynamically created attributes

Peter Marks

1/12/2009 8:25:00 AM

I'd like to specify a quantity of object attributes when creating an
instance of an object. For example, I would like to create a Grid object
with 4 different 'row' attributes like this: Grid.new(4). Here's some
dirty code that does that:

class Grid
#Creates row1, row2, etc. depending on row arg
def initialize(rows)
row_count = 1
rows.times do
instance_eval "@row#{row_count} = 'xxx'"
row_count += 1
end
end
end

It's dirty, but it creates the attributes. I don't see how to
dynamically create accessor methods for all these attributes though. Any
suggestions? I sense there's a better way to do this.
--
Posted via http://www.ruby-....

4 Answers

Stefano Crocco

1/12/2009 8:59:00 AM

0

Alle luned=C3=AC 12 gennaio 2009, Peter Marks ha scritto:
> I'd like to specify a quantity of object attributes when creating an
> instance of an object. For example, I would like to create a Grid object
> with 4 different 'row' attributes like this: Grid.new(4). Here's some
> dirty code that does that:
>
> class Grid
> #Creates row1, row2, etc. depending on row arg
> def initialize(rows)
> row_count =3D 1
> rows.times do
> instance_eval "@row#{row_count} =3D 'xxx'"
> row_count +=3D 1
> end
> end
> end
>
> It's dirty, but it creates the attributes. I don't see how to
> dynamically create accessor methods for all these attributes though. Any
> suggestions? I sense there's a better way to do this.

Well, the first thing I can think of is to replace your n instance variable=
s=20
with a single instance variable @rows which will be an array and contain th=
e=20
rows. Something like this:

class Grid

attr_reader :rows
def initialize(rows)
@rows =3D Array.new(rows){ 'xxx' }
end

end

If you don't want to make the array availlable from outside the instance, y=
ou
can skip the attr_readr line and provide methods to directly access the row=
s.=20
=46or example, you can define [] and []=3D methods as array does:

class Grid

def [](idx)
@rows[idx]
end

def []=3D(idx, value)
@rows[idx] =3D value
end

end

If you truly want to use an instance variable for each row, see the=20
documentation about instance_variable_set and look at the section "Object=20
specific classes" in the "Classes and Objects" chapter of the online editio=
n=20
of the Pickaxe book
(http://www.ruby-doc.org/docs/ProgrammingRuby/html/cl...)

I hope this helps

Stefano

Jesús Gabriel y Galán

1/12/2009 9:03:00 AM

0

On Mon, Jan 12, 2009 at 9:25 AM, Peter Marks <petertmarks@gmail.com> wrote:
> I'd like to specify a quantity of object attributes when creating an
> instance of an object. For example, I would like to create a Grid object
> with 4 different 'row' attributes like this: Grid.new(4). Here's some
> dirty code that does that:
>
> class Grid
> #Creates row1, row2, etc. depending on row arg
> def initialize(rows)
> row_count = 1
> rows.times do
> instance_eval "@row#{row_count} = 'xxx'"
> row_count += 1
> end
> end
> end
>
> It's dirty, but it creates the attributes. I don't see how to
> dynamically create accessor methods for all these attributes though. Any
> suggestions? I sense there's a better way to do this.
> --
> Posted via http://www.ruby-....
>
>

Maybe this is cleaner:

class Object
def singleton_class
class << self; self; end
end
end

class Grid
def initialize rows=0
rows.times do |i|
instance_variable_set "@row#{i}", "initial value"
singleton_class.instance_eval {attr_accessor "row#{i}"}
end
end
end

irb(main):020:0> a = Grid.new 3
=> #<Grid:0xb7c02008 @row0="initial value", @row2="initial value",
@row1="initial value">
irb(main):021:0> a.methods.grep /row/
=> ["row0", "row0=", "row1", "row1=", "row2", "row2="]

Hope this helps,

Jesus.

Jesús Gabriel y Galán

1/12/2009 9:07:00 AM

0

On Mon, Jan 12, 2009 at 10:03 AM, Jes=FAs Gabriel y Gal=E1n
<jgabrielygalan@gmail.com> wrote:
> On Mon, Jan 12, 2009 at 9:25 AM, Peter Marks <petertmarks@gmail.com> wrot=
e:
>> I'd like to specify a quantity of object attributes when creating an
>> instance of an object. For example, I would like to create a Grid object
>> with 4 different 'row' attributes like this: Grid.new(4). Here's some
>> dirty code that does that:
>>
>> class Grid
>> #Creates row1, row2, etc. depending on row arg
>> def initialize(rows)
>> row_count =3D 1
>> rows.times do
>> instance_eval "@row#{row_count} =3D 'xxx'"
>> row_count +=3D 1
>> end
>> end
>> end
>>
>> It's dirty, but it creates the attributes. I don't see how to
>> dynamically create accessor methods for all these attributes though. Any
>> suggestions? I sense there's a better way to do this.
>> --
>> Posted via http://www.ruby-....
>>
>>
>
> Maybe this is cleaner:
>
> class Object
> def singleton_class
> class << self; self; end
> end
> end
>
> class Grid
> def initialize rows=3D0
> rows.times do |i|
> instance_variable_set "@row#{i}", "initial value"
> singleton_class.instance_eval {attr_accessor "row#=
{i}"}
> end
> end
> end
>
> irb(main):020:0> a =3D Grid.new 3
> =3D> #<Grid:0xb7c02008 @row0=3D"initial value", @row2=3D"initial value",
> @row1=3D"initial value">
> irb(main):021:0> a.methods.grep /row/
> =3D> ["row0", "row0=3D", "row1", "row1=3D", "row2", "row2=3D"]

Ooops, my solution starts with 0, while you wanted to start with 1.
Anyway, an easy change. Nevertheless, I agree with Stefano that this
would be better off implemented as an array, instead of having
individual variables for each "field".

Jesus.

Peter Marks

1/12/2009 10:03:00 AM

0

Thanks for the help guys! The arrays sound like a much more suitable way
around this problem. Overthought this one.

Cheers!

Peter
--
Posted via http://www.ruby-....