post versions: add ability to search post versions by tags.
* Add ability to search /post_versions by added tags, removed tags, or changed tags (added or removed). * Add 'History' link to the sidebar of the /posts index. This is a shortcut for a /post_versions search of the current tag.
This commit is contained in:
@@ -39,10 +39,14 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
where.not("#{qualified_column_for(attr)} ~ ?", "(?e)" + value)
|
||||
end
|
||||
|
||||
def where_array_includes(attr, values)
|
||||
def where_array_includes_any(attr, values)
|
||||
where("#{qualified_column_for(attr)} && ARRAY[?]", values)
|
||||
end
|
||||
|
||||
def where_array_includes_all(attr, values)
|
||||
where("#{qualified_column_for(attr)} @> ARRAY[?]", values)
|
||||
end
|
||||
|
||||
def where_array_count(attr, value)
|
||||
relation = all
|
||||
qualified_column = "cardinality(#{qualified_column_for(attr)})"
|
||||
@@ -100,6 +104,10 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
column = column_for_attribute(name)
|
||||
type = column.type || reflect_on_association(name)&.class_name
|
||||
|
||||
if column.array?
|
||||
return search_array_attribute(name, type, params)
|
||||
end
|
||||
|
||||
case type
|
||||
when "User"
|
||||
search_user_attribute(name, params)
|
||||
@@ -110,11 +118,7 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
when :boolean
|
||||
search_boolean_attribute(name, params)
|
||||
when :integer, :datetime
|
||||
if column.array?
|
||||
search_array_attribute(name, type, params)
|
||||
else
|
||||
numeric_attribute_matches(name, params[name])
|
||||
end
|
||||
numeric_attribute_matches(name, params[name])
|
||||
else
|
||||
raise NotImplementedError, "unhandled attribute type"
|
||||
end
|
||||
@@ -173,9 +177,16 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
def search_array_attribute(name, type, params)
|
||||
relation = all
|
||||
|
||||
if params[:"#{name}_include"] && type == :integer
|
||||
items = params[:"#{name}_include"].to_s.scan(/\d+/).map(&:to_i)
|
||||
relation = relation.where_array_includes(name, items)
|
||||
if params[:"#{name}_include_any"]
|
||||
items = params[:"#{name}_include_any"].to_s.scan(/[^[:space:]]+/)
|
||||
items = items.map(&:to_i) if type == :integer
|
||||
|
||||
relation = relation.where_array_includes_any(name, items)
|
||||
elsif params[:"#{name}_include_all"]
|
||||
items = params[:"#{name}_include_any"].to_s.scan(/[^[:space:]]+/)
|
||||
items = items.map(&:to_i) if type == :integer
|
||||
|
||||
relation = relation.where_array_includes_all(name, items)
|
||||
end
|
||||
|
||||
if params[:"#{name.to_s.singularize}_count"]
|
||||
|
||||
@@ -19,7 +19,7 @@ class PoolArchive < ApplicationRecord
|
||||
end
|
||||
|
||||
def for_post_id(post_id)
|
||||
where_array_includes(:added_post_ids, [post_id]).or(where_array_includes(:removed_post_ids, [post_id]))
|
||||
where_array_includes_any(:added_post_ids, [post_id]).or(where_array_includes_any(:removed_post_ids, [post_id]))
|
||||
end
|
||||
|
||||
def search(params)
|
||||
|
||||
@@ -18,9 +18,23 @@ class PostArchive < ApplicationRecord
|
||||
end
|
||||
|
||||
module SearchMethods
|
||||
def changed_tags_include(tag)
|
||||
where_array_includes_all(:added_tags, [tag]).or(where_array_includes_all(:removed_tags, [tag]))
|
||||
end
|
||||
|
||||
def changed_tags_include_all(tags)
|
||||
tags.reduce(all) do |relation, tag|
|
||||
relation.changed_tags_include(tag)
|
||||
end
|
||||
end
|
||||
|
||||
def search(params)
|
||||
q = super
|
||||
q = q.search_attributes(params, :updater_id, :post_id, :rating, :rating_changed, :parent_id, :parent_changed, :source, :source_changed, :version)
|
||||
q = q.search_attributes(params, :updater_id, :post_id, :tags, :added_tags, :removed_tags, :rating, :rating_changed, :parent_id, :parent_changed, :source, :source_changed, :version)
|
||||
|
||||
if params[:changed_tags]
|
||||
q = q.changed_tags_include_all(params[:changed_tags].scan(/[^[:space:]]+/))
|
||||
end
|
||||
|
||||
if params[:updater_name].present?
|
||||
q = q.where(updater_id: User.name_to_id(params[:updater_name]))
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
<%= search_form_for(post_versions_path) do |f| %>
|
||||
<%= f.input :updated_at, label: "Date" %>
|
||||
<%= f.input :updater_name, label: "Updater", input_html: { "data-autocomplete": "user" } %>
|
||||
<%= f.input :changed_tags_include_all, label: "Changed tags" %>
|
||||
<%= f.input :added_tags_include_all, label: "Added tags" %>
|
||||
<%= f.input :removed_tags_include_all, label: "Removed tags" %>
|
||||
<%= f.input :post_id %>
|
||||
<%= f.input :parent_id %>
|
||||
<%= f.input :rating %>
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
<% end %>
|
||||
|
||||
<li><%= link_to "Deleted", posts_path(:tags => "#{params[:tags]} status:deleted"), :rel => "nofollow" %></li>
|
||||
|
||||
<li><%= link_to "Random", random_posts_path(:tags => params[:tags]), :id => "random-post", :rel => "nofollow", :"data-shortcut" => "r" %></li>
|
||||
|
||||
<% if Tag.is_simple_tag?(params[:tags]) %>
|
||||
<li><%= link_to "History", post_versions_path(search: { changed_tags: params[:tags] }) %></li>
|
||||
<% end %>
|
||||
<li><%= link_to "Count", posts_counts_path(:tags => params[:tags]) %></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
@@ -7,7 +7,7 @@ class PostVersionsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
context "The post versions controller" do
|
||||
context "index action" do
|
||||
setup do
|
||||
setup do
|
||||
@user.as_current do
|
||||
@post = create(:post)
|
||||
travel(2.hours) do
|
||||
@@ -34,6 +34,17 @@ class PostVersionsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :success
|
||||
assert_select "#post-version-#{@post2.versions[0].id}", false
|
||||
end
|
||||
|
||||
should "list all versions for search[changed_tags]" do
|
||||
get post_versions_path, as: :json, params: { search: { changed_tags: "1" }}
|
||||
assert_response :success
|
||||
assert_equal @versions[1].id, response.parsed_body[1]["id"].to_i
|
||||
assert_equal @versions[2].id, response.parsed_body[0]["id"].to_i
|
||||
|
||||
get post_versions_path, as: :json, params: { search: { changed_tags: "1 2" }}
|
||||
assert_response :success
|
||||
assert_equal @versions[1].id, response.parsed_body[0]["id"].to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,8 +66,8 @@ class PoolTest < ActiveSupport::TestCase
|
||||
@post1 = create(:post, tag_string: "pool:pool1")
|
||||
@post2 = create(:post, tag_string: "pool:pool2")
|
||||
|
||||
assert_equal([@pool1.id], Pool.search(post_ids_include: @post1.id).pluck(:id))
|
||||
assert_equal([@pool2.id, @pool1.id], Pool.search(post_ids_include: "#{@post1.id} #{@post2.id}").pluck(:id))
|
||||
assert_equal([@pool1.id], Pool.search(post_ids_include_any: @post1.id).pluck(:id))
|
||||
assert_equal([@pool2.id, @pool1.id], Pool.search(post_ids_include_any: "#{@post1.id} #{@post2.id}").pluck(:id))
|
||||
end
|
||||
|
||||
should "find pools by post id count" do
|
||||
|
||||
Reference in New Issue
Block a user