Class: YAML_Model

Inherits:
Object
  • Object
show all
Defined in:
lib/yaml-model.rb,
lib/yaml-model/version.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =
"1.3.5"
@@volatile =
[ :@volatile ]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeYAML_Model

Returns a new instance of YAML_Model.



65
66
67
68
69
70
# File 'lib/yaml-model.rb', line 65

def initialize
  self.class.attributes.keys.each do |attribute|
    instance_eval( "@#{attribute} ||= self.class.__#{attribute}__default" )
    instance_eval( "__#{attribute}__assert_type" )
  end
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



31
32
33
# File 'lib/yaml-model.rb', line 31

def id
  @id
end

Class Method Details

.[](id) ⇒ Object



89
90
91
# File 'lib/yaml-model.rb', line 89

def self.[]( id )
  all.select{|n|n.id==id}.first
end

.allObject



35
36
37
# File 'lib/yaml-model.rb', line 35

def self.all
  @@database[ :data ][ self.name ] ||= []
end

.assert(assertion, info) ⇒ Object

Raises:



39
40
41
# File 'lib/yaml-model.rb', line 39

def self.assert( assertion, info )
  raise Error.new( info.inspect ) unless assertion
end

.assert_type(variable, types) ⇒ Object



43
44
45
# File 'lib/yaml-model.rb', line 43

def self.assert_type( variable, types )
  assert( [types].flatten.inject(false){|result,type|result||=(type===variable)}, "Invalid type: `#{variable.class.name}` for `#{self.name}::#{variable}` should be of: #{types.inspect}" )
end

.create(*args) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/yaml-model.rb', line 138

def self.create( *args )
  this = self.new( *args )
  this.instance_eval do
    @id = @@database[ :next_oid ]
    @id.freeze
  end
  @@database[ :next_oid ] += 1
  @@database[ :data ][ this.class.name ] ||= []
  @@database[ :data ][ this.class.name ] << this
  this
end

.each(&block) ⇒ Object



114
115
116
# File 'lib/yaml-model.rb', line 114

def self.each &block
  all.each &block
end

.filename=(filename) ⇒ Object



97
98
99
100
# File 'lib/yaml-model.rb', line 97

def self.filename=( filename )
  @@database_filename = filename
  self.load!
end

.filter(hash) ⇒ Object



122
123
124
125
126
127
128
# File 'lib/yaml-model.rb', line 122

def self.filter hash
  select do |this|
    hash.keys.inject( true ) do |result,variable|
      this.instance_eval( "@#{variable}" ) == hash[ variable ]
    end
  end
end

.has(that_attribute_plural, that_class, opts = {}) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/yaml-model.rb', line 176

def self.has( that_attribute_plural, that_class, opts = {} )
  options = {
    :many_to_many => false
  }.merge( opts )
  if options[ :many_to_many ]
    this_class = self
    this_class_name, that_class_name = [this_class,that_class].map{|n|n.name.split(':')[-1]}
    this_attribute_singular = this_class_name.downcase.to_sym
    that_attribute_singular = that_class_name.downcase.to_sym
    via_class_name = [ this_class_name, that_class_name ].sort.map{|n|n.capitalize}.join('')
    via_class = eval( "#{via_class_name}||=Class.new(YAML_Model) do
type :#{this_attribute_singular}, #{this_class}
type :#{that_attribute_singular}, #{that_class}
init #{[this_attribute_singular,that_attribute_singular].sort.map{|n|":#{n}"}.join(',')}
end" )
    via_attribute_plural = ( via_class_name.downcase + "s" ).to_sym

    this_class.has via_attribute_plural, via_class

    define_method that_attribute_plural do
      send( via_attribute_plural ).map do |via_instance|
        via_instance.send( that_attribute_singular )
      end
    end

    define_method "add_#{that_attribute_singular}".to_sym do |that_instance|
      via_instance = ( ( this_attribute_singular < that_attribute_singular ) ? via_class.create( self, that_instance ) : via_class.create( that_instance, self ) )
      via_instance.send( "#{this_attribute_singular}=".to_sym, self )
      via_instance.send( "#{that_attribute_singular}=".to_sym, that_instance )
    end

    define_method "remove_#{that_attribute_singular}".to_sym do |that_instance|
      via_instance = via_class.select{|n| n.send(this_attribute_singular).id == self.id && n.send(that_attribute_singular).id == that_instance.id }.first
      via_instance.send( :delete )
    end

  else

    define_method that_attribute_plural do
      that_class.select do |that_instance|
        if options[ that_class ]
          that_instance.instance_eval( options[ that_class ].to_s ).id == self.id
        else
          that_instance.instance_variables.inject( false ) do |result,variable|
            result ||= that_instance.instance_eval(variable.to_s).class == self.class && that_instance.instance_eval(variable.to_s).id == self.id
          end
        end
      end
    end

  end
end

.inherited(child) ⇒ Object



6
7
8
9
10
11
# File 'lib/yaml-model.rb', line 6

def self.inherited( child )
  child.instance_eval('@__attributes = {}')
  child.define_singleton_method( :attributes ) do
    @__attributes
  end
end

.init(*attributes, &block) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/yaml-model.rb', line 72

def self.init *attributes, &block
  define_method :initialize do |*args|
    raise ArgumentError.new( "wrong number of arguments (#{args.size} for #{attributes.size}" ) unless args.size == attributes.size

    attributes.each do |attribute|
      value = args.shift
      self.send( "#{attribute}=".to_sym, value )
    end

    # FIXME For some reason commands within this block to set attribute values
    # require the `self.` prefix or they just don't work
    self.instance_eval( &block ) if block_given?

    super()
  end
end

.inspectObject



158
159
160
# File 'lib/yaml-model.rb', line 158

def self.inspect
  all.map{|a|a.inspect}.join("\n")
end

.load!Object



93
94
95
# File 'lib/yaml-model.rb', line 93

def self.load!
  @@database = YAML.load( File.read( @@database_filename.to_s ) ) if File.exists?( @@database_filename.to_s )
end

.next_oidObject



25
26
27
# File 'lib/yaml-model.rb', line 25

def self.next_oid
  @@database[ :next_oid ]
end

.reset!Object



16
17
18
19
20
21
22
23
# File 'lib/yaml-model.rb', line 16

def self.reset!
  @@database_filename = nil

  @@database = {
    :next_oid => 1,
    :data => {}
  }
end

.save!Object



106
107
108
109
110
111
112
# File 'lib/yaml-model.rb', line 106

def self.save!
  if @@database_filename
    File.open( @@database_filename, 'w' ) do |file|
      file.write( self.to_yaml )
    end
  end
end

.select(&block) ⇒ Object



118
119
120
# File 'lib/yaml-model.rb', line 118

def self.select &block
  all.select &block
end

.sort_by(*attributes) ⇒ Object



168
169
170
171
172
# File 'lib/yaml-model.rb', line 168

def self.sort_by( *attributes )
  define_method '<=>'.to_sym do |other|
    attributes.map{|a|self.send(a)} <=> attributes.map{|a|other.send(a)}
  end
end

.to_yamlObject



102
103
104
# File 'lib/yaml-model.rb', line 102

def self.to_yaml
  @@database.to_yaml
end

.type(attr, types, options = {}, &block) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/yaml-model.rb', line 47

def self.type attr, types, options = {}, &block
  @__attributes[ attr ] = [ types, options ]
  define_method attr do
    instance_eval "@#{attr}"
  end
  define_method "#{attr}=".to_sym do |value|
    YAML_Model.assert_type value, types
    instance_exec( value, &block ) if block_given?
    instance_eval "@#{attr} = value"
  end
  define_singleton_method "__#{attr}__default".to_sym do
    options[ :default ]
  end
  define_method "__#{attr}__assert_type" do
    YAML_Model.assert_type( instance_eval( "@#{attr}" ), types )
  end
end

.volatile(variable) ⇒ Object



130
131
132
# File 'lib/yaml-model.rb', line 130

def self.volatile variable
  @@volatile << "@#{variable}".to_sym
end

Instance Method Details

#deleteObject



150
151
152
# File 'lib/yaml-model.rb', line 150

def delete
  @@database[ :data ][ self.class.name ].delete( self )
end

#inspectObject



162
163
164
165
166
# File 'lib/yaml-model.rb', line 162

def inspect
  keys = self.class.attributes.keys.sort
  keys.delete( :id )
  "#{self.class.name}[#{id}]{#{keys.map{|k|"#{k.inspect}=>#{self.send(k).inspect}"}.join(',')}}"
end

#to_sObject



154
155
156
# File 'lib/yaml-model.rb', line 154

def to_s
  "#{self.class.name}[#{id}]"
end

#to_yaml_propertiesObject



134
135
136
# File 'lib/yaml-model.rb', line 134

def to_yaml_properties
  instance_variables - @@volatile
end