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.
Files changed (2) hide show
  1. data/lib/mongo_hash.rb +175 -0
  2. 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: []