From 734476b73d7aab634fad05b5bed9db27b87d86f8 Mon Sep 17 00:00:00 2001 From: Peter Bhat Harkins Date: Tue, 26 Sep 2023 21:29:04 -0500 Subject: [PATCH] bare searching for username; missing commenter explanation --- app/models/search.rb | 4 ++-- app/models/search_parser.rb | 6 ++++-- app/views/search/index.html.erb | 9 +++++++-- spec/models/search_parser_spec.rb | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/app/models/search.rb b/app/models/search.rb index 3c92c55b..0f10a75d 100644 --- a/app/models/search.rb +++ b/app/models/search.rb @@ -124,7 +124,7 @@ class Search parse_tree.each do |node| type, value = node.first case type - when :commenter + when :commenter, :user n_commenters += 1 return invalid("A comment only has one commenter") if n_commenters > 1 query.joins!(:user).where!(users: {username: value.to_s}) @@ -240,7 +240,7 @@ class Search n_domains += 1 return invalid("A story can't be from multiple domains at once") if n_domains > 1 query.joins!(:domain).where!(domains: {domain: value.to_s}) - when :submitter + when :submitter, :user n_submitters += 1 return invalid("A story only has one submitter") if n_submitters > 1 query.joins!(:user).where!(user: {username: value.to_s}) diff --git a/app/models/search_parser.rb b/app/models/search_parser.rb index aaffc78b..46bac2fc 100644 --- a/app/models/search_parser.rb +++ b/app/models/search_parser.rb @@ -25,6 +25,8 @@ class SearchParser < Parslet::Parser match("[A-Za-z0-9\\-_.:@/()%~?&=#]").repeat(1) ).as(:url) >> space? } + # User::VALID_USERNAME + rule(:user) { match("[@~]") >> match("[A-Za-z0-9_\\-]").repeat(1, 24).as(:user) >> space? } rule(:negated) { str("-") >> (domain | tag | quoted | term).as(:negated) >> space? } # catchall consumes ill-structured input @@ -36,9 +38,9 @@ class SearchParser < Parslet::Parser domain | submitter | tag | - # title before quoted so that doesn't consume the quotes - title | + title | # title before quoted so that doesn't consume the quotes url | + user | # user must come after commenter and submitter # term and quoted after operators they would fail to consume term | quoted | diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb index 50055538..356e8aff 100644 --- a/app/views/search/index.html.erb +++ b/app/views/search/index.html.erb @@ -58,8 +58,10 @@ type, value = node.first case type - when :domain - %> + when :commenter %> +
commenter:<%= value %>
+
Comment by: <%= link_to value, user_path(value) %>
+ <% when :domain %>
domain:<%= value %>
Domain: <%= link_to value, domain_path(value) %>
<% when :submitter %> @@ -71,6 +73,9 @@ <% when :title %>
title:<%= @search.flatten_title(value) %>
Title: <%= @search.flatten_title(value) %>
+ <% when :user %> +
@<%= value %>
+
<%= @search.searched_model.name %> by: <%= link_to value, user_path(value) %>
<% when :negated %> <% when :quoted %>
"<%= value %>"
diff --git a/spec/models/search_parser_spec.rb b/spec/models/search_parser_spec.rb index a546ae88..6bbe0d3b 100644 --- a/spec/models/search_parser_spec.rb +++ b/spec/models/search_parser_spec.rb @@ -65,6 +65,13 @@ describe SearchParser do it("parses multiple words") { expect(sp.quoted).to parse('"research words"') } end + describe "commenter rule" do + it("parses username") { expect(sp.commenter).to parse("commenter:alice") } + it("parses with @") { expect(sp.commenter).to parse("commenter:@bob") } + it("parses with ~") { expect(sp.commenter).to parse("commenter:~carol") } + it("doesn't parse blank") { expect(sp.commenter).to_not parse("commenter:") } + end + describe "domain rule" do it("parses single") { expect(sp.domain).to parse("domain:example.com") } it("parses dash") { expect(sp.domain).to parse("domain:foo-bar.com") } @@ -90,6 +97,14 @@ describe SearchParser do it("parses punctuation stripped from terms") { expect(sp.url).to parse("https://example.com/foo-bar&a=b") } end + describe "user rule" do + it("parses with @") { expect(sp.user).to parse("@bob") } + it("parses with ~") { expect(sp.user).to parse("~carol") } + it("doesn't parse blank @") { expect(sp.user).to_not parse("@") } + it("doesn't parse emails") { expect(sp.user).to_not parse("user@example.com") } + it("doesn't parse blank ~") { expect(sp.user).to_not parse("~") } + end + describe "title rule" do it("parses single") { expect(sp.title).to parse("title:seven") } it("does parse single word quote") { expect(sp.title).to parse('title:"tips"') }