Class: Structure

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/structure.rb,
lib/structure/version.rb,
lib/structure/active_support.rb

Overview

Structure is a nestable, typed key/value container.

class Person < Structure
  key  :name
  many :friends
end

Defined Under Namespace

Classes: Double

Constant Summary collapse

BasicObject =
::BasicObject
VERSION =
'0.20.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hsh = {}) ⇒ Structure

Creates a new structure.

A hash, if provided, seeds the attributes.



120
121
122
123
124
125
126
127
# File 'lib/structure.rb', line 120

def initialize(hsh = {})
  @attributes = defaults.inject({}) do |a, (k, v)|
    a[k] = v.is_a?(Array) ? v.dup : v
    a
  end

  hsh.each { |k, v| self.send("#{k}=", v) }
end

Instance Attribute Details

#attributesObject (readonly)

The attributes that make up the structure.



130
131
132
# File 'lib/structure.rb', line 130

def attributes
  @attributes
end

Class Method Details

.const_missing(name) ⇒ Object

Lazy-eval undefined constants, typically other structures, assuming they will be defined later in the text.



108
109
110
# File 'lib/structure.rb', line 108

def const_missing(name)
  Double.new(name)
end

.defaultsObject

Returns attribute keys and their default values.



59
60
61
# File 'lib/structure.rb', line 59

def defaults
  @defaults ||= {}
end

.inherited(child) ⇒ Object



112
113
114
# File 'lib/structure.rb', line 112

def inherited(child)
  child.def_delegator child, :defaults
end

.json_create(hsh) ⇒ Object

Recreates a structure out of its JSON representation.



64
65
66
67
# File 'lib/structure.rb', line 64

def json_create(hsh)
  hsh.delete('json_class')
  new(hsh)
end

.key(name, type = nil, default = nil) ⇒ Object

Defines an attribute.

Takes a name and, optionally, a type and default value.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/structure.rb', line 72

def key(name, type = nil, default = nil)
  name = name.to_sym

  if method_defined?(name)
    raise NameError, "#{name} is taken"
  end

  if !default || !type || default.is_a?(type)
    defaults[name] = default
  else
    binding.pry
    raise TypeError, "#{default} isn't a #{type}"
  end

  define_method(name) { attributes[name] }

  define_method("#{name}=") do |val|
    attributes[name] =
      if type.nil? || val.nil? || val.is_a?(type)
        val.dup rescue val
      elsif Kernel.respond_to?(type.to_s)
        Kernel.send(type.to_s, val)
      else
        raise TypeError, "#{val} isn't a #{type}"
      end
  end
end

.many(name) ⇒ Object

Defines an attribute that is an array and defaults to an empty one.



102
103
104
# File 'lib/structure.rb', line 102

def many(name)
  key name, Array, []
end

Instance Method Details

#==(other) ⇒ Object

Compares this object with another object for equality. A Structure is equal to the other object when both are of the same class and the their attributes are the same.



164
165
166
# File 'lib/structure.rb', line 164

def ==(other)
  other.is_a?(self.class) && attributes == other.attributes
end

#as_json(options = nil) ⇒ Object

Converts structure to a JSON representation.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/structure/active_support.rb', line 3

def as_json(options = nil)
  subset = if options
    if only = options[:only]
      attributes.slice(*Array.wrap(only))
    elsif except = options[:except]
      attributes.except(*Array.wrap(except))
    else
      attributes.dup
    end
  else
    attributes.dup
  end

  { JSON.create_id => self.class.name }.
    merge(subset)
end

#each(&block) ⇒ Object

Calls block once for each attribute in the structure, passing that attribute as a parameter.



134
135
136
# File 'lib/structure.rb', line 134

def each(&block)
  attributes.each { |v| block.call(v) }
end

#to_hashObject

Converts structure to a hash.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/structure.rb', line 139

def to_hash
  attributes.inject({}) do |a, (k, v)|
    a[k] =
      if v.respond_to?(:to_hash)
        v.to_hash
      elsif v.is_a?(Array)
        v.map { |e| e.respond_to?(:to_hash) ? e.to_hash : e }
      else
        v
      end

    a
  end
end

#to_json(*args) ⇒ Object

Converts structure to its JSON representation.



155
156
157
158
159
# File 'lib/structure.rb', line 155

def to_json(*args)
  { JSON.create_id => self.class.name }.
    merge(attributes).
    to_json(*args)
end