This card will show you a cool way to define a class using
Struct.new
Show archive.org snapshot
.
A common usecase for Structs are temporary data structures which just hold state and don't provide behaviour. In many cases you could use a simple hash as a data structure instead. However, a Struct provides you with a nice constructor, attribute accessors and complains if you try to access undefined attributes. Structs are easy to compare (by attributes). A struct gives meaning to the data.
Structs are great but sometimes there are arguments against their usage:
Define a class and create objects:
UserPreview = Struct.new(:gid, :email, :name)
u = UserPreview.new(1, 'hans@peter.de', 'Hans Peter')
=> #<struct UserPreview gid=1, email="hans@peter.de", name="Hans Peter">
access attributes:
u.gid
=> 1
u.name
=> "Hans Peter"
u['name']
=> "Hans Peter"
u[:name]
=> "Hans Peter"
u[2]
=> "Hans Peter"
u.to_a
=> [1, "hans@peter.de", "Hans Peter"]
u.to_h
=> {:gid=>1, :email=>"hans@peter.de", :name=>"Hans Peter"}
u.foo
NoMethodError: undefined method `foo' for #<UserPreview:0x00565427e1aa38>
compare objects:
UserPreview.new(1, 'hans@peter.de', 'Hans Peter') == UserPreview.new(1, 'hans@peter.de', 'Hans Peter')
=> true
Address = Struct.new(:street, :city, :country) do
def to_s
each.inject { |concat, attr| concat += "\n#{attr}" }
end
end
a = Address.new('Bahnhofstr. 1', '86150 Augsburg', 'Germany')
puts a
Bahnhofstr. 1
86150 Augsburg
Germany
If you prefer to create objects that feel more like ActiveRecord classes you could use the :keyword_init
argument.
This will allow you to make the new
method a bit more verbose and independent of argument order:
Customer = Struct.new(:name, :address, keyword_init: true)
Customer.new(name: "Dave", address: "123 Main")
=> #<struct Customer name="Dave", address="123 Main">
You might sometimes see that a class inherits from a stuct like this:
# BAD
class Address < Struct.new(:street, :city, :country)
end
# GOOD
Address = Struct.new(:street, :city, :country) do
end
This should be avoided as it creates an extra anonymous class that will never be used ( see the docs Show archive.org snapshot ).