Skip to content
Browse files

First class Postgres support.

  • Loading branch information...
1 parent 39b4e71 commit 2f7a0db2e3a9c3483e66c0980cb2254021026f19 @bouchard committed Jul 29, 2012
View
2 Gemfile
@@ -1,2 +1,2 @@
-source 'http://rubygems.org'
+source :rubygems
gemspec
View
6 README.md
@@ -80,7 +80,7 @@ Did the first user vote for the Car with id = 2 already?
u = User.first
u.vote_for(Car.find(2))
u.voted_on?(Car.find(2)) #=> true
-
+
Did the first user vote for or against the Car with id = 2?
u = User.first
@@ -92,6 +92,10 @@ Did the first user vote for or against the Car with id = 2?
You can easily retrieve voteable object collections based on the properties of their votes:
+ @items = Item.tally.limit(10).where('created_at > ?', 2.days.ago).having('COUNT(votes.id) < 10')
+
+Or for MySQL:
+
@items = Item.tally.limit(10).where('created_at > ?', 2.days.ago).having('vote_count < 10')
This will select the Items with less than 10 votes, the votes having been cast within the last two days, with a limit of 10 items. *This tallies all votes, regardless of whether they are +1 (up) or -1 (down).* The #tally method returns an ActiveRecord Relation, so you can chain the normal method calls on to it.
View
12 Rakefile
@@ -24,10 +24,18 @@ end
task :build do
system "gem build thumbs_up.gemspec"
end
-
+
task :release => :build do
system "gem push thumbs_up-#{ThumbsUp::VERSION}.gem"
system "rm thumbs_up-#{ThumbsUp::VERSION}.gem"
end
-task :default => :test
+task :test_both_databases do
+ # Test both MySQL and Postgres.
+ ENV['DB'] = 'mysql'
+ Rake::Task['test'].execute
+ ENV['DB'] = 'postgres'
+ Rake::Task['test'].execute
+end
+
+task :default => :test_both_databases
View
9 lib/acts_as_voteable.rb
@@ -2,6 +2,7 @@ module ThumbsUp
module ActsAsVoteable #:nodoc:
def self.included(base)
+ base.extend ThumbsUp::Base
base.extend ClassMethods
end
@@ -15,7 +16,7 @@ def acts_as_voteable
end
module SingletonMethods
-
+
# Calculate the plusminus for a group of voteables in one database query.
# This returns an Arel relation, so you can add conditions as you like chained on to
# this method call.
@@ -27,10 +28,10 @@ def plusminus_tally(params = {})
t = t.order("plusminus_tally DESC")
t = t.group("#{self.table_name}.id")
t = t.select("#{self.table_name}.*")
- t = t.select("SUM(CASE CAST(#{Vote.table_name}.vote AS UNSIGNED) WHEN 1 THEN 1 WHEN 0 THEN -1 ELSE 0 END) AS plusminus_tally")
+ t = t.select("SUM(CASE WHEN #{Vote.table_name}.vote THEN 1 ELSE -1 END) AS plusminus_tally")
if params[:separate_updown]
- t = t.select("SUM(CASE CAST(#{Vote.table_name}.vote AS UNSIGNED) WHEN 1 THEN 1 WHEN 0 THEN 0 ELSE 0 END) AS up")
- t = t.select("SUM(CASE CAST(#{Vote.table_name}.vote AS UNSIGNED) WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE 0 END) AS down")
+ t = t.select("SUM(CASE WHEN #{Vote.table_name}.vote THEN 1 ELSE 0 END) AS up")
+ t = t.select("SUM(CASE WHEN #{Vote.table_name}.vote THEN 0 ELSE 1 END) AS down")
end
t = t.select("COUNT(#{Vote.table_name}.id) AS vote_count")
end
View
8 lib/generators/thumbs_up/templates/migration.rb
@@ -1,19 +1,19 @@
class ThumbsUpMigration < ActiveRecord::Migration
def self.up
create_table :votes, :force => true do |t|
-
- t.boolean :vote, :default => false
+
+ t.boolean :vote, :default => false, :null => 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]
<% if options[:unique_voting] == true %>
- # Comment out the line below to allow multiple votes per voter on a single entity.
+ # 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
View
9 lib/thumbs_up.rb
@@ -2,6 +2,15 @@
require 'acts_as_voter'
require 'has_karma'
+module ThumbsUp
+ module Base
+ # Check if we're connected to a MySQL database.
+ def mysql?
+ ActiveRecord::Base.connection.adapter_name == 'MySQL'
+ end
+ end
+end
+
ActiveRecord::Base.send(:include, ThumbsUp::ActsAsVoteable)
ActiveRecord::Base.send(:include, ThumbsUp::ActsAsVoter)
ActiveRecord::Base.send(:include, ThumbsUp::Karma)
View
2 lib/thumbs_up/version.rb
@@ -1,3 +1,3 @@
module ThumbsUp
- VERSION = '0.5.7'
+ VERSION = '0.6.0'
end
View
63 test/test_helper.rb
@@ -7,26 +7,47 @@
require 'active_record'
-if ENV['TRAVIS']
- config = {
- :adapter => 'mysql2',
- :database => 'thumbs_up_test',
- :username => 'root'
- }
+if ENV['DB'] == 'mysql'
+ if ENV['TRAVIS']
+ config = {
+ :adapter => 'mysql2',
+ :database => 'thumbs_up_test',
+ :username => 'root'
+ }
+ else
+ config = {
+ :adapter => 'mysql2',
+ :database => 'thumbs_up_test',
+ :username => 'test',
+ :password => 'test',
+ :socket => '/tmp/mysql.sock'
+ }
+ end
+
+ ActiveRecord::Base.establish_connection(config)
+ ActiveRecord::Base.connection.drop_database config[:database] rescue nil
+ ActiveRecord::Base.connection.create_database config[:database]
+ ActiveRecord::Base.establish_connection(config)
else
- config = {
- :adapter => 'mysql2',
- :database => 'thumbs_up_test',
- :username => 'test',
- :password => 'test',
- :socket => '/tmp/mysql.sock'
- }
-end
+ if ENV['TRAVIS']
+ config = {
+ :adapter => 'postgresql',
+ :database => 'thumbs_up_test',
+ :username => 'root'
+ }
+ else
+ config = {
+ :adapter => 'postgresql',
+ :database => 'thumbs_up_test',
+ :username => 'test'
+ }
+ end
-ActiveRecord::Base.establish_connection(config)
-ActiveRecord::Base.connection.drop_database config[:database] rescue nil
-ActiveRecord::Base.connection.create_database config[:database]
-ActiveRecord::Base.establish_connection(config)
+ ActiveRecord::Base.establish_connection(config.merge({ :database => 'postgres' }))
+ ActiveRecord::Base.connection.drop_database config[:database]
+ ActiveRecord::Base.connection.create_database config[:database]
+ ActiveRecord::Base.establish_connection(config)
+end
ActiveRecord::Migration.verbose = false
@@ -41,14 +62,14 @@
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.
+ # 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.integer :user_id
t.string :name
View
25 test/thumbs_up_test.rb
@@ -24,6 +24,8 @@ def test_acts_as_voter_instance_methods
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_equal 1, user_for.votes.where(:voteable_type => 'Item').count
+ assert_equal 0, user_for.votes.where(:voteable_type => 'AnotherItem').count
assert_raises(ArgumentError) do
user_for.voted_which_way?(item, :foo)
end
@@ -226,8 +228,13 @@ def test_plusminus_tally_inclusion
assert_not_nil user.vote_for(item)
- assert (Item.plusminus_tally.having('vote_count > 0').include? item)
- assert (not Item.plusminus_tally.having('vote_count > 0').include? item_not_included)
+ if ActiveRecord::Base.connection.adapter_name == 'MySQL'
+ assert (Item.plusminus_tally.having('vote_count > 0').include? item)
+ assert (not Item.plusminus_tally.having('vote_count > 0').include? item_not_included)
+ else
+ assert (Item.plusminus_tally.having('COUNT(votes.id) > 0').include? item)
+ assert (not Item.plusminus_tally.having('COUNT(votes.id) > 0').include? item_not_included)
+ end
end
def test_plusminus_tally_voting_for
@@ -236,8 +243,9 @@ def test_plusminus_tally_voting_for
assert_not_nil user1.vote_for(item)
- assert_equal 1, Item.plusminus_tally[0].vote_count
- assert_equal 1, Item.plusminus_tally[0].plusminus
+ # https://github.com/rails/rails/issues/1718
+ assert_equal 1, Item.plusminus_tally[0].vote_count.to_i
+ assert_equal 1, Item.plusminus_tally[0].plusminus.to_i
end
def test_plusminus_tally_voting_against
@@ -248,8 +256,9 @@ def test_plusminus_tally_voting_against
assert_not_nil user1.vote_against(item)
assert_not_nil user2.vote_against(item)
- assert_equal 2, Item.plusminus_tally[0].vote_count
- assert_equal -2, Item.plusminus_tally[0].plusminus
+ # https://github.com/rails/rails/issues/1718
+ assert_equal 2, Item.plusminus_tally[0].vote_count.to_i
+ assert_equal -2, Item.plusminus_tally[0].plusminus.to_i
end
def test_plusminus_tally_default_ordering
@@ -268,7 +277,7 @@ def test_plusminus_tally_default_ordering
assert_equal item_for, Item.plusminus_tally[1]
assert_equal item_against, Item.plusminus_tally[2]
end
-
+
def test_plusminus_tally_limit
users = (0..9).map{ |u| User.create(:name => "User #{u}") }
items = (0..9).map{ |u| Item.create(:name => "Item #{u}", :description => "Item #{u}") }
@@ -305,7 +314,7 @@ def test_karma
users = (0..1).map{ |u| User.create(:name => "User #{u}") }
items = (0..1).map{ |u| users[0].items.create(:name => "Item #{u}", :description => "Item #{u}") }
users.each{ |u| items.each { |i| u.vote_for(i) } }
-
+
assert_equal 4, users[0].karma
assert_equal 0, users[1].karma
end
View
1 thumbs_up.gemspec
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('simplecov')
s.add_development_dependency('bundler')
s.add_development_dependency('mysql2')
+ s.add_development_dependency('pg')
s.add_development_dependency('rake')
end

0 comments on commit 2f7a0db

Please sign in to comment.
Something went wrong with that request. Please try again.