jy-acts_as_votable 0.3.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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ nbproject/*
5
+ bin
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in acts_as_votable.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,103 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ acts_as_votable (0.3.0)
5
+ rails (>= 3.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionmailer (3.2.3)
11
+ actionpack (= 3.2.3)
12
+ mail (~> 2.4.4)
13
+ actionpack (3.2.3)
14
+ activemodel (= 3.2.3)
15
+ activesupport (= 3.2.3)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.1)
19
+ rack (~> 1.4.0)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.1.2)
23
+ activemodel (3.2.3)
24
+ activesupport (= 3.2.3)
25
+ builder (~> 3.0.0)
26
+ activerecord (3.2.3)
27
+ activemodel (= 3.2.3)
28
+ activesupport (= 3.2.3)
29
+ arel (~> 3.0.2)
30
+ tzinfo (~> 0.3.29)
31
+ activeresource (3.2.3)
32
+ activemodel (= 3.2.3)
33
+ activesupport (= 3.2.3)
34
+ activesupport (3.2.3)
35
+ i18n (~> 0.6)
36
+ multi_json (~> 1.0)
37
+ arel (3.0.2)
38
+ builder (3.0.0)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.7.0)
41
+ hike (1.2.1)
42
+ i18n (0.6.0)
43
+ journey (1.0.3)
44
+ json (1.6.6)
45
+ mail (2.4.4)
46
+ i18n (>= 0.4.0)
47
+ mime-types (~> 1.16)
48
+ treetop (~> 1.4.8)
49
+ mime-types (1.18)
50
+ multi_json (1.2.0)
51
+ polyglot (0.3.3)
52
+ rack (1.4.1)
53
+ rack-cache (1.2)
54
+ rack (>= 0.4)
55
+ rack-ssl (1.3.2)
56
+ rack
57
+ rack-test (0.6.1)
58
+ rack (>= 1.0)
59
+ rails (3.2.3)
60
+ actionmailer (= 3.2.3)
61
+ actionpack (= 3.2.3)
62
+ activerecord (= 3.2.3)
63
+ activeresource (= 3.2.3)
64
+ activesupport (= 3.2.3)
65
+ bundler (~> 1.0)
66
+ railties (= 3.2.3)
67
+ railties (3.2.3)
68
+ actionpack (= 3.2.3)
69
+ activesupport (= 3.2.3)
70
+ rack-ssl (~> 1.3.2)
71
+ rake (>= 0.8.7)
72
+ rdoc (~> 3.4)
73
+ thor (~> 0.14.6)
74
+ rake (0.9.2.2)
75
+ rdoc (3.12)
76
+ json (~> 1.4)
77
+ rspec (2.9.0)
78
+ rspec-core (~> 2.9.0)
79
+ rspec-expectations (~> 2.9.0)
80
+ rspec-mocks (~> 2.9.0)
81
+ rspec-core (2.9.0)
82
+ rspec-expectations (2.9.1)
83
+ diff-lcs (~> 1.1.3)
84
+ rspec-mocks (2.9.0)
85
+ sprockets (2.1.2)
86
+ hike (~> 1.2)
87
+ rack (~> 1.0)
88
+ tilt (~> 1.1, != 1.3.0)
89
+ sqlite3 (1.3.5)
90
+ thor (0.14.6)
91
+ tilt (1.3.3)
92
+ treetop (1.4.10)
93
+ polyglot
94
+ polyglot (>= 0.3.1)
95
+ tzinfo (0.3.33)
96
+
97
+ PLATFORMS
98
+ ruby
99
+
100
+ DEPENDENCIES
101
+ acts_as_votable!
102
+ rspec
103
+ sqlite3
data/README.markdown ADDED
@@ -0,0 +1,227 @@
1
+ # Acts As Votable (aka Acts As Likeable)
2
+
3
+ Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models.
4
+ The main goals of this gem are:
5
+
6
+ - Allow any model to be voted on, like/dislike, upvote/downvote, etc.
7
+ - Allow any model to vote. In other words, votes do not have to come from a user,
8
+ they can come from any model (such as a Group or Team).
9
+ - Provide an easy to write/read syntax.
10
+
11
+ ## Installation
12
+
13
+ ### Rails 3
14
+
15
+ Just add the following to your Gemfile.
16
+
17
+ gem 'acts_as_votable'
18
+
19
+ And follow that up with a ``bundle install``.
20
+
21
+ ### Database Migrations
22
+
23
+ Acts As Votable uses a votes table to store all voting information. To
24
+ generate and run the migration just use.
25
+
26
+ rails generate acts_as_votable:migration
27
+ rake db:migrate
28
+
29
+ You will get a performance increase by adding in cached columns to your model's
30
+ tables. You will have to do this manually through your own migrations. See the
31
+ caching section of this document for more information.
32
+
33
+ ## Usage
34
+
35
+ ### Votable Models
36
+
37
+ class Post < ActiveRecord::Base
38
+ acts_as_votable
39
+ end
40
+
41
+ @post = Post.new(:name => 'my post!')
42
+ @post.save
43
+
44
+ @post.liked_by @user
45
+ @post.votes.size # => 1
46
+
47
+ ### Like/Dislike Yes/No Up/Down
48
+
49
+ Here are some voting examples. All of these calls are valid and acceptable. The
50
+ more natural calls are the first few examples.
51
+
52
+ @post.liked_by @user1
53
+ @post.downvote_from @user2
54
+ @post.vote :voter => @user3
55
+ @post.vote :voter => @user4, :vote => 'bad'
56
+ @post.vote :voter => @user5, :vote => 'like'
57
+
58
+
59
+ By default all votes are positive, so @user3 has cast a 'good' vote for @post.
60
+
61
+ @user1, @user3, and @user5 all voted in favor of @post.
62
+
63
+ @user2 and @user4 on the other had has voted against @post.
64
+
65
+
66
+ Just about any word works for casting a vote in favor or against post. Up/Down,
67
+ Like/Dislike, Positive/Negative... the list goes on-and-on. Boolean flags ``true`` and
68
+ ``false`` are also applicable.
69
+
70
+ Revisiting the previous example of code.
71
+
72
+ # positive votes
73
+ @post.liked_by @user1
74
+ @post.vote :voter => @user3
75
+ @post.vote :voter => @user5, :vote => 'like'
76
+
77
+ # negative votes
78
+ @post.downvote_from @user2
79
+ @post.vote :voter => @user2, :vote => 'bad'
80
+
81
+ # tally them up!
82
+ @post.votes.size # => 5
83
+ @post.likes.size # => 3
84
+ @post.upvotes.size # => 3
85
+ @post.dislikes.size # => 2
86
+ @post.downvotes.size # => 2
87
+
88
+ Active Record scopes are provided to make life easier.
89
+
90
+ @post.votes.up.by_type(User)
91
+ @post.votes.down
92
+ @user1.votes.up
93
+ @user1.votes.down
94
+ @user1.votes.up.by_type(Post)
95
+
96
+ Once scoping is complete, you can also trigger a get for the
97
+ voter/votable
98
+
99
+ @post.votes.up.by_type(User).voters
100
+ @post.votes.down.by_type(User).voters
101
+
102
+ @user.votes.up.for_type(Post).votables
103
+ @user.votes.up.votables
104
+
105
+ You can also 'unvote' a model to remove a previous vote.
106
+
107
+ @post.liked_by @user1
108
+ @post.unlike_by @user1
109
+
110
+ @post.disliked_by @user1
111
+ @post.undisliked_by @user1
112
+
113
+ Unvoting works for both positive and negative votes.
114
+
115
+ ### The Voter
116
+
117
+ You can have your voters ``acts_as_voter`` to provide some reserve functionality.
118
+
119
+ class User < ActiveRecord::Base
120
+ acts_as_voter
121
+ end
122
+
123
+ @user.likes @article
124
+
125
+ @article.votes.size # => 1
126
+ @article.likes.size # => 1
127
+ @article.dislikes.size # => 0
128
+
129
+ To check if a voter has voted on a model, you can use ``voted_for?``. You can
130
+ check how the voter voted by using ``voted_as_when_voted_for``.
131
+
132
+ @user.likes @comment1
133
+ @user.up_votes @comment2
134
+ # user has not voted on @comment3
135
+
136
+ @user.voted_for? @comment1 # => true
137
+ @user.voted_for? @comment2 # => true
138
+ @user.voted_for? @comment3 # => false
139
+
140
+ @user.voted_as_when_voted_for @comment1 # => true, he liked it
141
+ @user.voted_as_when_voted_for @comment2 # => false, he didnt like it
142
+ @user.voted_as_when_voted_for @comment3 # => nil, he has yet to vote
143
+
144
+ You can also check whether the voter has voted up or down.
145
+
146
+ @user.likes @comment1
147
+ @user.dislikes @comment2
148
+ # user has not voted on @comment3
149
+
150
+ @user.voted_up_on? @comment1 # => true
151
+ @user.voted_down_on? @comment1 # => false
152
+
153
+ @user.voted_down_on? @comment2 # => true
154
+ @user.voted_up_on? @comment2 # => false
155
+
156
+ @user.voted_up_on? @comment3 # => false
157
+ @user.voted_down_on? @comment3 # => false
158
+
159
+ ### Registered Votes
160
+
161
+ Voters can only vote once per model. In this example the 2nd vote does not count
162
+ because @user has already voted for @shoe.
163
+
164
+ @user.likes @shoe
165
+ @user.likes @shoe
166
+
167
+ @shoe.votes # => 1
168
+ @shoe.likes # => 1
169
+
170
+ To check if a vote counted, or registered, use vote_registered? on your model
171
+ after voting. For example:
172
+
173
+ @hat.liked_by @user
174
+ @hat.vote_registered? # => true
175
+
176
+ @hat.liked_by => @user
177
+ @hat.vote_registered? # => false, because @user has already voted this way
178
+
179
+ @hat.disliked_by @user
180
+ @hat.vote_registered? # => true, because user changed their vote
181
+
182
+ @hat.votes.size # => 1
183
+ @hat.positives.size # => 0
184
+ @hat.negatives.size # => 1
185
+
186
+ ## Caching
187
+
188
+ To speed up perform you can add cache columns to your votable model's table. These
189
+ columns will automatically be updated after each vote. For example, if we wanted
190
+ to speed up @post we would use the following migration:
191
+
192
+ class AddCachedVotesToPosts < ActiveRecord::Migration
193
+ def self.up
194
+ add_column :posts, :cached_votes_total, :integer, :default => 0
195
+ add_column :posts, :cached_votes_up, :integer, :default => 0
196
+ add_column :posts, :cached_votes_down, :integer, :default => 0
197
+ add_index :posts, :cached_votes_total
198
+ add_index :posts, :cached_votes_up
199
+ add_index :posts, :cached_votes_down
200
+ end
201
+
202
+ def self.down
203
+ remove_column :posts, :cached_votes_total
204
+ remove_column :posts, :cached_votes_up
205
+ remove_column :posts, :cached_votes_down
206
+ end
207
+ end
208
+
209
+ ## Testing
210
+
211
+ All tests follow the RSpec format and are located in the spec directory
212
+
213
+ ## TODO
214
+
215
+ - Pass in a block of options when creating acts_as. Allow for things
216
+ like disabling the aliasing
217
+
218
+ - Smarter language syntax. Example: ``@user.likes`` will return all of the votables
219
+ that the user likes, while ``@user.likes @model`` will cast a vote for @model by
220
+ @user.
221
+
222
+ - Need to test a model that is votable as well as a voter
223
+
224
+ - The aliased methods are referred to by using the terms 'up/down' and/or
225
+ 'true/false'. Need to come up with guidelines for naming these methods.
226
+
227
+ - Create more aliases. Specifically for counting votes and finding votes.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "acts_as_votable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "jy-acts_as_votable"
7
+ s.version = ActsAsVotable::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ryan"]
10
+ s.email = ["ryanto"]
11
+ s.homepage = "http://rubygems.org/gems/acts_as_votable"
12
+ s.summary = %q{Rails gem to allowing records to be votable}
13
+ s.description = %q{Rails gem to allowing records to be votable}
14
+
15
+ s.rubyforge_project = "acts_as_votable"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+
23
+
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "sqlite3"
26
+
27
+ s.add_dependency "rails", '>=3.0.0'
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'active_record'
2
+ require 'active_support/inflector'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ module ActsAsVotable
7
+
8
+ if defined?(ActiveRecord::Base)
9
+ require 'acts_as_votable/extenders/votable'
10
+ require 'acts_as_votable/extenders/voter'
11
+ require 'acts_as_votable/vote'
12
+ ActiveRecord::Base.extend ActsAsVotable::Extenders::Votable
13
+ ActiveRecord::Base.extend ActsAsVotable::Extenders::Voter
14
+ end
15
+
16
+ end
@@ -0,0 +1,25 @@
1
+ module ActsAsVotable
2
+ module Extenders
3
+
4
+ module Votable
5
+
6
+ def votable?
7
+ false
8
+ end
9
+
10
+ def acts_as_votable
11
+ require 'acts_as_votable/votable'
12
+ include ActsAsVotable::Votable
13
+
14
+ class_eval do
15
+ def self.votable?
16
+ true
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module ActsAsVotable
2
+ module Extenders
3
+
4
+ module Voter
5
+
6
+ def voter?
7
+ false
8
+ end
9
+
10
+ def acts_as_voter(*args)
11
+ require 'acts_as_votable/voter'
12
+ include ActsAsVotable::Voter
13
+
14
+ class_eval do
15
+ def self.voter?
16
+ true
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
24
+ end