voteable_mongo 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.9.0
2
+ * Add MongoMapper support
3
+ * Simplify voting algorithm
4
+ * vote / revote / unvote always return voteable object (votee)
5
+ * Tasks module bug fixes
6
+
1
7
  == 0.8.1
2
8
  * Fix gem release bug
3
9
 
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = Voteable Mongo
2
2
 
3
- voteable_mongo allows you to make your Mongoid::Document (mongo_mapper support coming soon) 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 (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.
4
4
 
5
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
6
6
 
@@ -27,6 +27,7 @@ After that, remember to run "bundle install"
27
27
 
28
28
  === Make Post and Comment voteable, User become the voter
29
29
 
30
+ == Mongoid
30
31
  post.rb
31
32
 
32
33
  class Post
@@ -62,6 +63,42 @@ user.rb
62
63
  include Mongo::Voter
63
64
  end
64
65
 
66
+
67
+ == MongoMapper
68
+ post.rb
69
+
70
+ class Post
71
+ include MongoMapper::Document
72
+ include Mongo::Voteable
73
+
74
+ # set points for each vote
75
+ voteable self, :up => +1, :down => -1
76
+
77
+ many :comments
78
+ end
79
+
80
+ comment.rb
81
+
82
+ require 'post'
83
+
84
+ class Comment
85
+ include MongoMapper::Document
86
+ include Mongo::Voteable
87
+
88
+ belongs_to :post
89
+
90
+ voteable self, :up => +1, :down => -3
91
+ voteable Post, :up => +2, :down => -1
92
+ end
93
+
94
+ user.rb
95
+
96
+ class User
97
+ include MongoMapper::Document
98
+ include Mongo::Voter
99
+ end
100
+
101
+
65
102
  === Make a vote
66
103
 
67
104
  @user.vote(@post, :up)
@@ -89,9 +126,8 @@ Re-vote
89
126
 
90
127
  Un-vote
91
128
  Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :unvote => true)
92
-
93
- In-case you need updated voteable object, add :return_votee => true
94
- votee = Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :return_votee => true)
129
+
130
+ Note: vote function always return updated votee object
95
131
 
96
132
  === Get vote_value
97
133
 
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- require "rspec"
5
- require "rspec/core/rake_task"
4
+ require 'rspec'
5
+ require 'rspec/core/rake_task'
6
6
  Rspec::Core::RakeTask.new(:spec) do |spec|
7
- spec.pattern = "spec/**/*_spec.rb"
7
+ spec.pattern = 'spec/**/*_spec.rb'
8
8
  end
9
9
 
10
- task :default => ["spec"]
10
+ task :default => ['spec']
data/TODO CHANGED
@@ -1,3 +1,8 @@
1
+ * Use mongo_ruby_driver as much as possible
2
+ * Move mongoid dependency to a separate module
3
+ * Learn from other gems how they manage and support multiple adaptors
4
+ - https://github.com/pluginaweek/state_machine/tree/master/lib/state_machine/integrations
5
+ - https://github.com/ianwhite/orm_adapter
1
6
  * Add support for mongo_mapper
2
7
  * Add options hash validations
3
8
  * Refactor specs
@@ -1,10 +1,9 @@
1
1
  require 'mongoid'
2
+
2
3
  require 'voteable_mongo/voteable'
3
4
  require 'voteable_mongo/voter'
5
+ require 'voteable_mongo/tasks'
4
6
 
5
- require 'voteable_mongo/voteable/tasks'
6
-
7
- # Add railtie
8
7
  if defined?(Rails)
9
8
  require 'voteable_mongo/railtie'
10
9
  end
@@ -0,0 +1,28 @@
1
+ module Mongo
2
+ module Voteable
3
+ module Integrations
4
+ module MongoMapper
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ key :votes, Hash, :default => DEFAULT_VOTES
9
+
10
+ class << self
11
+ alias_method :voteable_index, :ensure_index
12
+ alias_method :voteable_collection, :collection
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def voteable_relation(class_name)
18
+ associations.find{ |x, r| r.class_name == class_name }.try(:last)
19
+ end
20
+
21
+ def voteable_foreign_key(metadata)
22
+ (metadata.options[:in] || "#{metadata.name}_id").to_s
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module Mongo
2
+ module Voteable
3
+ module Integrations
4
+ module Mongoid
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ field :votes, :type => Hash, :default => DEFAULT_VOTES
9
+
10
+ class << self
11
+ alias_method :voteable_index, :index
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ def voteable_relation(class_name)
17
+ relations.find{ |x, r| r.class_name == class_name }.try(:last)
18
+ end
19
+
20
+ def voteable_collection
21
+ collection.master.collection
22
+ end
23
+
24
+ def voteable_foreign_key(metadata)
25
+ metadata.foreign_key.to_s
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -10,7 +10,7 @@ module Mongo
10
10
  klass_voteable = voteable[class_name]
11
11
  puts "Init stats for #{class_name}" if log
12
12
  klass.collection.update({:votes => nil}, {
13
- '$set' => { :votes => Votes::DEFAULT_ATTRIBUTES }
13
+ '$set' => { :votes => DEFAULT_VOTES }
14
14
  }, {
15
15
  :safe => true,
16
16
  :multi => true
@@ -68,12 +68,6 @@ module Mongo
68
68
  'votes_count' => true,
69
69
  'votes_point' => true,
70
70
  'voteable' => true
71
- # 'votes.u' => true,
72
- # 'votes.d' => true,
73
- # 'votes.uc' => true,
74
- # 'votes.dc' => true,
75
- # 'votes.c' => true,
76
- # 'votes.p' => true
77
71
  }
78
72
  }, { :safe => true })
79
73
  end
@@ -95,12 +89,15 @@ module Mongo
95
89
  def self.remake_stats_for(doc, voteable)
96
90
  up_count = doc.up_voter_ids.length
97
91
  down_count = doc.down_voter_ids.length
98
-
99
92
  doc.update_attributes(
100
- 'votes.up_count' => up_count,
101
- 'votes.down_count' => down_count,
102
- 'votes.count' => up_count + down_count,
103
- 'votes.point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
93
+ 'votes' => {
94
+ 'up' => doc.up_voter_ids,
95
+ 'down' => doc.down_voter_ids,
96
+ 'up_count' => up_count,
97
+ 'down_count' => down_count,
98
+ 'count' => up_count + down_count,
99
+ 'point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
100
+ }
104
101
  )
105
102
  end
106
103
 
@@ -109,10 +106,10 @@ module Mongo
109
106
  VOTEABLE.each do |class_name, voteable|
110
107
  klass = class_name.constantize
111
108
  voteable.each do |parent_class_name, parent_voteable|
112
- relation_metadata = klass.relations[parent_class_name.underscore]
113
- if relation_metadata
109
+ metadata = klass.voteable_relation(parent_class_name)
110
+ if metadata
114
111
  parent_class = parent_class_name.constantize
115
- foreign_key = relation_metadata.foreign_key
112
+ foreign_key = klass.voteable_foreign_key(metadata)
116
113
  puts "Updating stats for #{class_name} > #{parent_class_name}" if log
117
114
  klass.all.each{ |doc|
118
115
  update_parent_stats_for(doc, parent_class, foreign_key, parent_voteable)
@@ -142,9 +139,11 @@ module Mongo
142
139
  'votes.down_count' => down_count
143
140
  )
144
141
  end
145
-
142
+
143
+ parent_ids = parent_id.is_a?(Array) ? parent_id : [ parent_id ]
144
+
146
145
  parent_class.collection.update(
147
- { '_id' => parent_id },
146
+ { '_id' => { '$in' => parent_ids } },
148
147
  { '$inc' => inc_options },
149
148
  { :safe => true }
150
149
  )
@@ -1,3 +1,3 @@
1
1
  module VoteableMongo
2
- VERSION = '0.8.1'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -1,36 +1,45 @@
1
- require 'voteable_mongo/voteable/votes'
2
- require 'voteable_mongo/voteable/voting'
1
+ require 'voteable_mongo/voting'
2
+ require 'voteable_mongo/integrations/mongoid'
3
+ require 'voteable_mongo/integrations/mongo_mapper'
3
4
 
4
5
  module Mongo
5
6
  module Voteable
6
7
  extend ActiveSupport::Concern
7
8
 
9
+ DEFAULT_VOTES = {
10
+ 'up' => [],
11
+ 'down' => [],
12
+ 'up_count' => 0,
13
+ 'down_count' => 0,
14
+ 'count' => 0,
15
+ 'point' => 0
16
+ }
17
+
8
18
  included do
9
19
  include ::Mongo::Voteable::Voting
10
-
11
- field :votes, :type => Votes
12
20
 
13
- before_create do
14
- # Init votes so that counters and point have numeric values (0)
15
- self.votes = Votes::DEFAULT_ATTRIBUTES
21
+ if defined?(Mongoid) && defined?(field)
22
+ include ::Mongo::Voteable::Integrations::Mongoid
23
+ elsif defined?(MongoMapper)
24
+ include ::Mongo::Voteable::Integrations::MongoMapper
16
25
  end
17
26
 
18
27
  scope :voted_by, lambda { |voter|
19
- voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter.id
20
- any_of({ 'votes.up' => voter_id }, { 'votes.down' => voter_id })
28
+ voter_id = voter.is_a?(::BSON::ObjectId) ? voter : voter.id
29
+ where('$or' => [{ 'votes.up' => voter_id }, { 'votes.down' => voter_id }])
21
30
  }
22
-
31
+
23
32
  scope :up_voted_by, lambda { |voter|
24
- voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter.id
25
- where( 'votes.up' => voter_id )
33
+ voter_id = voter.is_a?(::BSON::ObjectId) ? voter : voter.id
34
+ where('votes.up' => voter_id)
26
35
  }
27
-
36
+
28
37
  scope :down_voted_by, lambda { |voter|
29
- voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter.id
30
- where( 'votes.down' => voter_id )
38
+ voter_id = voter.is_a?(::BSON::ObjectId) ? voter : voter.id
39
+ where('votes.down' => voter_id)
31
40
  }
32
- end # include
33
-
41
+ end
42
+
34
43
  # How many points should be assigned for each up or down vote and other options
35
44
  # This hash should manipulated using voteable method
36
45
  VOTEABLE = {}
@@ -89,24 +98,21 @@ module Mongo
89
98
  validate_and_normalize_vote_options(options)
90
99
  down_voted_by(options[:voter_id]).where(:_id => options[:votee_id]).count == 1
91
100
  end
92
-
93
- private
101
+
94
102
  def create_voteable_indexes
95
- class_eval do
96
- # Compound index _id and voters.up, _id and voters.down
97
- # to make up_voted_by, down_voted_by, voted_by scopes and voting faster
98
- # Should run in background since it introduce new index value and
99
- # while waiting to build, the system can use _id for voting
100
- # http://www.mongodb.org/display/DOCS/Indexing+as+a+Background+Operation
101
- index [['votes.up', 1], ['_id', 1]], :unique => true
102
- index [['votes.down', 1], ['_id', 1]], :unique => true
103
-
104
- # Index counters and point for desc ordering
105
- index [['votes.up_count', -1]]
106
- index [['votes.down_count', -1]]
107
- index [['votes.count', -1]]
108
- index [['votes.point', -1]]
109
- end
103
+ # Compound index _id and voters.up, _id and voters.down
104
+ # to make up_voted_by, down_voted_by, voted_by scopes and voting faster
105
+ # Should run in background since it introduce new index value and
106
+ # while waiting to build, the system can use _id for voting
107
+ # http://www.mongodb.org/display/DOCS/Indexing+as+a+Background+Operation
108
+ voteable_index [['votes.up', 1], ['_id', 1]], :unique => true
109
+ voteable_index [['votes.down', 1], ['_id', 1]], :unique => true
110
+
111
+ # Index counters and point for desc ordering
112
+ voteable_index [['votes.up_count', -1]]
113
+ voteable_index [['votes.down_count', -1]]
114
+ voteable_index [['votes.count', -1]]
115
+ voteable_index [['votes.point', -1]]
110
116
  end
111
117
  end
112
118
 
@@ -3,8 +3,6 @@ module Mongo
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- include ::Mongoid::Document
7
-
8
6
  scope :up_voted_for, lambda { |votee| where(:_id => { '$in' => votee.up_voter_ids }) }
9
7
  scope :down_voted_for, lambda { |votee| where(:_id => { '$in' => votee.down_voter_ids }) }
10
8
  scope :voted_for, lambda { |votee| where(:_id => { '$in' => votee.voter_ids }) }
@@ -41,7 +39,7 @@ module Mongo
41
39
  votee = unless options.is_a?(Hash)
42
40
  options
43
41
  else
44
- options[:votee] || options[:votee_type].classify.constantize.only(:votes).where(
42
+ options[:votee] || options[:votee_type].classify.constantize.where(
45
43
  :_id => options[:votee_id]
46
44
  ).first
47
45
  end
@@ -12,9 +12,8 @@ module Mongo
12
12
  # - :value: :up or :down
13
13
  # - :revote: if true change vote vote from :up to :down and vise versa
14
14
  # - :unvote: if true undo the voting
15
- # - :return_votee: if true always return updated voteable object
16
15
  #
17
- # @return [votes, false, nil]
16
+ # @return [votee, false]
18
17
  def vote(options)
19
18
  validate_and_normalize_vote_options(options)
20
19
  options[:voteable] = VOTEABLE[name][name]
@@ -28,27 +27,21 @@ module Mongo
28
27
  new_vote_query_and_update(options)
29
28
  end
30
29
 
31
- if options[:voteable][:update_parents] || options[:votee] || options[:return_votee]
32
- # If votee exits or need to update parent
33
- # use Collection#find_and_modify to retrieve updated votes data and parent_ids
34
- begin
35
- doc = collection.master.collection.find_and_modify(
36
- :query => query,
37
- :update => update,
38
- :new => true
39
- )
40
- # Update new votes data
41
- options[:votee].write_attribute('votes', doc['votes']) if options[:votee]
42
- update_parent_votes(doc, options) if options[:voteable][:update_parents]
43
- return options[:votee] || new(doc)
44
- rescue Exception => e
45
- # $stderr.puts "Mongo error: #{e.inspect}" # DEBUG
46
- # Don't update parents if operation fail or no matched object found
47
- return false
48
- end
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
+ )
37
+
38
+ if doc
39
+ update_parent_votes(doc, options) if options[:voteable][:update_parents]
40
+ # Update new votes data
41
+ options[:votee].write_attribute('votes', doc['votes']) if options[:votee]
42
+ options[:votee] || new(doc)
49
43
  else
50
- # Just update and don't care the result
51
- collection.update(query, update)
44
+ false
52
45
  end
53
46
  end
54
47
  end
@@ -155,25 +148,15 @@ module Mongo
155
148
 
156
149
  def update_parent_votes(doc, options)
157
150
  VOTEABLE[name].each do |class_name, voteable|
158
- # For other class in VOTEABLE options, if has relationship with current class
159
- relation_metadata = relations.find{ |x, r| r.class_name == class_name }.try(:last)
160
- next unless relation_metadata.present?
161
-
162
- # If cannot find current votee foreign_key value for that class
163
- foreign_key_value = doc[relation_metadata.foreign_key.to_s]
164
- next unless foreign_key_value.present?
165
-
166
- if relation_metadata.relation == ::Mongoid::Relations::Referenced::In
167
- class_name.constantize.collection.update(
168
- { '_id' => foreign_key_value },
169
- { '$inc' => parent_inc_options(voteable, options) }
170
- )
171
- elsif relation_metadata.relation == ::Mongoid::Relations::Referenced::ManyToMany
172
- class_name.constantize.collection.update(
173
- { '_id' => { '$in' => foreign_key_value } },
174
- { '$inc' => parent_inc_options(voteable, options) },
175
- { :multi => true }
176
- )
151
+ if metadata = voteable_relation(class_name)
152
+ if parent_id = doc[voteable_foreign_key(metadata)]
153
+ parent_ids = parent_id.is_a?(Array) ? parent_id : [ parent_id ]
154
+ class_name.constantize.collection.update(
155
+ { '_id' => { '$in' => parent_ids } },
156
+ { '$inc' => parent_inc_options(voteable, options) },
157
+ { :multi => true }
158
+ )
159
+ end
177
160
  end
178
161
  end
179
162
  end
@@ -0,0 +1,11 @@
1
+ class Category
2
+ include MongoMapper::Document
3
+ include Mongo::Voteable
4
+
5
+ key :name, String
6
+
7
+ key :post_ids, Array
8
+ many :posts, :in => :post_ids
9
+
10
+ voteable self, :index => true
11
+ end
@@ -0,0 +1,13 @@
1
+ require File.join(File.dirname(__FILE__), 'post')
2
+
3
+ class Comment
4
+ include MongoMapper::Document
5
+ include Mongo::Voteable
6
+
7
+ key :content, String
8
+
9
+ belongs_to :post
10
+
11
+ voteable self, :up => +1, :down => -3
12
+ voteable Post, :up => +2, :down => -1
13
+ end
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), 'category')
2
+
3
+ class Post
4
+ include MongoMapper::Document
5
+ include Mongo::Voteable
6
+
7
+ key :title, String
8
+ key :content, String
9
+
10
+ key :category_ids, Array
11
+ many :categories, :in => :category_ids
12
+
13
+ many :comments
14
+
15
+ voteable self, :up => +1, :down => -1, :index => true
16
+ voteable Category, :up => +3, :down => -5, :update_counters => false
17
+ end
@@ -0,0 +1,4 @@
1
+ class User
2
+ include MongoMapper::Document
3
+ include Mongo::Voter
4
+ end
File without changes
@@ -1,4 +1,4 @@
1
- require 'post'
1
+ require File.join(File.dirname(__FILE__), 'post')
2
2
 
3
3
  class Comment
4
4
  include Mongoid::Document
@@ -1,3 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), 'category')
2
+
1
3
  class Post
2
4
  include Mongoid::Document
3
5
  include Mongo::Voteable
File without changes
data/spec/spec_helper.rb CHANGED
@@ -3,29 +3,35 @@ require 'bundler'
3
3
  Bundler.setup
4
4
 
5
5
 
6
+ if rand > 0.6
7
+ puts 'Mongoid'
8
+ require 'mongoid'
9
+ models_folder = File.join(File.dirname(__FILE__), 'mongoid/models')
10
+ Mongoid.configure do |config|
11
+ name = 'voteable_mongo_test'
12
+ host = 'localhost'
13
+ config.master = Mongo::Connection.new.db(name)
14
+ config.autocreate_indexes = true
15
+ end
16
+ else
17
+ puts 'MongoMapper'
18
+ require 'mongo_mapper'
19
+ models_folder = File.join(File.dirname(__FILE__), 'mongo_mapper/models')
20
+ MongoMapper.database = 'voteable_mongo_test'
21
+ end
22
+
23
+
6
24
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
25
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
26
 
9
- MODELS = File.join(File.dirname(__FILE__), "models")
10
- $LOAD_PATH.unshift(MODELS)
11
27
 
12
-
13
- require 'mongoid'
14
28
  require 'voteable_mongo'
15
29
  require 'rspec'
16
30
  require 'rspec/autorun'
17
31
 
18
-
19
- Mongoid.configure do |config|
20
- name = "voteable_mongo_test"
21
- host = "localhost"
22
- config.master = Mongo::Connection.new.db(name)
23
- end
24
-
25
-
26
- Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
27
-
28
- User.collection.drop
29
- Post.collection.drop
30
- Comment.collection.drop
31
- Category.collection.drop
32
+ Dir[ File.join(models_folder, '*.rb') ].each { |file|
33
+ require file
34
+ file_name = File.basename(file).sub('.rb', '')
35
+ klass = file_name.classify.constantize
36
+ # klass.collection.drop
37
+ }
@@ -8,8 +8,8 @@ describe Mongo::Voteable::Tasks do
8
8
  end
9
9
 
10
10
  it 'after create votes has default value' do
11
- @post1.votes.should == Mongo::Voteable::Votes::DEFAULT_ATTRIBUTES
12
- @post2.votes.should == Mongo::Voteable::Votes::DEFAULT_ATTRIBUTES
11
+ @post1.votes.should == ::Mongo::Voteable::DEFAULT_VOTES
12
+ @post2.votes.should == ::Mongo::Voteable::DEFAULT_VOTES
13
13
  end
14
14
 
15
15
  it 'reset votes data' do
@@ -21,13 +21,14 @@ describe Mongo::Voteable::Tasks do
21
21
  end
22
22
 
23
23
  it 'init_stats recover votes default value' do
24
- Mongo::Voteable::Tasks.init_stats
24
+ ::Mongo::Voteable::Tasks.init_stats
25
+ ::Mongo::Voteable::Tasks.migrate_old_votes
25
26
 
26
27
  @post1.reload
27
28
  @post2.reload
28
-
29
- @post1.votes.should == Mongo::Voteable::Votes::DEFAULT_ATTRIBUTES
30
- @post2.votes.should == Mongo::Voteable::Votes::DEFAULT_ATTRIBUTES
29
+
30
+ @post1.votes.should == ::Mongo::Voteable::DEFAULT_VOTES
31
+ @post2.votes.should == ::Mongo::Voteable::DEFAULT_VOTES
31
32
  end
32
33
  end
33
34
  end
@@ -6,18 +6,20 @@ describe Mongo::Voteable do
6
6
  before do
7
7
  Post.collection.drop_indexes
8
8
  Category.collection.drop_indexes
9
+
10
+ Post.create_voteable_indexes
11
+ Category.create_voteable_indexes
9
12
  end
10
-
13
+
11
14
  it 'defines indexes' do
12
15
  [Post, Category].each do |klass|
13
- klass.create_indexes
14
16
  [ 'votes.up_1__id_1',
15
17
  'votes.down_1__id_1'
16
18
  ].each { |index_key|
17
19
  klass.collection.index_information.should have_key index_key
18
20
  klass.collection.index_information[index_key]['unique'].should be_true
19
21
  }
20
-
22
+
21
23
  [ 'votes.count_-1',
22
24
  'votes.up_count_-1',
23
25
  'votes.down_count_-1',
@@ -33,12 +35,9 @@ describe Mongo::Voteable do
33
35
  @category1 = Category.create!(:name => 'xyz')
34
36
  @category2 = Category.create!(:name => 'abc')
35
37
 
36
- @post1 = Post.create!
38
+ @post1 = Post.create!(:category_ids => [@category1.id, @category2.id])
37
39
  @post2 = Post.create!
38
-
39
- @post1.categories << @category1
40
- @category2.posts << @post1
41
-
40
+
42
41
  @comment = @post2.comments.create!
43
42
 
44
43
  @user1 = User.create!
@@ -123,7 +122,7 @@ describe Mongo::Voteable do
123
122
 
124
123
  context 'user1 vote up post1 the first time' do
125
124
  before :all do
126
- @post = @post1.vote(:voter_id => @user1.id, :value => :up, :return_votee => true)
125
+ @post = @post1.vote(:voter_id => @user1.id, :value => :up)
127
126
  end
128
127
 
129
128
  it 'validates return post' do
@@ -151,8 +150,8 @@ describe Mongo::Voteable do
151
150
  @post1.vote_value(@user2.id).should be_nil
152
151
  @post1.should_not be_voted_by(@user2.id)
153
152
 
154
- @post1.up_voters(User).should == [ @user1 ]
155
- @post1.voters(User).should == [ @user1 ]
153
+ @post1.up_voters(User).to_a.should == [ @user1 ]
154
+ @post1.voters(User).to_a.should == [ @user1 ]
156
155
  @post1.down_voters(User).should be_empty
157
156
 
158
157
  Post.voted_by(@user1).to_a.should == [ @post1 ]
@@ -206,9 +205,9 @@ describe Mongo::Voteable do
206
205
  end
207
206
 
208
207
  it 'post1 get voters' do
209
- @post1.up_voters(User).should == [ @user1 ]
210
- @post1.down_voters(User).should == [ @user2 ]
211
- @post1.voters(User).should == [ @user1, @user2 ]
208
+ @post1.up_voters(User).to_a.should == [ @user1 ]
209
+ @post1.down_voters(User).to_a.should == [ @user2 ]
210
+ @post1.voters(User).to_a.should == [ @user1, @user2 ]
212
211
  end
213
212
 
214
213
  it 'posts voted_by user1, user2 is post1 only' do
@@ -286,7 +285,9 @@ describe Mongo::Voteable do
286
285
  @post2.vote_value(@user1.id).should == :up
287
286
  @post2.vote_value(@user2.id).should be_nil
288
287
 
289
- Post.voted_by(@user1).sort.should == [ @post1, @post2 ].sort
288
+ Post.voted_by(@user1).size.should == 2
289
+ Post.voted_by(@user1).should be_include @post1
290
+ Post.voted_by(@user1).should be_include @post2
290
291
  end
291
292
  end
292
293
 
@@ -54,9 +54,9 @@ describe Mongo::Voter do
54
54
  Post.down_voted_by(@user1).to_a.should be_empty
55
55
  Post.voted_by(@user2).to_a.should be_empty
56
56
 
57
- User.up_voted_for(@post1).should == [ @user1 ]
58
- User.down_voted_for(@post1).should be_empty
59
- User.voted_for(@post1).should == [ @user1 ]
57
+ User.up_voted_for(@post1).to_a.should == [ @user1 ]
58
+ User.down_voted_for(@post1).to_a.should be_empty
59
+ User.voted_for(@post1).to_a.should == [ @user1 ]
60
60
  end
61
61
 
62
62
  it 'user1 vote post1 has no effect' do
@@ -88,9 +88,9 @@ describe Mongo::Voter do
88
88
  Post.up_voted_by(@user2).to_a.should be_empty
89
89
  Post.down_voted_by(@user2).to_a.should == [ @post1 ]
90
90
 
91
- User.up_voted_for(@post1).should == [ @user1 ]
92
- User.down_voted_for(@post1).should == [ @user2 ]
93
- User.voted_for(@post1).should == [ @user1, @user2 ]
91
+ User.up_voted_for(@post1).to_a.should == [ @user1 ]
92
+ User.down_voted_for(@post1).to_a.should == [ @user2 ]
93
+ User.voted_for(@post1).to_a.should == [ @user1, @user2 ]
94
94
  end
95
95
  end
96
96
 
@@ -142,7 +142,9 @@ describe Mongo::Voter do
142
142
  @user1.vote_value(@post2).should == :up
143
143
  @user2.vote_value(@post2).should be_nil
144
144
 
145
- Post.voted_by(@user1).sort.should == [ @post1, @post2 ].sort
145
+ Post.voted_by(@user1).size.should == 2
146
+ Post.voted_by(@user1).should be_include @post1
147
+ Post.voted_by(@user1).should be_include @post2
146
148
  end
147
149
  end
148
150
  end
@@ -10,12 +10,12 @@ Gem::Specification.new do |s|
10
10
  s.email = ['alex@vinova.sg']
11
11
  s.homepage = 'https://github.com/vinova/voteable_mongo'
12
12
  s.summary = %q{Add Up / Down Voting for Mongoid and MongoMapper}
13
- s.description = %q{Up / Down Voting for Mongoid (MongoMapper support coming soon). Built for speed by using only one database request per collection to validate data, update data, and get updated data.}
13
+ s.description = %q{Built for speed by using only one database request per collection to validate, update, and retrieve updated data}
14
14
 
15
- s.add_development_dependency 'rspec'
15
+ s.add_development_dependency 'rspec', '~> 2.5.0'
16
16
  s.add_development_dependency 'mongoid', '~> 2.0.0'
17
- s.add_development_dependency 'mongo_mapper'
18
- s.add_development_dependency 'bson_ext'
17
+ s.add_development_dependency 'mongo_mapper', '~> 0.9.0'
18
+ s.add_development_dependency 'bson_ext', '~> 1.3.0'
19
19
 
20
20
  s.rubyforge_project = 'voteable_mongo'
21
21
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: voteable_mongo
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.8.1
5
+ version: 0.9.0
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-03 00:00:00 Z
13
+ date: 2011-05-04 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -18,9 +18,9 @@ dependencies:
18
18
  requirement: &id001 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
- - - ">="
21
+ - - ~>
22
22
  - !ruby/object:Gem::Version
23
- version: "0"
23
+ version: 2.5.0
24
24
  type: :development
25
25
  version_requirements: *id001
26
26
  - !ruby/object:Gem::Dependency
@@ -40,9 +40,9 @@ dependencies:
40
40
  requirement: &id003 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ">="
43
+ - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: "0"
45
+ version: 0.9.0
46
46
  type: :development
47
47
  version_requirements: *id003
48
48
  - !ruby/object:Gem::Dependency
@@ -51,12 +51,12 @@ dependencies:
51
51
  requirement: &id004 !ruby/object:Gem::Requirement
52
52
  none: false
53
53
  requirements:
54
- - - ">="
54
+ - - ~>
55
55
  - !ruby/object:Gem::Version
56
- version: "0"
56
+ version: 1.3.0
57
57
  type: :development
58
58
  version_requirements: *id004
59
- description: Up / Down Voting for Mongoid (MongoMapper support coming soon). Built for speed by using only one database request per collection to validate data, update data, and get updated data.
59
+ description: Built for speed by using only one database request per collection to validate, update, and retrieve updated data
60
60
  email:
61
61
  - alex@vinova.sg
62
62
  executables: []
@@ -75,19 +75,24 @@ files:
75
75
  - Rakefile
76
76
  - TODO
77
77
  - lib/voteable_mongo.rb
78
+ - lib/voteable_mongo/integrations/mongo_mapper.rb
79
+ - lib/voteable_mongo/integrations/mongoid.rb
78
80
  - lib/voteable_mongo/railtie.rb
79
81
  - lib/voteable_mongo/railties/database.rake
82
+ - lib/voteable_mongo/tasks.rb
80
83
  - lib/voteable_mongo/version.rb
81
84
  - lib/voteable_mongo/voteable.rb
82
- - lib/voteable_mongo/voteable/tasks.rb
83
- - lib/voteable_mongo/voteable/votes.rb
84
- - lib/voteable_mongo/voteable/voting.rb
85
85
  - lib/voteable_mongo/voter.rb
86
+ - lib/voteable_mongo/voting.rb
86
87
  - spec/.rspec
87
- - spec/models/category.rb
88
- - spec/models/comment.rb
89
- - spec/models/post.rb
90
- - spec/models/user.rb
88
+ - spec/mongo_mapper/models/category.rb
89
+ - spec/mongo_mapper/models/comment.rb
90
+ - spec/mongo_mapper/models/post.rb
91
+ - spec/mongo_mapper/models/user.rb
92
+ - spec/mongoid/models/category.rb
93
+ - spec/mongoid/models/comment.rb
94
+ - spec/mongoid/models/post.rb
95
+ - spec/mongoid/models/user.rb
91
96
  - spec/spec_helper.rb
92
97
  - spec/voteable_mongo/tasks_spec.rb
93
98
  - spec/voteable_mongo/voteable_spec.rb
@@ -121,10 +126,14 @@ signing_key:
121
126
  specification_version: 3
122
127
  summary: Add Up / Down Voting for Mongoid and MongoMapper
123
128
  test_files:
124
- - spec/models/category.rb
125
- - spec/models/comment.rb
126
- - spec/models/post.rb
127
- - spec/models/user.rb
129
+ - spec/mongo_mapper/models/category.rb
130
+ - spec/mongo_mapper/models/comment.rb
131
+ - spec/mongo_mapper/models/post.rb
132
+ - spec/mongo_mapper/models/user.rb
133
+ - spec/mongoid/models/category.rb
134
+ - spec/mongoid/models/comment.rb
135
+ - spec/mongoid/models/post.rb
136
+ - spec/mongoid/models/user.rb
128
137
  - spec/spec_helper.rb
129
138
  - spec/voteable_mongo/tasks_spec.rb
130
139
  - spec/voteable_mongo/voteable_spec.rb
@@ -1,19 +0,0 @@
1
- module Mongo
2
- module Voteable
3
-
4
- class Votes
5
- include Mongoid::Document
6
-
7
- field :up, :type => Array, :default => []
8
- field :down, :type => Array, :default => []
9
- field :up_count, :type => Integer, :default => 0
10
- field :down_count, :type => Integer, :default => 0
11
- field :count, :type => Integer, :default => 0
12
- field :point, :type => Integer, :default => 0
13
-
14
- DEFAULT_ATTRIBUTES = new.attributes
15
- DEFAULT_ATTRIBUTES.delete('_id')
16
- end
17
-
18
- end
19
- end