mongo_hash 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []