Daily Code Reading #3 – Facets Hash#to_struct

Today I’m looking at facets’ Hash#to_struct. I use structs in my code when I want to store some complex data but don’t need to full Ruby class.

The Code

1
2
3
4
# File lib/core/facets/hash/to_struct.rb, line 12
  def to_struct(struct_name)
    Struct.new(struct_name,*keys).new(*values)
  end

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/ruby -wKU
#
# Code Reading #3
require '../base'
require 'facets/hash/to_struct'
 
Struct.new("Application", :users, :servers)
 
class Example
  def self.create
    {
      :users => [:edavis],
      :servers => [:app1, :app2, :app3]
    }.to_struct("Application")
  end
end
 
ap(Example.create)
 
class HashToStruct < Test::Unit::TestCase
  def test_should_be_a_struct
    assert_kind_of Struct, Example.create
  end
 
  def test_should_set_users
    @example = Example.create
    assert_equal [:edavis], @example.users
  end
 
  def test_should_set_servers
    @example = Example.create
    assert_equal [:app1, :app2, :app3], @example.servers
  end
 
end

On github

Review

Hash#to_struct has a pretty simple implementation.

  1. First it defines a new Struct class called “Application” with the attributes of ‘users’ and ‘servers’.
  2. This returns a new Class object, which #to_struct calls #new on passing in the Hash’s values (think of it as Struct::Application.new(*values)).
  3. Then the attributes are set, and the Struct::Application object is returned.

So in reality, I should revise my first sentence “I use structs in my code when I want to store some complex data but I don’t want to write full Ruby class myself.”