To demonstrate Structs and Records - lets assume we have a User
class that can receive messages posted to it.
code/crystal/src/structs_n_records/user.cr
require "./message_record"
class User
private getter name : String, email : String
def initialize(@name, @email)
end
def to_s
"#{name} <#{email}>"
end
def post_message(message : Message)
puts message.to_s
end
end
1. Records
Records are Structs with the initialize and getter automatically defined.
Records are actually Structs with Macros used to automatically generate the initialize and getter definitions - see: https://github.com/crystal-lang/crystal/blob/master/src/macros.cr
1.1. Records (no methods)
Thus the simplest Record definition for a Message would be:
record(Message, sender : User, text : String, receiver : User? = nil, topic : String? = nil)
# or without the parens
record Message, sender : User, text : String, receiver : User? = nil, topic : String? = nil
The following code demostrates how to use records.
code/crystal/src/structs_n_records/simple_record.cr
require "./user"
record(Message, sender : User, text : String, receiver : User? = nil, topic : String? = nil)
user_1 = User.new(name: "user_1", email: "[email protected]")
user_2 = User.new(name: "user_2", email: "[email protected]")
mesg_1 = Message.new(sender: user_2, text: "Hi")
mesg_2 = Message.new(sender: user_1, text: "Hoi", topic: "Greet")
mesg_3 = Message.new(sender: user_1, text: "Hoi", topic: "Greet", receiver: user_2)
user_1.post_message(mesg_1)
user_2.post_message(mesg_2)
user_2.post_message(mesg_3)
Run this using:
$ crystal src/structs_n_records/simple_record.cr
This of course has the same limitation as a Struct without a to_s
methods.
1.2. Records (with methods)
Assuming you want a custom method then the record looks like:
code/crystal/src/structs_n_records/message_record.cr
require "./user"
record(Message, sender : User, text : String,
receiver : User? = nil, topic : String = "") do
def to_s
output = [] of String
output << "-" * 30
output << "From: #{sender.to_s}"
output << "To: #{receiver.to_s}" unless receiver.nil?
output << "Topic: #{topic.to_s.strip}"
output << text.strip
output << "-" * 30
output.join("\n")
end
end
user_1 = User.new(name: "user_1", email: "[email protected]")
user_2 = User.new(name: "user_2", email: "[email protected]")
mesg_1 = Message.new(sender: user_2, text: "Hi")
mesg_2 = Message.new(sender: user_1, text: "Hoi", topic: "Greet")
mesg_3 = Message.new(sender: user_1, text: "Hoi", topic: "Greet", receiver: user_2)
user_1.post_message(mesg_1)
user_2.post_message(mesg_2)
user_2.post_message(mesg_3)
Run this using:
$ crystal src/structs_n_records/message_record.cr