aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorrhenium <re4k@re4k.info>2013-06-01 00:22:57 +0900
committerrhenium <re4k@re4k.info>2013-06-01 00:22:57 +0900
commite1b34a2234a7ff30c30f643d59b73c610372a8c0 (patch)
tree244c31c964f4579049a9c2a692a42cec17d6d109 /app
parentcf51cb4bb07ccd6cfc17d0ee9d22377cc1ea9fc9 (diff)
downloadaclog-e1b34a2234a7ff30c30f643d59b73c610372a8c0.tar.gz
move parse_query to Tweet model
Diffstat (limited to 'app')
-rw-r--r--app/controllers/search_controller.rb59
-rw-r--r--app/models/tweet.rb57
2 files changed, 58 insertions, 58 deletions
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 6cb5014..0ed404a 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -3,63 +3,6 @@ class SearchController < ApplicationController
def search
@caption = "search"
- @tweets = Tweet.where(parse_query(params[:query] || "")).reacted.recent(7).order_by_id.list(params, force_page: true)
- end
-
- private
- def parse_query(input)
- str = input.dup
- strings = []
- str.gsub!(/"((?:\\"|[^"])*?)"/) {|m| strings << $1; "##{strings.size - 1}" }
- groups = []
- while str.sub!(/\(([^()]*?)\)/) {|m| groups << $1; " $#{groups.size - 1} " }; end
-
- conv = -> s do
- s.scan(/\S+(?: +OR +\S+)*/).map {|co|
- co.split(/ +OR +/).map {|token|
- if /^\$(\d+)$/ =~ token
- conv.call(groups[$1.to_i])
- else
- parse_condition(token, strings)
- end
- }.inject(&:or)
- }.inject(&:and)
- end
- conv.call(str)
- end
-
- def parse_condition(token, strings)
- tweets = Tweet.arel_table
- escape_text = -> str do
- str.gsub(/#(\d+)/) { strings[$1.to_i] }
- .gsub("%", "\\%")
- .gsub("*", "%")
- .gsub("_", "\\_")
- .gsub("?", "_")
- end
-
- positive = token[0] != "-"
- case token
- when /^-?(?:user|from):([A-Za-z0-9_]{1,20})$/
- u = User.find_by(screen_name: $1)
- uid = u && u.id || 0
- tweets[:user_id].__send__(positive ? :eq :not_eq, uid)
- when /^-?since:(\d{4}(-?)\d{2}\2\d{2})$/
- tweets[:id].__send__(positive ? :gteq : :lt, snowflake(Date.parse($1)))
- when /^-?until:(\d{4}(-?)\d{2}\2\d{2})$/
- tweets[:id].__send__(positive ? :lt : :gteq, snowflake(Date.parse($1) + 1))
- when /^-?favs?:(\d+)$/
- tweets[:favorites_count].__send__(positive ? :gteq : :lt, $1.to_i)
- when /^-?rts?:(\d+)$/
- tweets[:retweets_count].__send__(positive ? :gteq : :lt, $1.to_i)
- when /^-?(?:sum|reactions?):(\d+)$/
- (tweets[:favorites_count] + tweets[:retweets_count]).__send__(positive ? :gteq : :lt, $1.to_i)
- when /^(?:source|via):(.+)$/
- source_text = "<url:%:#{escape_text.call($1).gsub(":", "%3A")}>"
- tweets[:source].__send__(positive ? :matches : :does_not_match, source_text)
- else
- search_text = escape_text.call(positive ? token : token[1..-1])
- tweets[:text].__send__(positive ? :matches : :does_not_match, "%#{search_text}%")
- end
+ @tweets = Tweet.recent(7).parse_query(params[:query] || "").reacted.order_by_id.list(params, force_page: true)
end
end
diff --git a/app/models/tweet.rb b/app/models/tweet.rb
index dd7d0bc..602fdaa 100644
--- a/app/models/tweet.rb
+++ b/app/models/tweet.rb
@@ -92,7 +92,64 @@ class Tweet < ActiveRecord::Base
end
end
+ def self.parse_query(query)
+ str = query.dup
+ strings = []
+ str.gsub!(/"((?:\\"|[^"])*?)"/) {|m| strings << $1; "##{strings.size - 1}" }
+ groups = []
+ while str.sub!(/\(([^()]*?)\)/) {|m| groups << $1; " $#{groups.size - 1} " }; end
+
+ conv = -> s do
+ s.scan(/\S+(?: +OR +\S+)*/).map {|co|
+ co.split(/ +OR +/).map {|token|
+ if /^\$(\d+)$/ =~ token
+ conv.call(groups[$1.to_i])
+ else
+ parse_condition(token, strings)
+ end
+ }.inject(&:or)
+ }.inject(&:and)
+ end
+
+ where(conv.call(str))
+ end
+
private
+ def self.parse_condition(token, strings)
+ tweets = Tweet.arel_table
+ escape_text = -> str do
+ str.gsub(/#(\d+)/) { strings[$1.to_i] }
+ .gsub("%", "\\%")
+ .gsub("*", "%")
+ .gsub("_", "\\_")
+ .gsub("?", "_")
+ end
+
+ positive = token[0] != "-"
+ case token
+ when /^-?(?:user|from):([A-Za-z0-9_]{1,20})$/
+ u = User.find_by(screen_name: $1)
+ uid = u && u.id || 0
+ tweets[:user_id].__send__(positive ? :eq :not_eq, uid)
+ when /^-?since:(\d{4}(-?)\d{2}\2\d{2})$/
+ tweets[:id].__send__(positive ? :gteq : :lt, snowflake(Date.parse($1)))
+ when /^-?until:(\d{4}(-?)\d{2}\2\d{2})$/
+ tweets[:id].__send__(positive ? :lt : :gteq, snowflake(Date.parse($1) + 1))
+ when /^-?favs?:(\d+)$/
+ tweets[:favorites_count].__send__(positive ? :gteq : :lt, $1.to_i)
+ when /^-?rts?:(\d+)$/
+ tweets[:retweets_count].__send__(positive ? :gteq : :lt, $1.to_i)
+ when /^-?(?:sum|reactions?):(\d+)$/
+ (tweets[:favorites_count] + tweets[:retweets_count]).__send__(positive ? :gteq : :lt, $1.to_i)
+ when /^(?:source|via):(.+)$/
+ source_text = "<url:%:#{escape_text.call($1).gsub(":", "%3A")}>"
+ tweets[:source].__send__(positive ? :matches : :does_not_match, source_text)
+ else
+ search_text = escape_text.call(positive ? token : token[1..-1])
+ tweets[:text].__send__(positive ? :matches : :does_not_match, "%#{search_text}%")
+ end
+ end
+
def self.cache_list(expires_in)
key = "tweets/#{scoped.to_sql}"
ids = Rails.cache.read(key)