add tag subscriptions
This commit is contained in:
81
app/models/tag_subscription.rb
Normal file
81
app/models/tag_subscription.rb
Normal file
@@ -0,0 +1,81 @@
|
||||
class TagSubscription < ActiveRecord::Base
|
||||
belongs_to :owner, :class_name => "User"
|
||||
before_create :initialize_post_ids
|
||||
before_save :normalize_name
|
||||
before_save :limit_tag_count
|
||||
scope :visible, :conditions => "is_visible_on_profile = TRUE"
|
||||
attr_accessible :name, :tag_query, :post_ids, :is_visible_on_profile
|
||||
|
||||
def normalize_name
|
||||
self.name = name.gsub(/\W/, "_")
|
||||
end
|
||||
|
||||
def initialize_post_ids
|
||||
process
|
||||
end
|
||||
|
||||
def tag_query_array
|
||||
Tag.scan_query(tag_query)
|
||||
end
|
||||
|
||||
def limit_tag_count
|
||||
self.tag_query = tag_query_array.slice(0, 20).join(" ")
|
||||
end
|
||||
|
||||
def process
|
||||
post_ids = tag_query_array.inject([]) do |all, tag|
|
||||
all += Post.find_by_tags(tag, :limit => Danbooru.config.tag_subscription_post_limit / 3, :select => "posts.id", :order => "posts.id desc").map(&:id)
|
||||
end
|
||||
self.post_ids = post_ids.sort.reverse.slice(0, Danbooru.config.tag_subscription_post_limit).join(",")
|
||||
end
|
||||
|
||||
def self.find_tags(subscription_name)
|
||||
if subscription_name =~ /^(.+?):(.+)$/
|
||||
user_name = $1
|
||||
sub_group = $2
|
||||
else
|
||||
user_name = subscription_name
|
||||
sub_group = nil
|
||||
end
|
||||
|
||||
user = User.find_by_name(user_name)
|
||||
if user
|
||||
relation = where(["owner_id = ?", user.id])
|
||||
|
||||
if sub_group
|
||||
relation = relation.where(["name ILIKE ? ESCAPE E'\\\\'", sub_group.to_escaped_for_sql_like])
|
||||
end
|
||||
|
||||
relation.map {|x| x.tag_query.split(/ /)}.flatten
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_post_ids(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit)
|
||||
relation = where(["owner_id = ?", user_id])
|
||||
|
||||
if name
|
||||
relation = relation.where(["name ILIKE ? ESCAPE E'\\\\'", name.to_escaped_for_sql_like])
|
||||
end
|
||||
|
||||
relation.map {|x| x.post_ids.split(/,/)}.flatten.uniq.map(&:to_i).sort.reverse.slice(0, limit)
|
||||
end
|
||||
|
||||
def self.find_posts(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit)
|
||||
Post.where(["id in (?)", find_post_ids(user_id, name, limit)]).all(:order => "id DESC", :limit => limit)
|
||||
end
|
||||
|
||||
def self.process_all
|
||||
all.each do |tag_subscription|
|
||||
if $job_task_daemon_active != false && tag_subscription.owner.is_privileged?
|
||||
begin
|
||||
tag_subscription.process
|
||||
tag_subscription.save
|
||||
rescue Exception => x
|
||||
raise if Rails.environment != "production"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
19
db/migrate/20100307073438_create_tag_subscriptions.rb
Normal file
19
db/migrate/20100307073438_create_tag_subscriptions.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
class CreateTagSubscriptions < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :tag_subscriptions do |t|
|
||||
t.column :owner_id, :integer, :null => false
|
||||
t.column :name, :string, :null => false
|
||||
t.column :tag_query, :string, :null => false
|
||||
t.column :post_ids, :text, :null => false
|
||||
t.column :is_visible_on_profile, :boolean, :null => false, :default => true
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :tag_subscriptions, :owner_id
|
||||
add_index :tag_subscriptions, :name
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :tag_subscriptions
|
||||
end
|
||||
end
|
||||
2805
db/test_structure.sql
Normal file
2805
db/test_structure.sql
Normal file
File diff suppressed because it is too large
Load Diff
5
test/factories/tag_subscription.rb
Normal file
5
test/factories/tag_subscription.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
Factory.define(:tag_subscription) do |f|
|
||||
f.owner {|x| x.association(:user)}
|
||||
f.name {Faker::Lorem.words.join(" ")}
|
||||
f.is_visible_on_profile true
|
||||
end
|
||||
11
test/fixtures/tag_subscriptions.yml
vendored
Normal file
11
test/fixtures/tag_subscriptions.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
# This model initially had no columns defined. If you add columns to the
|
||||
# model remove the '{}' from the fixture names and add the columns immediately
|
||||
# below each fixture, per the syntax in the comments below
|
||||
#
|
||||
one: {}
|
||||
# column: value
|
||||
#
|
||||
two: {}
|
||||
# column: value
|
||||
@@ -13,7 +13,7 @@ class RelatedTagCalculatorTest < ActiveSupport::TestCase
|
||||
assert_equal({"bbb" => 3, "ccc" => 2, "ddd" => 1}, calculator.calculate_from_sample("aaa", 10))
|
||||
end
|
||||
|
||||
should "calculate related tags for a tag" do
|
||||
should "calculate typed related tags for a tag" do
|
||||
posts = []
|
||||
posts << Factory.create(:post, :tag_string => "aaa bbb art:ccc copy:ddd")
|
||||
posts << Factory.create(:post, :tag_string => "aaa bbb art:ccc")
|
||||
|
||||
65
test/unit/tag_subscription_test.rb
Normal file
65
test/unit/tag_subscription_test.rb
Normal file
@@ -0,0 +1,65 @@
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
class TagSubscriptionTest < ActiveSupport::TestCase
|
||||
context "A tag subscription" do
|
||||
should "find the union of all posts for each tag in its tag query" do
|
||||
posts = []
|
||||
user = Factory.create(:user)
|
||||
posts << Factory.create(:post, :tag_string => "aaa")
|
||||
posts << Factory.create(:post, :tag_string => "bbb")
|
||||
posts << Factory.create(:post, :tag_string => "ccc")
|
||||
posts << Factory.create(:post, :tag_string => "ddd")
|
||||
sub_1 = Factory.create(:tag_subscription, :tag_query => "aaa bbb", :owner => user, :name => "zzz")
|
||||
sub_2 = Factory.create(:tag_subscription, :tag_query => "ccc", :owner => user, :name => "yyy")
|
||||
assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id))
|
||||
assert_equal([posts[2].id, posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id))
|
||||
end
|
||||
|
||||
should "cache its tag query results" do
|
||||
posts = []
|
||||
user = Factory.create(:user)
|
||||
posts << Factory.create(:post, :tag_string => "aaa")
|
||||
posts << Factory.create(:post, :tag_string => "bbb")
|
||||
posts << Factory.create(:post, :tag_string => "ccc")
|
||||
sub = Factory.create(:tag_subscription, :tag_query => "aaa bbb", :owner => user, :name => "zzz")
|
||||
assert_equal("#{posts[1].id},#{posts[0].id}", sub.post_ids)
|
||||
end
|
||||
|
||||
should "find posts based on its cached post ids" do
|
||||
user = Factory.create(:user)
|
||||
subs = []
|
||||
subs << Factory.create(:tag_subscription, :tag_query => "aaa", :owner => user, :name => "zzz")
|
||||
subs << Factory.create(:tag_subscription, :tag_query => "bbb", :owner => user, :name => "yyy")
|
||||
assert_equal([], TagSubscription.find_posts(user.id))
|
||||
assert_equal([], TagSubscription.find_posts(user.id, "zzz"))
|
||||
assert_equal([], TagSubscription.find_posts(user.id, "yyy"))
|
||||
posts = []
|
||||
posts << Factory.create(:post, :tag_string => "aaa")
|
||||
posts << Factory.create(:post, :tag_string => "bbb")
|
||||
posts << Factory.create(:post, :tag_string => "ccc")
|
||||
subs.each {|x| x.process; x.save}
|
||||
assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id))
|
||||
assert_equal([posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id))
|
||||
assert_equal([posts[1].id], TagSubscription.find_posts(user.id, "yyy").map(&:id))
|
||||
end
|
||||
end
|
||||
|
||||
context "A tag subscription manager" do
|
||||
should "process all active tag subscriptions" do
|
||||
users = []
|
||||
users << Factory.create(:user)
|
||||
users << Factory.create(:user)
|
||||
posts = []
|
||||
posts << Factory.create(:post, :tag_string => "aaa")
|
||||
posts << Factory.create(:post, :tag_string => "bbb")
|
||||
posts << Factory.create(:post, :tag_string => "ccc")
|
||||
subscriptions = []
|
||||
subscriptions << Factory.create(:tag_subscription, :tag_query => "aaa", :owner => users[0])
|
||||
subscriptions << Factory.create(:tag_subscription, :tag_query => "bbb", :owner => users[1])
|
||||
TagSubscription.process_all
|
||||
subscriptions.each {|x| x.reload}
|
||||
assert_equal("#{posts[0].id}", subscriptions[0].post_ids)
|
||||
assert_equal("#{posts[1].id}", subscriptions[1].post_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user