diff --git a/app/models/favorite.rb b/app/models/favorite.rb index 3cfa23d89..a86a54a8a 100644 --- a/app/models/favorite.rb +++ b/app/models/favorite.rb @@ -1,2 +1,13 @@ -class Favorite < ActiveRecord::Base +class Favorite + def self.table_name_for(user) + "favorites_#{user.id % 10}" + end + + def self.create(user, post) + ActiveRecord::Base.connection.execute("INSERT INTO #{table_name_for(user)} (user_id, post_id) VALUES (#{user.id}, #{post.id})") + end + + def self.destroy(user, post) + ActiveRecord::Base.connection.execute("DELETE FROM #{table_name_for(user)} WHERE user_id = #{user.id} AND post_id = #{post.id}") + end end diff --git a/app/models/pool.rb b/app/models/pool.rb index ab6c64d3d..a0e28650c 100644 --- a/app/models/pool.rb +++ b/app/models/pool.rb @@ -3,6 +3,7 @@ class Pool < ActiveRecord::Base validates_presence_of :name validates_format_of :name, :with => /\A[^\s;,]+\Z/, :on => :create, :message => "cannot have whitespace, commas, or semicolons" belongs_to :creator, :class_name => "User" + has_many :versions, :class_name => "PoolVersion" def self.create_anonymous(creator) pool = Pool.create(:name => "TEMP - #{Time.now.to_f}.#{rand(1_000_000)}", :creator => creator) diff --git a/app/models/pool_version.rb b/app/models/pool_version.rb new file mode 100644 index 000000000..e523af43c --- /dev/null +++ b/app/models/pool_version.rb @@ -0,0 +1,6 @@ +class PoolVersion < ActiveRecord::Base + class Error < Exception ; end + + validates_presence_of :updater_id, :updater_ip_addr + belongs_to :pool +end diff --git a/app/models/post.rb b/app/models/post.rb index 858fad418..75e34e0ff 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -221,11 +221,13 @@ class Post < ActiveRecord::Base def add_favorite(user) self.fav_string += " fav:#{user.name}" self.fav_string.strip! + Favorite.create(user, self) end def remove_favorite(user) self.fav_string.gsub!(/fav:#{user.name}\b\s*/, " ") self.fav_string.strip! + Favorite.destroy(user, self) end end diff --git a/app/models/post_version.rb b/app/models/post_version.rb index aec1dd4e4..165d39c5b 100644 --- a/app/models/post_version.rb +++ b/app/models/post_version.rb @@ -2,4 +2,5 @@ class PostVersion < ActiveRecord::Base class Error < Exception ; end validates_presence_of :updater_id, :updater_ip_addr + belongs_to :post end diff --git a/app/models/user.rb b/app/models/user.rb index 146dd8aa4..0b1c0cbe4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -71,8 +71,30 @@ class User < ActiveRecord::Base end end + module FavoriteMethods + def favorite_posts(options = {}) + favorites_table = Favorite.table_name_for(self) + before_id = options[:before] + before_id_sql_fragment = "AND favorites.id < #{before_id.to_i}" if before_id + limit = options[:limit] || 20 + + sql = <<-EOS + SELECT posts.*, favorites.id AS favorite_id + FROM posts + JOIN #{favorites_table} AS favorites ON favorites.post_id = posts.id + WHERE + favorites.user_id = #{id} + #{before_id_sql_fragment} + ORDER BY favorite_id DESC + LIMIT #{limit.to_i} + EOS + Post.find_by_sql(sql) + end + end + include NameMethods include PasswordMethods extend AuthenticationMethods + include FavoriteMethods end diff --git a/test/unit/favorite_test.rb b/test/unit/favorite_test.rb index 4067023de..6d49259a9 100644 --- a/test/unit/favorite_test.rb +++ b/test/unit/favorite_test.rb @@ -1,8 +1,40 @@ -require 'test_helper' +require File.dirname(__FILE__) + '/../test_helper' class FavoriteTest < ActiveSupport::TestCase - # Replace this with your real tests. - test "the truth" do - assert true + context "A favorite" do + should "know which table it belongs to" do + user1 = Factory.create(:user) + user2 = Factory.create(:user) + p1 = Factory.create(:post) + p2 = Factory.create(:post) + + p1.add_favorite(user1) + p2.add_favorite(user1) + p1.add_favorite(user2) + + favorites = user1.favorite_posts + assert_equal(2, favorites.size) + assert_equal(p2.id, favorites[0].id) + assert_equal(p1.id, favorites[1].id) + + favorites = user2.favorite_posts + assert_equal(1, favorites.size) + assert_equal(p1.id, favorites[0].id) + end + + should "filter before a given id" do + user1 = Factory.create(:user) + p1 = Factory.create(:post) + p2 = Factory.create(:post) + p3 = Factory.create(:post) + p1.add_favorite(user1) + p2.add_favorite(user1) + p3.add_favorite(user1) + favorites = user1.favorite_posts(:limit => 1) + favorites = user1.favorite_posts(:before => favorites.first.favorite_id) + assert_equal(2, favorites.size) + assert_equal(p2.id, favorites[0].id) + assert_equal(p1.id, favorites[1].id) + end end end