Reputation: 3123
Is there any data structure in Ruby which is similar to Pascal records?
I would like to define a record type which has about 15-20 fields, all of them are strings.
I tried to define a class for this purpose, but I realized that I have to define getter and setter methods:
class Data
def description
@description
end
def size
@size
end
def address
@address
end
.
. all other (about 15 variables...)
.
def description=( value )
@description = value
end
def size=(value)
@size=value
end
def address=(value)
@address=value
end
.
. more setter method (about 15 times...)
.
end
To define all the 15-20 fields and getters/setters this way is quite annoying. Is there any shorter way to do it? For example:
class Data
desc, size, address=""
end
Or something similar, and then I would be able to create a new instance of the Data class:
d=Data.new
and then set the instance variables:
d.desc="bla"
d.size="50.66"
d.address="Bla street 20."
I already have a method, that can parse an XML file with the XMLSimple gem, and I would like to create a record (or class) from the parsed data and return it back with the "return" keyword. Then I want to access the fields of the record simply: d.size, d.address, d.description and so on. For example:
def data_import(fname="1.xml")
data = XmlSimple.xml_in(fname,{'SuppressEmpty' => ""})
d=Data.new()
d.desc=data['desc'][0]
d.size=data['size'][0]
d.address=data['address'][0]
d. ... =
d. ... = (about 15-20 times)
d. ... =
return d
end
my XML (1.xml):
<entity>
<desc>bla</desc>
<size>50.66</size>
<address>Bla street 20.</address>
.
. (15-20 more fields)
.
</entity>
In the Pascal language (and as far as I know in C++) there were a data structure called "record" for this purpose.
Upvotes: 2
Views: 351
Reputation: 3205
You cand use a Hash as a bucket for your attributes/properties or you can make use of Ruby's metaprogramming abilities for generating getters and setters using accessors like this:
attr_accessor :desc, :size, :address
You can also collect the attributes in an array and use splatting like this to expand the array in a list needed by the previously mentioned method:
attributes = [:desc, :size, :address]
attr_accessor *attributes
Upvotes: 1
Reputation: 369468
Yes, there is, it uses the C/C++ name instead of record: Struct
. Struct
is a class factory, if you call Struct.new
, it will return a class which has the desired fields:
Data = Struct.new(:description, :size, :address, …)
If you need to modify the behavior, you can pass a block to Struct.new
:
Data = Struct.new(:description, :size, :address, …) do
def my_custom_method; end
end
or use inheritance:
class Data < Struct.new(:description, :size, :address, …)
def my_custom_method; end
end
Then:
d = Data.new
d.description = …
d.size = …
d.address = …
or alternatively:
d = Data.new(…, …, …)
Upvotes: 1