voteable_mongo 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.9.2
2
+ * Replace votee_type to votee_class
3
+ * Bug fixes
4
+
1
5
  == 0.9.1
2
6
  * Update gem description
3
7
 
data/README.rdoc CHANGED
@@ -1,14 +1,29 @@
1
1
  = Voteable Mongo
2
2
 
3
- voteable_mongo allows you to make your Mongoid::Document or MongoMapper::Document objects voteable (up or down) and tabulate votes count and votes point for you. For instance, in a forum, a user can vote up (or down) on a post or a comment.
3
+ voteable_mongo allows you to make your Mongoid::Document or MongoMapper::Document objects voteable and tabulate votes count and votes point for you. For instance, in a forum, a user can vote up (or down) on a post or a comment. It's optimized for speed by using only ONE database request per collection to validate, update, and retrieve updated data.
4
4
 
5
- voteable_mongo is built for speed. It uses only one database request per collection to validate data, update data, and get updated data. Initial idea is based on http://cookbook.mongodb.org/patterns/votes
5
+ Initial idea based on http://cookbook.mongodb.org/patterns/votes
6
6
 
7
7
  Sample app at https://github.com/vinova/simple_qa
8
8
 
9
- Benchmarks at https://github.com/vinova/voteable_benchmarks
9
+ Wonder how fast voteable_mongo is compare to other SQL & MongoDB solutions?
10
+ Visit benchmarks at https://github.com/vinova/voteable_benchmarks
10
11
 
11
- === Sites using voteable_mongo
12
+ == Why voteable_mongo?
13
+
14
+ There are various solution for up / down voting problem (see list below)
15
+ * https://github.com/medihack/make_voteable
16
+ * https://github.com/brady8/thumbs_up
17
+ * https://github.com/icaruswings/mm-voteable
18
+ * https://github.com/jcoene/mongoid_voteable
19
+
20
+ Most of them using additional votes table (SQL) or votes collection (MongoDB) to store votes and do data tabulation on that votes table or votes collection.
21
+
22
+ voteable_mongo is different. It can do much more with a single request to MongoDB database. It takes advantage of document-oriented database to store all related votes data inside voteable document do you don't have to maintain additional collection. When do vote up, vote down, revote, unvote, voteable_mongo validates vote data, updates voteable document data and retrieves updated data using only ONE database request (thanks to atomic find_and_modify operation). When voteable document is loaded, all votes data related to it also be loaded, no more additional database requests to see how many votes this document got?, who give up votes? who give down vote? total vote points, votes count ...
23
+
24
+ So use voteable_mongo and save your database requests for other other tasks.
25
+
26
+ == Sites using voteable_mongo
12
27
  * http://www.amorveneris.com
13
28
  * http://zheye.org (https://github.com/huacnlee/quora)
14
29
 
@@ -108,7 +123,7 @@ Is equivalent to
108
123
  @post.vote(:voter => @user, :value => :up)
109
124
 
110
125
  In case you don't need to init voter and / or votee objects you can
111
- @user.vote(:votee_type => 'Post', :votee_id => post_id, :value => :down)
126
+ @user.vote(:votee_class => Post, :votee_id => post_id, :value => :down)
112
127
  @post.vote(:voter_id => user_id, :value => :up)
113
128
  Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up)
114
129
 
@@ -132,14 +147,14 @@ Note: vote function always return updated votee object
132
147
  === Get vote_value
133
148
 
134
149
  @user.vote_value(@post)
135
- @user.vote_value(:class_type => 'Post', :votee_id => post_id)
150
+ @user.vote_value(:votee_class => Post, :votee_id => post_id)
136
151
  @post.vote_value(@user)
137
152
  @post.vote_value(user_id)
138
153
 
139
154
  === Check if voted?
140
155
 
141
156
  @user.voted?(@post)
142
- @user.voted?(:class_type => 'Post', :votee_id => post_id)
157
+ @user.voted?(:votee_class => Post, :votee_id => post_id)
143
158
  @post.voted_by?(@user)
144
159
  @post.voted_by?(user_id)
145
160
 
@@ -180,16 +195,16 @@ Rails
180
195
  Ruby
181
196
  Mongo::Voteable::Tasks::init_stats
182
197
 
183
- === Migrate from version < 0.7.0
198
+ === Migrate from voteable_mongoid version < 0.7.0
184
199
  Rails
185
200
  rake mongo:voteable:migrate_old_votes
186
201
  Ruby
187
202
  Mongo::Voteable::Tasks.migrate_old_votes
188
203
 
189
204
  == Credits
190
- * Alex Nguyen (alex@vinova.sg) - Author
191
- * Stefan Nguyen (stefan@vinova.sg) - Unvoting
205
+ * Alex Nguyen - Author
206
+ * https://github.com/vinova/voteable_mongo/contributors
192
207
 
193
- Copyright (c) 2010-2011 Vinova Pte Ltd (http://vinova.sg)
208
+ Copyright (c) 2010-2011 Vinova Pte Ltd
194
209
 
195
210
  Licensed under the MIT license.
data/TODO CHANGED
@@ -1,3 +1,11 @@
1
+ * Add :foreign_key => ... option to update parents' votes
2
+ - Reduce time to check relationships and foreign keys
3
+ - More flexible
4
+ - Need to change votable interface?
5
+ * Support https://github.com/benmyles/mongomatic &
6
+ https://github.com/carlosparamio/mongo_odm
7
+ - Don't have scope
8
+ - Don't have relationships
1
9
  * Add options hash validations
2
10
  * Refactor specs
3
11
  * More test cases for Tasks module
@@ -1,5 +1,3 @@
1
- require 'mongoid'
2
-
3
1
  require 'voteable_mongo/voteable'
4
2
  require 'voteable_mongo/voter'
5
3
  require 'voteable_mongo/tasks'
@@ -4,7 +4,9 @@ module Rails #:nodoc:
4
4
 
5
5
  initializer "preload all application models" do |app|
6
6
  config.to_prepare do
7
- ::Rails::Mongoid.load_models(app)
7
+ if defined?(Mongoid)
8
+ ::Rails::Mongoid.load_models(app)
9
+ end
8
10
  end
9
11
  end
10
12
 
@@ -145,7 +145,7 @@ module Mongo
145
145
  parent_class.collection.update(
146
146
  { '_id' => { '$in' => parent_ids } },
147
147
  { '$inc' => inc_options },
148
- { :safe => true }
148
+ { :safe => true, :multi => true }
149
149
  )
150
150
  end
151
151
  end
@@ -1,3 +1,3 @@
1
1
  module VoteableMongo
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'
3
3
  end
@@ -23,7 +23,7 @@ module Mongo
23
23
  votee_class = votee.class
24
24
  votee_id = votee.id
25
25
  else
26
- votee_class = options[:votee_type].classify.constantize
26
+ votee_class = options[:votee_class]
27
27
  votee_id = options[:votee_id]
28
28
  end
29
29
  end
@@ -39,9 +39,7 @@ module Mongo
39
39
  votee = unless options.is_a?(Hash)
40
40
  options
41
41
  else
42
- options[:votee] || options[:votee_type].classify.constantize.where(
43
- :_id => options[:votee_id]
44
- ).first
42
+ options[:votee] || options[:votee_class].find(options[:votee_id])
45
43
  end
46
44
  votee.vote_value(_id)
47
45
  end
@@ -74,7 +72,7 @@ module Mongo
74
72
  options[:votee_id] = votee.id
75
73
  votee_class = votee.class
76
74
  else
77
- votee_class = options[:votee_type].classify.constantize
75
+ votee_class = options[:votee_class]
78
76
  end
79
77
 
80
78
  if options[:value].nil?
@@ -87,7 +85,7 @@ module Mongo
87
85
  options[:voter] = self
88
86
  options[:voter_id] = id
89
87
 
90
- ( votee || votee_class ).vote(options)
88
+ (votee || votee_class).vote(options)
91
89
  end
92
90
  end
93
91
 
@@ -27,13 +27,16 @@ module Mongo
27
27
  new_vote_query_and_update(options)
28
28
  end
29
29
 
30
- # If votee exits or need to update parent
31
- # use Collection#find_and_modify to retrieve updated votes data and parent_ids
32
- doc = voteable_collection.find_and_modify(
33
- :query => query,
34
- :update => update,
35
- :new => true
36
- )
30
+ # http://www.mongodb.org/display/DOCS/findAndModify+Command
31
+ begin
32
+ doc = voteable_collection.find_and_modify(
33
+ :query => query,
34
+ :update => update,
35
+ :new => true
36
+ )
37
+ rescue Mongo::OperationFailure
38
+ doc = nil
39
+ end
37
40
 
38
41
  if doc
39
42
  update_parent_votes(doc, options) if options[:voteable][:update_parents]
data/spec/spec_helper.rb CHANGED
@@ -2,8 +2,8 @@ require 'rubygems'
2
2
  require 'bundler'
3
3
  Bundler.setup
4
4
 
5
-
6
- if rand > 0.6
5
+ # TODO: Need better solution
6
+ if rand > 0.5
7
7
  puts 'Mongoid'
8
8
  require 'mongoid'
9
9
  models_folder = File.join(File.dirname(__FILE__), 'mongoid/models')
@@ -33,5 +33,5 @@ Dir[ File.join(models_folder, '*.rb') ].each { |file|
33
33
  require file
34
34
  file_name = File.basename(file).sub('.rb', '')
35
35
  klass = file_name.classify.constantize
36
- # klass.collection.drop
36
+ klass.collection.drop
37
37
  }
@@ -44,6 +44,10 @@ describe Mongo::Voteable do
44
44
  @user2 = User.create!
45
45
  end
46
46
 
47
+ it "vote for unexisting post" do
48
+ @user1.vote(:votee_class => Post, :votee_id => BSON::ObjectId.new, :value => :up).should == false
49
+ end
50
+
47
51
  context "just created" do
48
52
  it 'votes_count, up_votes_count, down_votes_count, votes_point should be zero' do
49
53
  @category1.up_votes_count.should == 0
@@ -35,7 +35,7 @@ describe Mongo::Voter do
35
35
 
36
36
  context 'user1 vote up post1 the first time' do
37
37
  before :all do
38
- @user1.vote(:revote => '', :votee_id => @post1.id, :votee_type => 'Post', :value => :up)
38
+ @user1.vote(:revote => '', :votee_id => @post1.id, :votee_class => Post, :value => :up)
39
39
  @post1.reload
40
40
  end
41
41
 
@@ -44,10 +44,10 @@ describe Mongo::Voter do
44
44
  @post1.votes_point.should == 1
45
45
 
46
46
  @user1.vote_value(@post1).should == :up
47
- @user2.vote_value(:votee_type => 'Post', :votee_id => @post1.id).should be_nil
47
+ @user2.vote_value(:votee_class => Post, :votee_id => @post1.id).should be_nil
48
48
 
49
49
  @user1.should be_voted(@post1)
50
- @user2.should_not be_voted(:votee_type => 'Post', :votee_id => @post1.id)
50
+ @user2.should_not be_voted(:votee_class => Post, :votee_id => @post1.id)
51
51
 
52
52
  Post.voted_by(@user1).to_a.should == [ @post1 ]
53
53
  Post.up_voted_by(@user1).to_a.should == [ @post1 ]
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9
9
  s.authors = ['Alex Nguyen']
10
10
  s.email = ['alex@vinova.sg']
11
11
  s.homepage = 'https://github.com/vinova/voteable_mongo'
12
- s.summary = %q{Add Up / Down Voting for Mongoid and MongoMapper}
13
- s.description = %q{Add Up / Down Voting for Mongoid and MongoMapper. Built for speed by using only one database request per collection to validate, update, and retrieve updated data.}
12
+ s.summary = %q{Add up / down voting ability to Mongoid and MongoMapper documents}
13
+ s.description = %q{Add up / down voting ability to Mongoid and MongoMapper documents. Optimized for speed by using only ONE request to MongoDB to validate, update, and retrieve updated data.}
14
14
 
15
15
  s.add_development_dependency 'rspec', '~> 2.5.0'
16
16
  s.add_development_dependency 'mongoid', '~> 2.0.0'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: voteable_mongo
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.9.1
5
+ version: 0.9.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Nguyen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-04 00:00:00 Z
13
+ date: 2011-05-07 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -56,7 +56,7 @@ dependencies:
56
56
  version: 1.3.0
57
57
  type: :development
58
58
  version_requirements: *id004
59
- description: Add Up / Down Voting for Mongoid and MongoMapper. Built for speed by using only one database request per collection to validate, update, and retrieve updated data.
59
+ description: Add up / down voting ability to Mongoid and MongoMapper documents. Optimized for speed by using only ONE request to MongoDB to validate, update, and retrieve updated data.
60
60
  email:
61
61
  - alex@vinova.sg
62
62
  executables: []
@@ -121,10 +121,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  requirements: []
122
122
 
123
123
  rubyforge_project: voteable_mongo
124
- rubygems_version: 1.7.2
124
+ rubygems_version: 1.8.1
125
125
  signing_key:
126
126
  specification_version: 3
127
- summary: Add Up / Down Voting for Mongoid and MongoMapper
127
+ summary: Add up / down voting ability to Mongoid and MongoMapper documents
128
128
  test_files:
129
129
  - spec/mongo_mapper/models/category.rb
130
130
  - spec/mongo_mapper/models/comment.rb