@@ -20,7 +20,7 @@ class Tag < ApplicationRecord
2020 HASHTAG_NAME_RE = '([[:word:]_][[:word:]_·]*[[:alpha:]_·][[:word:]_·]*[[:word:]_])|([[:word:]_]*[[:alpha:]][[:word:]_]*)'
2121 HASHTAG_RE = /(?:^|[^\/ \) \w ])#(#{ HASHTAG_NAME_RE } )/i
2222
23- validates :name , presence : true , uniqueness : true , format : { with : /\A (#{ HASHTAG_NAME_RE } )\z /i }
23+ validates :name , presence : true , format : { with : /\A (#{ HASHTAG_NAME_RE } )\z /i }
2424
2525 scope :discoverable , -> { joins ( :account_tag_stat ) . where ( AccountTagStat . arel_table [ :accounts_count ] . gt ( 0 ) ) . where ( account_tag_stats : { hidden : false } ) . order ( Arel . sql ( 'account_tag_stats.accounts_count desc' ) ) }
2626 scope :hidden , -> { where ( account_tag_stats : { hidden : true } ) }
@@ -64,22 +64,48 @@ def history
6464 end
6565
6666 class << self
67+ def find_or_create_by_names ( name_or_names )
68+ Array ( name_or_names ) . map ( &method ( :normalize ) ) . uniq . map do |normalized_name |
69+ tag = matching_name ( normalized_name ) . first || create ( name : normalized_name )
70+
71+ yield tag if block_given?
72+
73+ tag
74+ end
75+ end
76+
6777 def search_for ( term , limit = 5 , offset = 0 )
68- pattern = sanitize_sql_like ( term . strip ) + '%'
78+ pattern = sanitize_sql_like ( normalize ( term . strip ) ) + '%'
6979
70- Tag . where ( 'lower( name) like lower(?)' , pattern )
80+ Tag . where ( arel_table [ : name] . lower . matches ( pattern . downcase ) )
7181 . order ( :name )
7282 . limit ( limit )
7383 . offset ( offset )
7484 end
7585
7686 def find_normalized ( name )
77- find_by ( name : name . mb_chars . downcase . to_s )
87+ matching_name ( name ) . first
7888 end
7989
8090 def find_normalized! ( name )
8191 find_normalized ( name ) || raise ( ActiveRecord ::RecordNotFound )
8292 end
93+
94+ def matching_name ( name_or_names )
95+ names = Array ( name_or_names ) . map { |name | normalize ( name ) . downcase }
96+
97+ if names . size == 1
98+ where ( arel_table [ :name ] . lower . eq ( names . first ) )
99+ else
100+ where ( arel_table [ :name ] . lower . in ( names ) )
101+ end
102+ end
103+
104+ private
105+
106+ def normalize ( str )
107+ str . gsub ( /\A #/ , '' ) . mb_chars . to_s
108+ end
83109 end
84110
85111 private
0 commit comments