mongoid_ext 0.6.2 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +20 -18
- data/VERSION +1 -1
- data/lib/mongoid_ext/criteria_ext.rb +0 -3
- data/lib/mongoid_ext/document_ext.rb +8 -10
- data/lib/mongoid_ext/file.rb +20 -4
- data/lib/mongoid_ext/file_list.rb +28 -2
- data/lib/mongoid_ext/filter/result_set.rb +3 -0
- data/lib/mongoid_ext/js/filter.js +42 -21
- data/lib/mongoid_ext/js/find_tags.js +7 -4
- data/lib/mongoid_ext/js/tag_cloud.js +17 -15
- data/lib/mongoid_ext/modifiers.rb +24 -25
- data/lib/mongoid_ext/paranoia.rb +1 -1
- data/lib/mongoid_ext/patches.rb +14 -1
- data/lib/mongoid_ext/storage.rb +23 -14
- data/lib/mongoid_ext/types/embedded_hash.rb +40 -5
- data/lib/mongoid_ext/types/open_struct.rb +13 -9
- data/lib/mongoid_ext/types/timestamp.rb +6 -4
- data/lib/mongoid_ext/types/translation.rb +4 -2
- data/lib/mongoid_ext/versioning.rb +62 -65
- data/lib/mongoid_ext/voteable.rb +8 -8
- data/mongoid_ext.gemspec +11 -13
- data/test/helper.rb +1 -2
- data/test/models.rb +1 -1
- data/test/test_storage.rb +1 -1
- data/test/types/test_open_struct.rb +1 -1
- metadata +172 -165
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,36 +1,37 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.
|
5
|
-
activesupport (= 3.
|
6
|
-
builder (~>
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
activemodel (3.2.1)
|
5
|
+
activesupport (= 3.2.1)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activesupport (3.2.1)
|
8
|
+
i18n (~> 0.6)
|
9
|
+
multi_json (~> 1.0)
|
10
|
+
bson (1.5.2)
|
11
|
+
builder (3.0.0)
|
11
12
|
differ (0.1.2)
|
13
|
+
encryptor (1.1.3)
|
12
14
|
git (1.2.5)
|
13
|
-
i18n (0.
|
15
|
+
i18n (0.6.0)
|
14
16
|
jeweler (1.5.2)
|
15
17
|
bundler (~> 1.0.0)
|
16
18
|
git (>= 1.2.5)
|
17
19
|
rake
|
18
20
|
jnunemaker-matchy (0.4.0)
|
19
21
|
mocha (0.9.12)
|
20
|
-
mongo (1.
|
21
|
-
bson (
|
22
|
-
mongoid (2.
|
23
|
-
activemodel (~> 3.
|
22
|
+
mongo (1.5.2)
|
23
|
+
bson (= 1.5.2)
|
24
|
+
mongoid (2.4.4)
|
25
|
+
activemodel (~> 3.1)
|
24
26
|
mongo (~> 1.3)
|
25
27
|
tzinfo (~> 0.3.22)
|
26
|
-
|
27
|
-
rake (0.
|
28
|
+
multi_json (1.0.4)
|
29
|
+
rake (0.9.2.2)
|
28
30
|
shoulda (2.11.3)
|
29
31
|
timecop (0.3.5)
|
30
|
-
tzinfo (0.3.
|
32
|
+
tzinfo (0.3.31)
|
31
33
|
uuidtools (2.1.2)
|
32
|
-
|
33
|
-
yard (0.6.7)
|
34
|
+
yard (0.6.8)
|
34
35
|
|
35
36
|
PLATFORMS
|
36
37
|
ruby
|
@@ -38,11 +39,12 @@ PLATFORMS
|
|
38
39
|
DEPENDENCIES
|
39
40
|
bundler (~> 1.0.0)
|
40
41
|
differ (>= 0.1.2)
|
42
|
+
encryptor (~> 1.1.3)
|
41
43
|
i18n
|
42
44
|
jeweler (~> 1.5.2)
|
43
45
|
jnunemaker-matchy (~> 0.4)
|
44
46
|
mocha (~> 0.9.4)
|
45
|
-
mongoid (~> 2.
|
47
|
+
mongoid (~> 2.3)
|
46
48
|
shoulda (~> 2.11.3)
|
47
49
|
timecop
|
48
50
|
tzinfo
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.1
|
@@ -12,18 +12,16 @@ module MongoidExt
|
|
12
12
|
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
return true if !changed? && !opts.delete(:force)
|
15
|
+
def raw_save(opts = {})
|
16
|
+
return true if !changed? && !opts.delete(:force)
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
18
|
+
if (opts.delete(:validate) != false || valid?)
|
19
|
+
self.collection.save(raw_attributes, opts)
|
20
|
+
true
|
21
|
+
else
|
22
|
+
false
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
28
26
|
end
|
29
|
-
Mongoid::Document.send(:include, MongoidExt::DocumentExt)
|
27
|
+
Mongoid::Document.send(:include, MongoidExt::DocumentExt)
|
data/lib/mongoid_ext/file.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module MongoidExt
|
2
2
|
class File < EmbeddedHash
|
3
3
|
attr_accessor :_root_document
|
4
|
+
attr_accessor :_list_name
|
4
5
|
|
5
6
|
field :name, :type => String
|
6
7
|
field :extension, :type => String
|
7
8
|
field :content_type, :type => String
|
9
|
+
field :md5, :type => String
|
8
10
|
|
9
11
|
alias :filename :name
|
10
12
|
|
11
13
|
def put(filename, io, options = {})
|
14
|
+
mark_parent!
|
15
|
+
|
12
16
|
options[:_id] = grid_filename
|
13
17
|
|
14
18
|
options[:metadata] ||= {}
|
@@ -26,7 +30,10 @@ module MongoidExt
|
|
26
30
|
if defined?(Magic) && Magic.respond_to?(:guess_string_mime_type)
|
27
31
|
data = io.read(256) # be nice with memory usage
|
28
32
|
self["content_type"] = options[:content_type] = Magic.guess_string_mime_type(data.to_s)
|
29
|
-
|
33
|
+
|
34
|
+
if self.fetch("extension", nil).nil?
|
35
|
+
self["extension"] = options[:content_type].to_s.split("/").last.split("-").last
|
36
|
+
end
|
30
37
|
|
31
38
|
if io.respond_to?(:rewind)
|
32
39
|
io.rewind
|
@@ -38,6 +45,11 @@ module MongoidExt
|
|
38
45
|
options[:filename] = grid_filename
|
39
46
|
gridfs.delete(grid_filename)
|
40
47
|
gridfs.put(io, options)
|
48
|
+
|
49
|
+
if file = self.get
|
50
|
+
file.send(:get_md5)
|
51
|
+
self['md5'] = file.server_md5
|
52
|
+
end
|
41
53
|
end
|
42
54
|
|
43
55
|
def get
|
@@ -61,11 +73,11 @@ module MongoidExt
|
|
61
73
|
end
|
62
74
|
|
63
75
|
def size
|
64
|
-
get.file_length
|
76
|
+
get.file_length rescue nil
|
65
77
|
end
|
66
78
|
|
67
79
|
def read(size = nil)
|
68
|
-
self.get.read(size)
|
80
|
+
self.get.read(size) rescue nil
|
69
81
|
end
|
70
82
|
|
71
83
|
def delete
|
@@ -74,7 +86,7 @@ module MongoidExt
|
|
74
86
|
end
|
75
87
|
|
76
88
|
def method_missing(name, *args, &block)
|
77
|
-
f = self.get
|
89
|
+
f = self.get
|
78
90
|
if f && f.respond_to?(name)
|
79
91
|
f.send(name, *args, &block)
|
80
92
|
else
|
@@ -86,5 +98,9 @@ module MongoidExt
|
|
86
98
|
def gridfs
|
87
99
|
_root_document.class.gridfs
|
88
100
|
end
|
101
|
+
|
102
|
+
def mark_parent!
|
103
|
+
_root_document.send("#{_list_name}_will_change!")
|
104
|
+
end
|
89
105
|
end
|
90
106
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module MongoidExt
|
2
2
|
class FileList < EmbeddedHash
|
3
3
|
attr_accessor :parent_document
|
4
|
+
attr_accessor :list_name
|
4
5
|
|
5
6
|
def put(id, io, metadata = {})
|
7
|
+
mark_parent!
|
8
|
+
|
6
9
|
if !parent_document.new_record?
|
7
10
|
filename = id
|
8
11
|
if io.respond_to?(:original_filename)
|
@@ -33,20 +36,24 @@ module MongoidExt
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def get(id)
|
39
|
+
mark_parent!
|
40
|
+
|
36
41
|
if id.kind_of?(MongoidExt::File)
|
37
42
|
self[id.id] = id
|
38
43
|
return id
|
39
44
|
end
|
40
45
|
|
41
46
|
id = id.to_s.gsub(".", "_")
|
42
|
-
file = self
|
47
|
+
file = self.fetch(id, nil)
|
48
|
+
|
43
49
|
if file.nil?
|
44
50
|
file = self[id] = MongoidExt::File.new
|
45
|
-
elsif file.class == BSON::OrderedHash
|
51
|
+
elsif file.class == ::Hash || file.class == BSON::OrderedHash
|
46
52
|
file = self[id] = MongoidExt::File.new(file)
|
47
53
|
end
|
48
54
|
|
49
55
|
file._root_document = parent_document
|
56
|
+
file._list_name = self.list_name
|
50
57
|
file
|
51
58
|
end
|
52
59
|
|
@@ -60,6 +67,8 @@ module MongoidExt
|
|
60
67
|
end
|
61
68
|
|
62
69
|
def delete(id)
|
70
|
+
mark_parent!
|
71
|
+
|
63
72
|
file = self.get(id)
|
64
73
|
super(id)
|
65
74
|
file.delete
|
@@ -70,5 +79,22 @@ module MongoidExt
|
|
70
79
|
get(id).delete
|
71
80
|
end
|
72
81
|
end
|
82
|
+
|
83
|
+
def serialize(v)
|
84
|
+
v
|
85
|
+
end
|
86
|
+
|
87
|
+
def deserialize(v)
|
88
|
+
doc = self.class.new
|
89
|
+
v.each do |k,v|
|
90
|
+
doc[k] = MongoidExt::File.new(v)
|
91
|
+
end
|
92
|
+
|
93
|
+
doc
|
94
|
+
end
|
95
|
+
|
96
|
+
def mark_parent!
|
97
|
+
parent_document.send("#{list_name}_will_change!")
|
98
|
+
end
|
73
99
|
end
|
74
100
|
end
|
@@ -9,6 +9,8 @@ module MongoidExt
|
|
9
9
|
attr_reader :parsed_query
|
10
10
|
attr_reader :mongo_query
|
11
11
|
alias limit per_page
|
12
|
+
alias :total_count :total_entries
|
13
|
+
alias :limit_value :per_page
|
12
14
|
|
13
15
|
def initialize(total_entries, parsed_query, mongo_query, current_page, per_page=nil)
|
14
16
|
@total_entries = total_entries.to_i
|
@@ -21,6 +23,7 @@ module MongoidExt
|
|
21
23
|
def total_pages
|
22
24
|
(total_entries / per_page.to_f).ceil
|
23
25
|
end
|
26
|
+
alias :num_pages :total_pages
|
24
27
|
|
25
28
|
def out_of_bounds?
|
26
29
|
current_page > total_pages
|
@@ -8,28 +8,49 @@ function filter(collection, q, config) {
|
|
8
8
|
}
|
9
9
|
|
10
10
|
var time = new Date().getTime();
|
11
|
-
db[collection].find(q, fields).limit(500).forEach(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
var
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
11
|
+
db[collection].find(q, fields).limit(500).forEach(function(doc) {
|
12
|
+
var rac = db.eval(
|
13
|
+
function(doc, config) {
|
14
|
+
var r = [];
|
15
|
+
var c = 0;
|
16
|
+
|
17
|
+
var set = {};
|
18
|
+
for(var i = 0; i<doc._keywords.length; i++) {
|
19
|
+
set[doc._keywords[i]] = true;
|
20
|
+
}
|
21
|
+
|
22
|
+
var score = 0.0;
|
23
|
+
for(var i = 0; i < config.words.length; i++) {
|
24
|
+
var word = config.words[i];
|
25
|
+
if(set[word]) {
|
26
|
+
score += 15.0;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
for(var i = 0; i < config.stemmed.length; i++) {
|
31
|
+
var word = config.stemmed[i];
|
32
|
+
if(set[word]) {
|
33
|
+
score += (1.0 + word.length);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
if(score >= config.min_score || 1.0 ) {
|
38
|
+
delete doc._keywords;
|
39
|
+
r.push({'score': score, 'doc': doc});
|
40
|
+
c += 1;
|
41
|
+
}
|
42
|
+
|
43
|
+
return [r, c];
|
44
|
+
},
|
45
|
+
doc,
|
46
|
+
config
|
47
|
+
);
|
48
|
+
|
49
|
+
for(var i = 0; i<rac[0].length; i++) {
|
50
|
+
results.push(rac[0][i]);
|
31
51
|
}
|
32
|
-
|
52
|
+
counter += rac[1];
|
53
|
+
});
|
33
54
|
|
34
55
|
var sorted = results.sort(function(a,b) {
|
35
56
|
return b.score - a.score;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
function find_tags(collection, regex, query, limit) {
|
2
|
-
var
|
2
|
+
var counts = db.eval(
|
3
|
+
function(collection, regex, query){
|
3
4
|
var counts = {};
|
4
5
|
db[collection].find(query, {"tags":1}).limit(500).forEach(
|
5
6
|
function(p){
|
@@ -13,9 +14,11 @@ function find_tags(collection, regex, query, limit) {
|
|
13
14
|
}
|
14
15
|
);
|
15
16
|
return counts;
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
},
|
18
|
+
collection,
|
19
|
+
regex,
|
20
|
+
query
|
21
|
+
);
|
19
22
|
|
20
23
|
var tags = [];
|
21
24
|
for ( var tag in counts ){
|
@@ -1,22 +1,24 @@
|
|
1
1
|
// TODO: port it to map reduce
|
2
2
|
function tagCloud(collection, q, limit) {
|
3
|
-
var
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
var
|
10
|
-
|
3
|
+
var counts = db.eval(
|
4
|
+
function(collection, q){
|
5
|
+
var counts = {constructor: 0};
|
6
|
+
db[collection].find(q, {"tags":1}).limit(500).forEach(
|
7
|
+
function(p){
|
8
|
+
if ( p.tags ){
|
9
|
+
for ( var i=0; i<p.tags.length; i++ ){
|
10
|
+
var name = p.tags[i];
|
11
|
+
counts[name] = 1 + ( counts[name] || 0 );
|
12
|
+
}
|
11
13
|
}
|
12
14
|
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
);
|
16
|
+
if(counts["constructor"] == 0) { delete counts.constructor; }
|
17
|
+
return counts;
|
18
|
+
},
|
19
|
+
collection,
|
20
|
+
q
|
21
|
+
);
|
20
22
|
|
21
23
|
// maybe sort to by nice
|
22
24
|
var sorted = [];
|
@@ -54,38 +54,37 @@ module MongoidExt
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
#InstanceMethods
|
58
|
+
def unset(update)
|
59
|
+
self.class.unset({:_id => id}, update)
|
60
|
+
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
def increment(update)
|
63
|
+
self.class.increment({:_id => id}, update)
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
def decrement(update)
|
67
|
+
self.class.decrement({:_id => id}, update)
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
def override(update)
|
71
|
+
self.class.override({:_id => id}, update)
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
def push(update)
|
75
|
+
self.class.push({:_id => id}, update)
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
def pull(update)
|
79
|
+
self.class.pull({:_id => id}, update)
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
def push_uniq(update)
|
83
|
+
self.class.push_uniq({:_id => id}, update)
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
end
|
86
|
+
def pop(update)
|
87
|
+
self.class.pop({:_id => id}, update)
|
89
88
|
end
|
90
89
|
end
|
91
90
|
end
|