A Ruby Struct allows an instance to be generated with a set of accessors:
# Create a structure named by its constant Customer = Struct.new(:name, :address) #=> Customer Customer.new("Dave", "123 Main") #=> #<Customer name="Dave", address="123 Main">
This looks convenient and powerful, however, a Hash does something pretty similar:
Customer = {:name => "Dave", :address => "123 Main"}
What are the real-world situations where I should prefer a Struct (and why), and what are the caveats or pitfalls in choosing one over the other?
Struct is a compact way to group together a number of attributes, using accessor methods, without creating an explicit class. The Struct class is a creator of specific classes, each one is defined to hold a set of variable and their accessors. The subclass of Struct class is Struct::Tms.
In Ruby, Hash is a collection of unique keys and their values. Hash is like an Array, except the indexing is done with the help of arbitrary keys of any object type. In Hash, the order of returning keys and their value by various iterators is arbitrary and will generally not be in the insertion order.
Advertisements. A Hash is a collection of key-value pairs like this: "employee" = > "salary". It is similar to an Array, except that indexing is done via arbitrary keys of any object type, not an integer index.
Hashes are not meant to be in a certain order (though they are in Ruby 1.9) as they're a data structure where one thing merely relates to another thing.
Personally I use a struct in cases when I want to make a piece of data act like a collection of data instead of loosely coupled under a Hash
.
For instance I've made a script that downloads videos from Youtube and in there I've a struct to represent a Video and to test whether all data is in place:
Video = Struct.new(:title, :video_id, :id) do def to_s "http://youtube.com/get_video.php?t=#{id}&video_id=#{video_id}&fmt=18" end def empty? @title.nil? and @video_id.nil? and @id.nil? end end
Later on in my code I've a loop that goes through all rows in the videos source HTML-page until empty?
doesn't return true.
Another example I've seen is James Edward Gray IIs configuration class which uses OpenStruct
to easily add configuration variables loaded from an external file:
#!/usr/bin/env ruby -wKU require "ostruct" module Config module_function def load_config_file(path) eval <<-END_CONFIG config = OpenStruct.new #{File.read(path)} config END_CONFIG end end # configuration_file.rb config.db = File.join(ENV['HOME'], '.cool-program.db') config.user = ENV['USER'] # Usage: Config = Config.load_config('configuration_file.rb') Config.db # => /home/ba/.cool-program.db Config.user # => ba Config.non_existant # => Nil
The difference between Struct
and OpenStruct
is that Struct
only responds to the attributes that you've set, OpenStruct
responds to any attribute set - but those with no value set will return Nil
A Struct has the feature that you can get at its elements by index as well as by name:
irb(main):004:0> Person = Struct.new(:name, :age) => Person irb(main):005:0> p = Person.new("fred", 26) => # irb(main):006:0> p[0] => "fred" irb(main):007:0> p[1] => 26 irb(main):008:0> p.name => "fred" irb(main):009:0> p.age => 26
which sometimes is useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With