mongo_hash 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/mongo_hash.rb +175 -0
- metadata +57 -0
data/lib/mongo_hash.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
class MongoHash < Hash
|
2
|
+
attr_accessor :collection
|
3
|
+
attr_accessor :new_record
|
4
|
+
attr_accessor :subkey
|
5
|
+
attr_accessor :_id
|
6
|
+
attr_accessor :query_hash
|
7
|
+
attr_accessor :fields
|
8
|
+
attr_accessor :dirty_keys
|
9
|
+
attr_accessor :delete_keys
|
10
|
+
|
11
|
+
|
12
|
+
### figure out how to make this one method
|
13
|
+
def get_options_specifier(subkey)
|
14
|
+
if subkey == ""
|
15
|
+
{}
|
16
|
+
else
|
17
|
+
{:fields => {'_id' => 1, subkey => 1}}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get_options_specifier(subkey)
|
22
|
+
if subkey == ""
|
23
|
+
{}
|
24
|
+
else
|
25
|
+
{:fields => {'_id' => 1, subkey => 1}}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Main find method to use for searching the mongo collection for a matching object
|
30
|
+
#
|
31
|
+
# @param [Mongo::Collection] the mongo collection object
|
32
|
+
# @param [Hash] the query specifier, in standard mongodb syntax, optional
|
33
|
+
# @param [String] the subkey attribute to base the return on, optional
|
34
|
+
# @return [Array] the list of matching MongoHash objects from the collection
|
35
|
+
|
36
|
+
def self.find(collection, query = {}, subkey = "")
|
37
|
+
options_specifier = get_options_specifier(subkey)
|
38
|
+
records = collection.find(query, options_specifier)
|
39
|
+
return [] if records.nil? or records == [] or records.count == 0
|
40
|
+
mhs = []
|
41
|
+
records.each{|record|
|
42
|
+
mhs << self.new(collection, record['_id'], record, subkey)
|
43
|
+
}
|
44
|
+
mhs
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds matching objects, or creates a blank one if not
|
48
|
+
#
|
49
|
+
# @todo Infer default values from the query specifier
|
50
|
+
# @param [Mongo::Collection] the mongo collection object
|
51
|
+
# @param [Hash] the query specifier, in standard mongodb syntax, optional
|
52
|
+
# @param [String] the subkey attribute to base the return on, optional
|
53
|
+
# @return [Array] the list of matching MongoHash objects from the collection, or an array with a blank MongoHash object if none found
|
54
|
+
|
55
|
+
def self.find_or_create(collection, query = {}, subkey = "")
|
56
|
+
result = self.find(collection, query, subkey)
|
57
|
+
if result == []
|
58
|
+
result = [self.new(collection)]
|
59
|
+
else
|
60
|
+
result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# MongoHash.new creates a new blank object tied to the specified collection or retrieves a specific object
|
65
|
+
#
|
66
|
+
# @param [Mongo::Collection] the mongo collection object
|
67
|
+
# @param [Object] the _id to query the collection for, optional
|
68
|
+
# @param [Hash] the default value to prepopulate into the returned object, optional
|
69
|
+
# @param [String] the subkey attribute to base the return on, optional
|
70
|
+
# @return [MongoHash] a single MongoHash object tied to the specified collection
|
71
|
+
|
72
|
+
def initialize(collection, _id = nil, default = {}, subkey = "")
|
73
|
+
@subkey = subkey
|
74
|
+
@collection = collection
|
75
|
+
if _id.nil?
|
76
|
+
@new_record = true
|
77
|
+
else
|
78
|
+
@_id = _id
|
79
|
+
@new_record = false
|
80
|
+
end
|
81
|
+
@dirty_keys = []
|
82
|
+
@delete_keys = []
|
83
|
+
# super() {|h, k| h[k] = Hash.new()}
|
84
|
+
super()
|
85
|
+
if default == {}
|
86
|
+
# puts default.inspect
|
87
|
+
# puts _id
|
88
|
+
unless @new_record
|
89
|
+
options_specifier = self.get_options_specifier(subkey)
|
90
|
+
default = collection.find({'_id' => _id}, options_specifier).first
|
91
|
+
end
|
92
|
+
end
|
93
|
+
default.delete('_id')
|
94
|
+
default.delete(:_id)
|
95
|
+
default.each{|k,v|
|
96
|
+
# puts [k,v].inspect
|
97
|
+
self[k] = v
|
98
|
+
} unless default.nil? or default.keys.length == 0
|
99
|
+
@dirty_keys = []
|
100
|
+
@delete_keys = []
|
101
|
+
end
|
102
|
+
|
103
|
+
# Overrides key assignment with mongohash metadata
|
104
|
+
|
105
|
+
def []=(key,value)
|
106
|
+
@dirty_keys << key
|
107
|
+
@delete_keys -= [key]
|
108
|
+
super
|
109
|
+
end
|
110
|
+
|
111
|
+
# Overrides delete assignment with mongohash metadata
|
112
|
+
|
113
|
+
def delete(key, mark = true)
|
114
|
+
if mark == true
|
115
|
+
@delete_keys << key
|
116
|
+
end
|
117
|
+
super(key)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Removes the tied object from the mongo collection
|
121
|
+
|
122
|
+
def destroy()
|
123
|
+
unless @new_record == true
|
124
|
+
retval = @collection.remove({'_id' => self._id}, :safe => true)
|
125
|
+
@new_record = true
|
126
|
+
self._id = nil
|
127
|
+
## maybe some other things
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Persists the tied object to the mongo collection
|
132
|
+
# if a new record, assigns self._id after success
|
133
|
+
# if no keys have been modified, returns immediately
|
134
|
+
# attempts to be smart about updating individual keys instead of overwriting entire record
|
135
|
+
|
136
|
+
def save()
|
137
|
+
@dirty_keys.uniq!
|
138
|
+
@delete_keys.uniq!
|
139
|
+
if @subkey == ""
|
140
|
+
return nil if @dirty_keys.length == 0 and @delete_keys.length == 0
|
141
|
+
end
|
142
|
+
|
143
|
+
if @new_record == true
|
144
|
+
self['created_at'] = Time.now.to_i
|
145
|
+
id = @collection.insert(self, :safe => true)
|
146
|
+
self._id = id
|
147
|
+
self.delete(:_id, false)
|
148
|
+
@new_record = false
|
149
|
+
else
|
150
|
+
self['updated_at'] = Time.now.to_i
|
151
|
+
|
152
|
+
## @todo: what if the object with that key doesn't exist in the db when it's saved?
|
153
|
+
|
154
|
+
if @subkey == ""
|
155
|
+
if (@dirty_keys.length + @delete_keys.length) < self.keys.length / 2
|
156
|
+
update_hash = {}
|
157
|
+
@dirty_keys.map{|key| update_hash[key] = self[key]}
|
158
|
+
delete_hash = {}
|
159
|
+
@delete_keys.map{|key| delete_hash[key] = 1}
|
160
|
+
@collection.update({'_id' => self._id}, {'$unset' => delete_hash, '$set' => update_hash }, :safe => true)
|
161
|
+
|
162
|
+
retval = true
|
163
|
+
else
|
164
|
+
retval = @collection.update({'_id' => self._id}, self, :safe => true)
|
165
|
+
end
|
166
|
+
else
|
167
|
+
retval = @collection.update({'_id' => self._id}, {'$set' => {@subkey => self[@subkey]} }, :safe => true)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
@delete_keys = []
|
171
|
+
@dirty_keys = []
|
172
|
+
retval
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongo_hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Fields
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mongo
|
16
|
+
requirement: &70199814585480 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70199814585480
|
25
|
+
description: A simple front-end for mongodb persistence for ruby hashes
|
26
|
+
email: adam@morningside-analytics.com
|
27
|
+
executables: []
|
28
|
+
extensions: []
|
29
|
+
extra_rdoc_files: []
|
30
|
+
files:
|
31
|
+
- lib/mongo_hash.rb
|
32
|
+
homepage: http://rubygems.org/gems/mongo_hash
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements:
|
51
|
+
- Mongo Gem
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.15
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: MongoHash
|
57
|
+
test_files: []
|