update specs; add new specs to test for reported bug related to AND query in referenced table

This commit is contained in:
Bilal
2020-04-20 22:21:26 +02:00
parent f4bec85161
commit 455845e36b
3 changed files with 140 additions and 25 deletions

View File

@@ -158,35 +158,132 @@ describe PgSearchable do
expect(DynamicModelWithTagValues.scope_search('tag:green or value:"not"')).to contain_exactly(record1, record2) expect(DynamicModelWithTagValues.scope_search('tag:green or value:"not"')).to contain_exactly(record1, record2)
end end
it 'can search in referenced column and in model columns with multiple search terms connected with logical operators' do describe 'searching in model with has_many association' do
record1 = DynamicModelWithTagValues.create name: 'something', value: 'amazing' before do
record2 = DynamicModelWithTagValues.create name: 'new record', value: 'not so amazing' records = DynamicModelWithTagValues.create [{ name: 'something', value: 'amazing' },
record3 = DynamicModelWithTagValues.create name: 'last one', value: 'no value' { name: 'new record', value: 'not so amazing' },
record4 = DynamicModelWithTagValues.create name: 'really last one', value: 'no value' { name: 'last one', value: 'no value' },
Tag.create(taggable: record1, value: 'red') { name: 'really last one', value: 'no value' }]
Tag.create(taggable: record1, value: 'green')
Tag.create(taggable: record2, value: 'black')
Tag.create(taggable: record3, value: '-12')
Tag.create(taggable: record4, value: '-')
expect(DynamicModelWithTagValues.scope_search('tag:red or tag:black')).to contain_exactly(record1, record2) Tag.create [{ taggable: records[0], value: 'red', custom_attribute: 'rose' },
expect(DynamicModelWithTagValues.scope_search('tag:red and tag:black')).to be_empty { taggable: records[0], value: 'green', custom_attribute: 'garden' },
expect(DynamicModelWithTagValues.scope_search('tag:red or tag:green')).to contain_exactly(record1) { taggable: records[1], value: 'black', custom_attribute: 'sky' },
expect(DynamicModelWithTagValues.scope_search('not tag:-12 and not value:amazing')).to contain_exactly(record4) { taggable: records[2], value: '-1/12', custom_attribute: 'gold nugget' },
{ taggable: records[3], value: '-', custom_attribute: 'unknown' },
{ taggable: records[3], value: 'red-green', custom_attribute: 'unicorn' }]
end
it 'can search with multiple search terms connected with OR operator' do
records = DynamicModelWithTagValues.all
expect(DynamicModelWithTagValues.scope_search('tag:red or tag:black')).to contain_exactly(records[0], records[1], records[3])
expect(DynamicModelWithTagValues.scope_search('tag:red or tag:green')).to contain_exactly(records[0], records[3])
end
it 'can search with multiple search terms connected with AND operator' do
records = DynamicModelWithTagValues.all
expect(DynamicModelWithTagValues.scope_search('tag:red and tag:black')).to be_empty
expect(DynamicModelWithTagValues.scope_search('tag:red and tag:green')).to contain_exactly(records[0], records[3])
end
it 'can search with multiple search terms and containing NOT' do
records = DynamicModelWithTagValues.all
expect(DynamicModelWithTagValues.scope_search('not tag:"-1/12" and not value:amazing')).to contain_exactly(records[3])
end
it 'can search in referenced column and in model columns with multiple search terms connected with logical operators and with brackets' do
records = DynamicModelWithTagValues.all
expect(DynamicModelWithTagValues.scope_search('(tag:- and not tag:12) or (value:"amazing" and not value:"not")')).to contain_exactly(records[0], records[3])
end
end end
it 'can search in referenced column and in model columns with multiple search terms connected with logical operators and with brackets' do describe 'searching through multiple referenced columns in model with has_many association' do
record1 = DynamicModelWithTagValues.create name: 'something', value: 'amazing' before do
record2 = DynamicModelWithTagValues.create name: 'new record', value: 'not so amazing' records = DynamicModelWithTagValuesAndCustomAttribute.create [{ name: 'something', value: 'amazing' },
record3 = DynamicModelWithTagValues.create name: 'last one', value: 'no value' { name: 'new record', value: 'not so amazing' },
record4 = DynamicModelWithTagValues.create name: 'really last one', value: 'no value' { name: 'last one', value: 'no value' },
Tag.create(taggable: record1, value: 'red') { name: 'really last one', value: 'no value' }]
Tag.create(taggable: record1, value: 'green')
Tag.create(taggable: record2, value: 'black')
Tag.create(taggable: record3, value: '-12')
Tag.create(taggable: record4, value: '-')
expect(DynamicModelWithTagValues.scope_search('(tag:- and not tag:12) or (value:"amazing" and not value:"not")')).to contain_exactly(record1, record4) Tag.create [{ taggable: records[0], value: 'red', custom_attribute: 'rose' },
{ taggable: records[0], value: 'green', custom_attribute: 'garden' },
{ taggable: records[1], value: 'black', custom_attribute: 'sky' },
{ taggable: records[2], value: '-1/12', custom_attribute: 'gold nugget' },
{ taggable: records[3], value: '-', custom_attribute: 'unknown' },
{ taggable: records[3], value: 'red-green', custom_attribute: 'unicorn' }]
end
it 'can search with multiple search terms connected with OR operator' do
records = DynamicModelWithTagValuesAndCustomAttribute.all
expect(DynamicModelWithTagValuesAndCustomAttribute.scope_search('tag:red or custom:sky')).to contain_exactly(records[0], records[1], records[3])
end
it 'can search with multiple search terms connected with AND operator' do
records = DynamicModelWithTagValuesAndCustomAttribute.all
expect(DynamicModelWithTagValuesAndCustomAttribute.scope_search('custom:unicorn and tag:black')).to be_empty
expect(DynamicModelWithTagValuesAndCustomAttribute.scope_search('tag:"-1/12" and custom:gold')).to contain_exactly(records[2])
end
it 'can search with multiple search terms and containing NOT' do
expect(DynamicModelWithTagValuesAndCustomAttribute.scope_search('not tag:"-1/12" and not value:amazing and not custom:unknown')).to be_empty
end
it 'can search with multiple search terms connected with logical operators and with brackets' do
records = DynamicModelWithTagValuesAndCustomAttribute.all
expect(DynamicModelWithTagValuesAndCustomAttribute.scope_search('(tag:- and not tag:12) or (value:"amazing" and not value:"not") or (custom:unknown or custom:rose)')).to contain_exactly(records[0], records[3])
end
end
describe 'searching in model with multiple has_many associations' do
before do
records = DynamicModelWithTagAndCategories.create [{ name: 'something', value: 'amazing' },
{ name: 'new record', value: 'not so amazing' },
{ name: 'last one', value: 'no value' },
{ name: 'really last one', value: 'no value' }]
Tag.create [{ taggable: records[0], value: 'red', custom_attribute: 'rose' },
{ taggable: records[0], value: 'green', custom_attribute: 'garden' },
{ taggable: records[1], value: 'black', custom_attribute: 'sky' },
{ taggable: records[2], value: '-1/12', custom_attribute: 'gold nugget' },
{ taggable: records[3], value: '-', custom_attribute: 'unknown' },
{ taggable: records[3], value: 'red-green', custom_attribute: 'unicorn' }]
Category.create [{ categoriable: records[0], name: 'home' },
{ categoriable: records[0], name: 'home' },
{ categoriable: records[1], name: 'world' },
{ categoriable: records[2], name: 'math' },
{ categoriable: records[3], name: 'unknown' },
{ categoriable: records[3], name: 'myth' }]
end
it 'can search with multiple search terms connected with OR operator' do
records = DynamicModelWithTagAndCategories.all
expect(DynamicModelWithTagAndCategories.scope_search('tag:red or category:math')).to contain_exactly(records[0], records[2], records[3])
end
it 'can search with multiple search terms connected with AND operator' do
records = DynamicModelWithTagAndCategories.all
expect(DynamicModelWithTagAndCategories.scope_search('category:home and tag:-')).to be_empty
expect(DynamicModelWithTagAndCategories.scope_search('tag:"-1/12" and category:math')).to contain_exactly(records[2])
end
it 'can search with multiple search terms and containing NOT' do
expect(DynamicModelWithTagAndCategories.scope_search('not tag:"-1/12" and not value:amazing and not category:unknown')).to be_empty
end
it 'can search with multiple search terms connected with logical operators and with brackets' do
records = DynamicModelWithTagAndCategories.all
expect(DynamicModelWithTagAndCategories.scope_search('(tag:- and not tag:12) or (value:"amazing" and not value:"not") or (category:unknown or category:math)')).to contain_exactly(records[0], records[2], records[3])
end
end end
end end
end end

View File

@@ -27,6 +27,7 @@ ActiveRecord::Schema.define do
create_table :tags, force: true do |t| create_table :tags, force: true do |t|
t.string :value t.string :value
t.string :custom_attribute
t.references :category, index: true t.references :category, index: true
t.references :taggable, polymorphic: true, index: true t.references :taggable, polymorphic: true, index: true
t.timestamps null: false t.timestamps null: false
@@ -34,6 +35,7 @@ ActiveRecord::Schema.define do
create_table :categories, force: true do |t| create_table :categories, force: true do |t|
t.string :name t.string :name
t.references :categoriable, polymorphic: true, index: true
t.timestamps null: false t.timestamps null: false
end end

View File

@@ -82,6 +82,21 @@ class DynamicModelWithTagValues < ActiveRecord::Base
has_many :tags, as: :taggable has_many :tags, as: :taggable
end end
class DynamicModelWithTagAndCategories < ActiveRecord::Base
self.table_name = :dynamic_models
include PgSearchable
pg_search fields: %i[dynamic_models.id dynamic_models.name dynamic_models.value], fields_mappings: {tag: 'tags.value', category: 'categories.name'}, joins: [:tags, :categories]
has_many :tags, as: :taggable
has_many :categories, as: :categoriable
end
class DynamicModelWithTagValuesAndCustomAttribute < ActiveRecord::Base
self.table_name = :dynamic_models
include PgSearchable
pg_search fields: %i[dynamic_models.id dynamic_models.name dynamic_models.value], fields_mappings: {tag: 'tags.value', custom: 'tags.custom_attribute'}, joins: [:tags]
has_many :tags, as: :taggable
end
class DynamicModelWithCategory < ActiveRecord::Base class DynamicModelWithCategory < ActiveRecord::Base
self.table_name = :dynamic_models self.table_name = :dynamic_models
include PgSearchable include PgSearchable
@@ -112,4 +127,5 @@ end
class Category < ActiveRecord::Base class Category < ActiveRecord::Base
has_many :tags has_many :tags
belongs_to :categoriable, polymorphic: true
end end