Permalink
Browse files

Merge branch 'master' of https://github.com/czarneckid/thumbs_up

  • Loading branch information...
2 parents 605bcd6 + c909fc1 commit 478652a1d396765b7df33d980975dc60d292e3cb Brady Bouchard committed Jan 13, 2011
View
@@ -1,2 +1,3 @@
*.gem
pkg/*
+Gemfile.lock
View
13 Gemfile
@@ -0,0 +1,13 @@
+source :rubygems
+
+gem 'activerecord', '3.0.3'
+
+group :development do
+ gem "bundler", "~> 1.0.0"
+ gem "jeweler", "~> 1.5.2"
+ gem "rcov", ">= 0"
+end
+
+group :test do
+ gem 'sqlite3-ruby', '1.3.2'
+end
View
@@ -65,7 +65,7 @@ Usage
voter.vote(voteable, vote) # Adds either a +1 or -1 vote: vote => true (+1), vote => false (-1)
voter.vote_exclusively_for(voteable) # Removes any previous votes by that particular voter, and votes for.
- voter.vote_exclusively_for(voteable) # Removes any previous votes by that particular voter, and votes against.
+ voter.vote_exclusively_against(voteable) # Removes any previous votes by that particular voter, and votes against.
### Querying votes
@@ -123,6 +123,9 @@ ThumbsUp by default only allows one vote per user. This can be changed by removi
add_index :votes, ["voter_id", "voter_type", "voteable_id", "voteable_type"], :unique => true, :name => "uniq_one_vote_only"
+You can also use `--unique-voting false` when running the generator command:
+
+ rails generate thumbs_up --unique-voting false
Credits
=======
View
@@ -1,19 +1,50 @@
# encoding: UTF-8
require 'rubygems'
-require 'rake'
+require 'bundler'
begin
- require 'jeweler'
- Jeweler::Tasks.new do |gem|
- gem.name = "thumbs_up"
- gem.summary = "Voting for ActiveRecord with multiple vote sources and karma calculation."
- gem.description = "ThumbsUp provides dead-simple voting capabilities to ActiveRecord models with karma calculation, a la stackoverflow.com."
- gem.email = "brady@ldawn.com"
- gem.homepage = "http://github.com/brady8/thumbs_up"
- gem.authors = ["Brady Bouchard", "Peter Jackson", "Cosmin Radoi", "Bence Nagy", "Rob Maddox", "Wojciech Wnętrzak"]
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
- end
- Jeweler::GemcutterTasks.new
-rescue LoadError
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
-end
+ Bundler.setup(:default, :development)
+rescue Bundler::BundlerError => e
+ $stderr.puts e.message
+ $stderr.puts "Run `bundle install` to install missing gems"
+ exit e.status_code
+end
+require 'rake'
+
+require 'jeweler'
+Jeweler::Tasks.new do |gem|
+ gem.name = "thumbs_up"
+ gem.summary = "Voting for ActiveRecord with multiple vote sources and karma calculation."
+ gem.description = "ThumbsUp provides dead-simple voting capabilities to ActiveRecord models with karma calculation, a la stackoverflow.com."
+ gem.email = "brady@ldawn.com"
+ gem.homepage = "http://github.com/brady8/thumbs_up"
+ gem.authors = ["Brady Bouchard", "Peter Jackson", "Cosmin Radoi", "Bence Nagy", "Rob Maddox", "Wojciech Wnętrzak"]
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+end
+Jeweler::RubygemsDotOrgTasks.new
+
+require 'rake/testtask'
+Rake::TestTask.new(:test) do |test|
+ test.libs << 'lib' << 'test'
+ test.pattern = 'test/**/test_*.rb'
+ test.verbose = true
+end
+
+require 'rcov/rcovtask'
+Rcov::RcovTask.new do |test|
+ test.libs << 'test'
+ test.pattern = 'test/**/test_*.rb'
+ test.verbose = true
+end
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
+
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "leaderboard #{version}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+task :default => :test
@@ -12,8 +12,10 @@ def self.up
add_index :votes, [:voter_id, :voter_type]
add_index :votes, [:voteable_id, :voteable_type]
- # Comment out the line below to allow multiple votes per voter on a single entity.
+<% if options[:unique_voting] == true %>
+ # Comment out the line below to allow multiple votes per voter on a single entity.
add_index :votes, [:voter_id, :voter_type, :voteable_id, :voteable_type], :unique => true, :name => 'fk_one_vote_per_user_per_entity'
+<% end %>
end
def self.down
@@ -10,7 +10,8 @@ class Vote < ActiveRecord::Base
attr_accessible :vote, :voter, :voteable
+<% if options[:unique_voting] == true %>
# Comment out the line below to allow multiple votes per user.
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
-
+<% end %>
end
@@ -5,6 +5,8 @@ class ThumbsUpGenerator < Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)
+
+ class_option :unique_voting, :type => :boolean, :default => true, :desc => 'Do you want only one vote allowed per voter? (default: true)'
# Implement the required interface for Rails::Generators::Migration.
def self.next_migration_number(dirname) #:nodoc:
View
@@ -0,0 +1,67 @@
+require 'test/unit'
+
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+
+require 'active_record'
+
+ActiveRecord::Base.establish_connection(
+ :adapter => "sqlite3",
+ :database => ":memory:"
+)
+
+ActiveRecord::Migration.verbose = false
+
+ActiveRecord::Schema.define do
+ create_table :votes, :force => true do |t|
+ t.boolean :vote, :default => false
+ t.references :voteable, :polymorphic => true, :null => false
+ t.references :voter, :polymorphic => true
+ t.timestamps
+ end
+
+ add_index :votes, [:voter_id, :voter_type]
+ add_index :votes, [:voteable_id, :voteable_type]
+
+ # Comment out the line below to allow multiple votes per voter on a single entity.
+ add_index :votes, [:voter_id, :voter_type, :voteable_id, :voteable_type], :unique => true, :name => 'fk_one_vote_per_user_per_entity'
+
+ create_table :users, :force => true do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :items, :force => true do |t|
+ t.string :name
+ t.string :description
+ end
+end
+
+require 'thumbs_up'
+
+class Vote < ActiveRecord::Base
+
+ scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.name]) }
+ scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.name]) }
+ scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
+ scope :descending, order("created_at DESC")
+
+ belongs_to :voteable, :polymorphic => true
+ belongs_to :voter, :polymorphic => true
+
+ attr_accessible :vote, :voter, :voteable
+
+ # Comment out the line below to allow multiple votes per user.
+ validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
+end
+
+class User < ActiveRecord::Base
+ acts_as_voter
+end
+
+class Item < ActiveRecord::Base
+ acts_as_voteable
+end
+
+class Test::Unit::TestCase
+end
View
@@ -0,0 +1,53 @@
+require 'helper'
+
+class TestThumbsUp < Test::Unit::TestCase
+ def setup
+ Vote.delete_all
+ User.delete_all
+ Item.delete_all
+ end
+
+ def test_acts_as_voter_instance_methods
+ user_for = User.create(:name => 'david')
+ user_against = User.create(:name => 'brady')
+ item = Item.create(:name => 'XBOX', :description => 'XBOX console')
+
+ assert_not_nil user_for.vote_for(item)
+ assert_raises(ActiveRecord::RecordInvalid) do
+ user_for.vote_for(item)
+ end
+ assert_equal true, user_for.voted_for?(item)
+ assert_equal false, user_for.voted_against?(item)
+ assert_equal true, user_for.voted_on?(item)
+ assert_equal 1, user_for.vote_count
+ assert_equal 1, user_for.vote_count(:up)
+ assert_equal 0, user_for.vote_count(:down)
+ assert_equal true, user_for.voted_which_way?(item, :up)
+ assert_equal false, user_for.voted_which_way?(item, :down)
+ assert_raises(ArgumentError) do
+ user_for.voted_which_way?(item, :foo)
+ end
+
+ assert_not_nil user_against.vote_against(item)
+ assert_raises(ActiveRecord::RecordInvalid) do
+ user_against.vote_against(item)
+ end
+ assert_equal false, user_against.voted_for?(item)
+ assert_equal true, user_against.voted_against?(item)
+ assert_equal true, user_against.voted_on?(item)
+ assert_equal 1, user_against.vote_count
+ assert_equal 0, user_against.vote_count(:up)
+ assert_equal 1, user_against.vote_count(:down)
+ assert_equal false, user_against.voted_which_way?(item, :up)
+ assert_equal true, user_against.voted_which_way?(item, :down)
+ assert_raises(ArgumentError) do
+ user_against.voted_which_way?(item, :foo)
+ end
+
+ assert_not_nil user_against.vote_exclusively_for(item)
+ assert_equal true, user_against.voted_for?(item)
+
+ assert_not_nil user_for.vote_exclusively_against(item)
+ assert_equal true, user_for.voted_against?(item)
+ end
+end

0 comments on commit 478652a

Please sign in to comment.