Class: Hashie::Nash

Inherits:
Trash
  • Object
show all
Includes:
PrettyInspect
Defined in:
lib/nashie.rb

Overview

A Nash is a Nested Defined Hash and is an extension of a Dash A Nash allows you to create complex assignments composing of several nested Dashes

Nashes are useful when you need to create a lightweigth nested data object, ideal for validating JSON

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

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



133
134
135
136
137
138
139
140
141
# File 'lib/nashie.rb', line 133

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

  # override whatever Dash has set
  attributes.each_pair do |att, value|
    self.send((att.to_s + '=').to_sym,value)
  end if attributes
  assert_required_properties_set!
end

Class Attribute Details

.class_propertiesObject (readonly)

Returns the value of attribute class_properties.



18
19
20
# File 'lib/nashie.rb', line 18

def class_properties
  @class_properties
end

Class Method Details

.inherited(klass) ⇒ Object



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

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

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

Defines a property on the Nash. 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 Nash.

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

  • :class - Specify a class for this property that should be instantiated when an assignment is made to this property.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/nashie.rb', line 37

def self.property(property_name, options = {}, &block)
      if block_given?
        # if my college professor sees this he will personally come and beat the shit out of me :(
        class_name = property_name.to_s.capitalize
        class_ref = const_set(class_name, Class.new(Hashie::Nash))
        class_ref.class_eval &block
        options[:class] = class_name
      end
      property_name = property_name.to_sym

      self.properties << property_name

      if options.has_key?(:class)
        class_name = options[:class].to_s
        class_properties[property_name] = class_name if options.delete(:class)
        if not options[:collection]
          class_eval <<-ACCESSORS
            def #{property_name}(&block)
              self.[](#{property_name.to_s.inspect}, &block)
            end

            def #{property_name}=(value)
              self.[]=(#{property_name.to_s.inspect}, #{class_properties[property_name]}.new(value))
            end

          ACCESSORS
        else
          # expect arrays and convert single items into arrays
          class_eval <<-ACCESSORS
            def #{property_name}(&block)
              self.[](#{property_name.to_s.inspect}, &block)
            end

            def #{property_name}=(value)
              if not value.is_a? Array
                if #{options[:permissive]}
                  value = [value]
                else
                  raise "#{property_name} requires an array, use :permissive => true to automatically convert to array"
                end
              end
              values = []
              value.each do |item|
                values << #{class_properties[property_name]}.new(item)
              end
              values =
              self.[]=(#{property_name.to_s.inspect}, values)
            end

          ACCESSORS

        end


      elsif
        class_properties[property_name] = nil
      end

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

      unless instance_methods.map { |m| m.to_s }.include?("#{property_name}=")
        class_eval <<-ACCESSORS
          def #{property_name}(&block)
            self.[](#{property_name.to_s.inspect}, &block)
          end

          def #{property_name}=(value)
            self.[]=(#{property_name.to_s.inspect}, value)
          end
        ACCESSORS
      end

      if defined? @subclasses
        @subclasses.each { |klass| klass.property(property_name, options) }
      end
      required_properties << property_name if options.delete(:required)
end