Class: Hashie::Dash

Inherits:
Hash
  • Object
show all
Includes:
Extensions::PrettyInspect
Defined in:
lib/hashie/dash.rb

Overview

A Dash is a 'defined' or 'discrete' Hash, that is, a Hash that has a set of defined keys that are accessible (with optional defaults) and only those keys may be set or read.

Dashes are useful when you need to create a very simple lightweight data object that needs even fewer options and resources than something like a DataMapper resource.

It is preferrable to a Struct because of the in-class API for defining properties as well as per-property defaults.

Direct Known Subclasses

Trash

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Extensions::PrettyInspect

#hashie_inspect, included

Methods inherited from Hash

#to_hash, #to_json, #to_mash

Methods included from Extensions::StringifyKeys

#stringify_keys, #stringify_keys!

Constructor Details

#initialize(attributes = {}, &block) ⇒ Dash

You may initialize a Dash with an attributes hash just like you would many other kinds of data objects.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/hashie/dash.rb', line 88

def initialize(attributes = {}, &block)
  super(&block)

  self.class.defaults.each_pair do |prop, value|
    self[prop] = begin
      value.dup
    rescue TypeError
      value
    end
  end

  initialize_attributes(attributes)
  assert_required_attributes_set!
end

Class Attribute Details

.defaultsObject (readonly)

Returns the value of attribute defaults.



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

def defaults
  @defaults
end

.propertiesObject (readonly)

Returns the value of attribute properties.



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

def properties
  @properties
end

.required_propertiesObject (readonly)

Returns the value of attribute required_properties.



60
61
62
# File 'lib/hashie/dash.rb', line 60

def required_properties
  @required_properties
end

Class Method Details

.inherited(klass) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/hashie/dash.rb', line 66

def self.inherited(klass)
  super
  (@subclasses ||= Set.new) << klass
  klass.instance_variable_set('@properties', properties.dup)
  klass.instance_variable_set('@defaults', defaults.dup)
  klass.instance_variable_set('@required_properties', required_properties.dup)
end

.property(property_name, options = {}) ⇒ Object

Defines a property on the Dash. Options are as follows:

  • :default - Specify a default value for this property, to be returned before a value is set on the property in a new Dash.

  • :required - Specify the value as required for this property, to raise an error if a value is unset in a new or existing Dash.

  • :message - Specify custom error message for required property



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/hashie/dash.rb', line 32

def self.property(property_name, options = {})
  properties << property_name

  if options.key?(:default)
    defaults[property_name] = options[:default]
  elsif defaults.key?(property_name)
    defaults.delete property_name
  end

  unless instance_methods.map(&:to_s).include?("#{property_name}=")
    define_method(property_name) { |&block| self.[](property_name, &block) }
    property_assignment = property_name.to_s.concat('=').to_sym
    define_method(property_assignment) { |value| self.[]=(property_name, value) }
  end

  if defined? @subclasses
    @subclasses.each { |klass| klass.property(property_name, options) }
  end

  if options.delete(:required)
    required_properties[property_name] = options.delete(:message) || "is required for #{name}."
  else
    fail ArgumentError, 'The :message option should be used with :required option.' if options.key?(:message)
  end
end

.property?(name) ⇒ Boolean

Check to see if the specified property has already been defined.

Returns:

  • (Boolean)


76
77
78
# File 'lib/hashie/dash.rb', line 76

def self.property?(name)
  properties.include? name
end

.required?(name) ⇒ Boolean

Check to see if the specified property is required.

Returns:

  • (Boolean)


82
83
84
# File 'lib/hashie/dash.rb', line 82

def self.required?(name)
  required_properties.key? name
end

Instance Method Details

#[](property) ⇒ Object

Retrieve a value from the Dash (will return the property's default value if it hasn't been set).



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/hashie/dash.rb', line 109

def [](property)
  assert_property_exists! property
  value = super(property)
  # If the value is a lambda, proc, or whatever answers to call, eval the thing!
  if value.is_a? Proc
    self[property] = value.call # Set the result of the call as a value
  else
    yield value if block_given?
    value
  end
end

#[]=(property, value) ⇒ Object

Set a value on the Dash in a Hash-like way. Only works on pre-existing properties.



123
124
125
126
127
# File 'lib/hashie/dash.rb', line 123

def []=(property, value)
  assert_property_required! property, value
  assert_property_exists! property
  super(property, value)
end

#merge(other_hash) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/hashie/dash.rb', line 129

def merge(other_hash)
  new_dash = dup
  other_hash.each do |k, v|
    new_dash[k] = block_given? ? yield(k, self[k], v) : v
  end
  new_dash
end

#merge!(other_hash) ⇒ Object



137
138
139
140
141
142
# File 'lib/hashie/dash.rb', line 137

def merge!(other_hash)
  other_hash.each do |k, v|
    self[k] = block_given? ? yield(k, self[k], v) : v
  end
  self
end

#replace(other_hash) ⇒ Object



144
145
146
147
148
149
# File 'lib/hashie/dash.rb', line 144

def replace(other_hash)
  other_hash = self.class.defaults.merge(other_hash)
  (keys - other_hash.keys).each { |key| delete(key) }
  other_hash.each { |key, value| self[key] = value }
  self
end

#update_attributes!(attributes) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/hashie/dash.rb', line 151

def update_attributes!(attributes)
  initialize_attributes(attributes)

  self.class.defaults.each_pair do |prop, value|
    self[prop] = begin
      value.dup
    rescue TypeError
      value
    end if self[prop].nil?
  end
  assert_required_attributes_set!
end