tag unit test

This commit is contained in:
Albert Yi
2010-02-06 23:11:26 -05:00
parent 305f4d4607
commit 341a24e22e
8 changed files with 403 additions and 11 deletions

View File

@@ -1,2 +1,224 @@
class Tag < ActiveRecord::Base
class CategoryMapping
Danbooru.config.reverse_tag_category_mapping.each do |value, category|
define_method(category.downcase) do
value
end
end
def regexp
@regexp ||= Regexp.compile(Danbooru.config.tag_category_mapping.keys.sort_by {|x| -x.size}.join("|"))
end
def value_for(string)
Danbooru.config.tag_category_mapping[string.downcase] || 0
end
end
attr_accessible :category
after_save {|rec| Cache.put("tag_type:#{cache_safe_name}", rec.category_name)}
### Category Methods ###
def self.categories
@category_mapping ||= CategoryMapping.new
end
def category_name
Danbooru.config.reverse_tag_category_mapping[category]
end
### Statistics Methods ###
def self.trending
raise NotImplementedError
end
### Name Methods ###
def self.normalize_name(name)
name.downcase.tr(" ", "_").gsub(/\A[-~*]+/, "")
end
def self.find_or_create_by_name(name, options = {})
name = normalize_name(name)
category = self.class.types.general
if name =~ /\A(#{categories.regexp}):(.+)\Z/
category = self.class.types.value_for($1)
end
tag = find_by_name(name)
if tag
if category > 0 && !(options[:user] && !options[:user].is_privileged? && tag.post_count > 10)
tag.update_attribute(:category, category)
end
tag
else
returning Tag.new do |tag|
tag.name = name
tag.category = category
tag.save
end
end
end
def cache_safe_name
name.gsub(/[^a-zA-Z0-9_-]/, "_")
end
### Update methods ###
def self.mass_edit(start_tags, result_tags, updater_id, updater_ip_addr)
raise NotImplementedError
Post.find_by_tags(start_tags).each do |p|
start = TagAlias.to_aliased(scan_tags(start_tags))
result = TagAlias.to_aliased(scan_tags(result_tags))
tags = (p.cached_tags.scan(/\S+/) - start + result).join(" ")
p.update_attributes(:updater_user_id => updater_id, :updater_ip_addr => updater_ip_addr, :tags => tags)
end
end
### Parse Methods ###
def self.scan_query(query)
query.to_s.downcase.scan(/\S+/).uniq
end
def self.scan_tags(tags)
tags.to_s.downcase.gsub(/[&,;]/, "").scan(/\S+/).uniq
end
def self.parse_cast(object, type)
case type
when :integer
object.to_i
when :float
object.to_f
when :date
begin
object.to_date
rescue Exception
nil
end
when :filesize
object =~ /^(\d+(?:\.\d*)?|\d*\.\d+)([kKmM]?)[bB]?$/
size = $1.to_f
unit = $2
conversion_factor = case unit
when /m/i
1024 * 1024
when /k/i
1024
else
1
end
(size * conversion_factor).to_i
end
end
def self.parse_helper(range, type = :integer)
# "1", "0.5", "5.", ".5":
# (-?(\d+(\.\d*)?|\d*\.\d+))
case range
when /^(.+?)\.\.(.+)/
return [:between, parse_cast($1, type), parse_cast($2, type)]
when /^<=(.+)/, /^\.\.(.+)/
return [:lte, parse_cast($1, type)]
when /^<(.+)/
return [:lt, parse_cast($1, type)]
when /^>=(.+)/, /^(.+)\.\.$/
return [:gte, parse_cast($1, type)]
when /^>(.+)/
return [:gt, parse_cast($1, type)]
else
return [:eq, parse_cast(range, type)]
end
end
def self.parse_query(query, options = {})
q = Hash.new {|h, k| h[k] = []}
scan_query(query).each do |token|
if token =~ /^(sub|md5|-rating|rating|width|height|mpixels|score|filesize|source|id|date|order|change|status|tagcount|gentagcount|arttagcount|chartagcount|copytagcount):(.+)$/
if $1 == "user"
q[:user] = $2
elsif $1 == "fav"
q[:fav] = $2
elsif $1 == "sub"
q[:subscriptions] = $2
elsif $1 == "md5"
q[:md5] = $2
elsif $1 == "-rating"
q[:rating_negated] = $2
elsif $1 == "rating"
q[:rating] = $2
elsif $1 == "id"
q[:post_id] = parse_helper($2)
elsif $1 == "width"
q[:width] = parse_helper($2)
elsif $1 == "height"
q[:height] = parse_helper($2)
elsif $1 == "mpixels"
q[:mpixels] = parse_helper($2, :float)
elsif $1 == "score"
q[:score] = parse_helper($2)
elsif $1 == "filesize"
q[:filesize] = parse_helper($2, :filesize)
elsif $1 == "source"
q[:source] = $2.to_escaped_for_sql_like + "%"
elsif $1 == "date"
q[:date] = parse_helper($2, :date)
elsif $1 == "tagcount"
q[:tag_count] = parse_helper($2)
elsif $1 == "gentagcount"
q[:general_tag_count] = parse_helper($2)
elsif $1 == "arttagcount"
q[:artist_tag_count] = parse_helper($2)
elsif $1 == "chartagcount"
q[:character_tag_count] = parse_helper($2)
elsif $1 == "copytagcount"
q[:copyright_tag_count] = parse_helper($2)
elsif $1 == "order"
q[:order] = $2
elsif $1 == "change"
q[:change] = parse_helper($2)
elsif $1 == "status"
q[:status] = $2
end
elsif token[0] == "-" && token.size > 1
q[:exclude] << token[1..-1]
elsif token[0] == "~" && token.size > 1
q[:include] << token[1..-1]
elsif token.include?("*")
matches = where(["name LIKE ? ESCAPE E'\\\\'", token.to_escaped_for_sql_like]).all(:select => "name", :limit => 25, :order => "post_count DESC").map(&:name)
matches = ["~no_matches~"] if matches.empty?
q[:include] += matches
else
q[:related] << token
end
end
q[:exclude] = TagAlias.to_aliased(q[:exclude], :strip_prefix => true) if q.has_key?(:exclude)
q[:include] = TagAlias.to_aliased(q[:include], :strip_prefix => true) if q.has_key?(:include)
q[:related] = TagAlias.to_aliased(q[:related]) if q.has_key?(:related)
return q
end
end

View File

@@ -3,6 +3,8 @@ require 'digest/sha1'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :password_hash, :email, :last_logged_in_at, :last_forum_read_at, :has_mail, :receive_email_notifications, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags
validates_length_of :name, :within => 2..20, :on => :create
validates_format_of :name, :with => /\A[^\s;,]+\Z/, :on => :create, :message => "cannot have whitespace, commas, or semicolons"
validates_uniqueness_of :name, :case_sensitive => false, :on => :create