Class: MongoHash

Inherits:
Hash
  • Object
show all
Defined in:
lib/mongo_hash.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection, _id = nil, default = {}, subkey = "") ⇒ MongoHash

MongoHash.new creates a new blank object tied to the specified collection or retrieves a specific object

Parameters:

  • the (Mongo::Collection)

    mongo collection object

  • the (Object)

    _id to query the collection for, optional

  • the (Hash)

    default value to prepopulate into the returned object, optional

  • the (String)

    subkey attribute to base the return on, optional



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
# File 'lib/mongo_hash.rb', line 72

def initialize(collection, _id = nil, default = {}, subkey = "")
  @subkey = subkey
  @collection = collection
  if _id.nil?
    @new_record = true
  else
    @_id = _id
    @new_record = false
  end
  @dirty_keys = []
  @delete_keys = []
#    super() {|h, k| h[k] = Hash.new()}
  super()
  if default == {}
#        puts default.inspect
#        puts _id
    unless @new_record
      options_specifier = self.get_options_specifier(subkey)
      default = collection.find({'_id' => _id}, options_specifier).first
    end
  end
  default.delete('_id')
  default.delete(:_id)    
  default.each{|k,v|
#      puts [k,v].inspect
    self[k] = v
  } unless default.nil? or default.keys.length == 0
  @dirty_keys = []
  @delete_keys = []
end

Instance Attribute Details

#_idObject

Returns the value of attribute _id.



5
6
7
# File 'lib/mongo_hash.rb', line 5

def _id
  @_id
end

#collectionObject

Returns the value of attribute collection.



2
3
4
# File 'lib/mongo_hash.rb', line 2

def collection
  @collection
end

#delete_keysObject

Returns the value of attribute delete_keys.



9
10
11
# File 'lib/mongo_hash.rb', line 9

def delete_keys
  @delete_keys
end

#dirty_keysObject

Returns the value of attribute dirty_keys.



8
9
10
# File 'lib/mongo_hash.rb', line 8

def dirty_keys
  @dirty_keys
end

#fieldsObject

Returns the value of attribute fields.



7
8
9
# File 'lib/mongo_hash.rb', line 7

def fields
  @fields
end

#new_recordObject

Returns the value of attribute new_record.



3
4
5
# File 'lib/mongo_hash.rb', line 3

def new_record
  @new_record
end

#query_hashObject

Returns the value of attribute query_hash.



6
7
8
# File 'lib/mongo_hash.rb', line 6

def query_hash
  @query_hash
end

#subkeyObject

Returns the value of attribute subkey.



4
5
6
# File 'lib/mongo_hash.rb', line 4

def subkey
  @subkey
end

Class Method Details

.find(collection, query = {}, subkey = "") ⇒ Array

Main find method to use for searching the mongo collection for a matching object

Parameters:

  • the (Mongo::Collection)

    mongo collection object

  • the (Hash)

    query specifier, in standard mongodb syntax, optional

  • the (String)

    subkey attribute to base the return on, optional

Returns:

  • (Array)

    the list of matching MongoHash objects from the collection



36
37
38
39
40
41
42
43
44
45
# File 'lib/mongo_hash.rb', line 36

def self.find(collection, query = {}, subkey = "")
  options_specifier = get_options_specifier(subkey)
  records = collection.find(query, options_specifier)
  return [] if records.nil? or records == [] or records.count == 0
  mhs = []
  records.each{|record|
    mhs << self.new(collection, record['_id'], record, subkey)
  }
  mhs
end

.find_or_create(collection, query = {}, subkey = "") ⇒ Array

TODO:

Infer default values from the query specifier

Finds matching objects, or creates a blank one if not

Parameters:

  • the (Mongo::Collection)

    mongo collection object

  • the (Hash)

    query specifier, in standard mongodb syntax, optional

  • the (String)

    subkey attribute to base the return on, optional

Returns:

  • (Array)

    the list of matching MongoHash objects from the collection, or an array with a blank MongoHash object if none found



55
56
57
58
59
60
61
62
# File 'lib/mongo_hash.rb', line 55

def self.find_or_create(collection, query = {}, subkey = "")
  result = self.find(collection, query, subkey)
  if result == []
    result = [self.new(collection)]
  else
    result
  end
end

.get_options_specifier(subkey) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/mongo_hash.rb', line 21

def self.get_options_specifier(subkey)
  if subkey == ""
    {}
  else
    {:fields => {'_id' => 1, subkey => 1}}
  end
end

Instance Method Details

#[]=(key, value) ⇒ Object

Overrides key assignment with mongohash metadata



105
106
107
108
109
# File 'lib/mongo_hash.rb', line 105

def []=(key,value)
  @dirty_keys << key
  @delete_keys -= [key]
  super
end

#delete(key, mark = true) ⇒ Object

Overrides delete assignment with mongohash metadata



113
114
115
116
117
118
# File 'lib/mongo_hash.rb', line 113

def delete(key, mark = true)
  if mark == true
    @delete_keys << key
  end
  super(key)
end

#destroyObject

Removes the tied object from the mongo collection



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

def destroy()
  unless @new_record == true
    retval = @collection.remove({'_id' => self._id}, :w => 1)
    @new_record = true
    self._id = nil
    ## maybe some other things
  end
end

#get_options_specifier(subkey) ⇒ Object

figure out how to make this one method



13
14
15
16
17
18
19
# File 'lib/mongo_hash.rb', line 13

def get_options_specifier(subkey)
  if subkey == ""
    {}
  else
    {:fields => {'_id' => 1, subkey => 1}}
  end
end

#saveObject

Persists the tied object to the mongo collection if a new record, assigns self._id after success if no keys have been modified, returns immediately attempts to be smart about updating individual keys instead of overwriting entire record



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/mongo_hash.rb', line 136

def save()
  @dirty_keys.uniq!
  @delete_keys.uniq!
  if @subkey == ""
    return nil if @dirty_keys.length == 0 and @delete_keys.length == 0
  end

  if @new_record == true
    self['created_at'] = Time.now.to_i
    id = @collection.insert(self, :w => 1)
    self._id = id
    self.delete(:_id, false)
    @new_record = false
  else
    self['updated_at'] = Time.now.to_i

    ## @todo: what if the object with that key doesn't exist in the db when it's saved?

    if @subkey == ""
      if (@dirty_keys.length + @delete_keys.length) < self.keys.length / 2
        update_hash = {}
        @dirty_keys.map{|key| update_hash[key] = self[key]}
        delete_hash = {}
        @delete_keys.map{|key| delete_hash[key] = 1}
        @collection.update({'_id' => self._id}, {'$unset' => delete_hash, '$set' => update_hash }, :w => 1)           
        
        retval = true
      else
        retval = @collection.update({'_id' => self._id}, self, :w => 1)
      end
    else
      retval = @collection.update({'_id' => self._id}, {'$set' => {@subkey => self[@subkey]} }, :w => 1)
    end
  end
  @delete_keys = []
  @dirty_keys = []
  retval
end