OpenStruct vs. Struct
# Struct
Struct.new("StructName", :attribute1, :attribute2)
sn = StructName.new('aaa', 'bbb')
#=> NameError: uninitialized constant StructName
sn = Struct::StructName.new('aaa', 'bbb')
#=> #<struct Struct::StructName attribute1="aaa", attribute2="bbb">
StructName = Struct.new(:attribute1, :attribute2) # Capitial S for StructName, so the `StructName` will be a Constant
sn = StructName.new('aaa', 'bbb')
#=> #<struct StructName attribute1="aaa", attribute2="bbb">
# OpenStruct
osn = OpenStruct.new(attribute1: 'aaa', attribute2: 'bbb')
=> #<OpenStruct attribute1="aaa", attribute2="bbb">
osn.attribute3 = 'ccc'
#=> 'ccc'
osn
#=> #<OpenStruct attribute1="aaa", attribute2="bbb", attribute3="ccc">
# open struct object's attributes are defined by using Ruby's metaprogramming
sn.attribute3 = 'ccc'
#=> NoMethodError: undefined method `attribute3=' for #<struct Struct::StructName attribute1="aaa", attribute2="bbb">
osn = OpenStruct.new
#=> #<OpenStruct>
osn.attribute1 = 'aaa'
osn.attribute2 = 'bbb'
osn.attribute3 = 'ccc'