ddr-models 2.4.0.rc4 → 2.4.0.rc5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/ddr-models.gemspec +1 -1
- data/lib/ddr/index.rb +1 -2
- data/lib/ddr/index/field_attribute.rb +18 -0
- data/lib/ddr/index/filter.rb +70 -38
- data/lib/ddr/index/filters.rb +7 -20
- data/lib/ddr/index/query.rb +13 -8
- data/lib/ddr/index/query_builder.rb +122 -49
- data/lib/ddr/index/query_clause.rb +55 -41
- data/lib/ddr/index/query_params.rb +28 -12
- data/lib/ddr/index/sort_order.rb +11 -3
- data/lib/ddr/models/version.rb +1 -1
- data/spec/index/filter_spec.rb +74 -32
- data/spec/index/query_builder_spec.rb +45 -24
- data/spec/index/query_clause_spec.rb +29 -21
- data/spec/index/query_spec.rb +6 -3
- metadata +5 -12
- data/lib/ddr/index/queries.rb +0 -20
- data/lib/ddr/index/query_value.rb +0 -24
- data/spec/index/filters_spec.rb +0 -34
- data/spec/index/queries_spec.rb +0 -21
- data/spec/index/query_value_spec.rb +0 -33
@@ -1,17 +1,42 @@
|
|
1
|
+
require "virtus"
|
2
|
+
|
1
3
|
module Ddr::Index
|
2
4
|
class QueryClause
|
5
|
+
include Virtus.value_object
|
6
|
+
|
7
|
+
ANY_FIELD = Field.new('*').freeze
|
8
|
+
ANY_VALUE = "[* TO *]"
|
9
|
+
QUOTE = '"'
|
10
|
+
|
11
|
+
TERM_QUERY = "{!term f=%{field}}%{value}"
|
12
|
+
STANDARD_QUERY = "%{field}:%{value}"
|
13
|
+
NEGATIVE_QUERY = "-%{field}:%{value}"
|
14
|
+
DISJUNCTION = "{!lucene q.op=OR df=%{field}}%{value}"
|
15
|
+
|
16
|
+
values do
|
17
|
+
attribute :field, FieldAttribute
|
18
|
+
attribute :value, String
|
19
|
+
attribute :quote_value, Boolean, default: false
|
20
|
+
attribute :template, String, default: STANDARD_QUERY
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
template % { field: field, value: quote_value ? quote(value) : value }
|
25
|
+
end
|
3
26
|
|
4
|
-
|
5
|
-
|
6
|
-
|
27
|
+
def quote(value)
|
28
|
+
self.class.quote(value)
|
29
|
+
end
|
7
30
|
|
8
31
|
class << self
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
32
|
+
|
33
|
+
def quote(value)
|
34
|
+
# Derived from Blacklight::Solr::SearchBuilderBehavior#solr_param_quote
|
35
|
+
unless value =~ /\A[a-zA-Z0-9$_\-\^]+\z/
|
36
|
+
QUOTE + value.gsub("'", "\\\\\'").gsub('"', "\\\\\"") + QUOTE
|
37
|
+
else
|
38
|
+
value
|
39
|
+
end
|
15
40
|
end
|
16
41
|
|
17
42
|
# Builds a query clause to retrieve the index document by unique key.
|
@@ -20,62 +45,51 @@ module Ddr::Index
|
|
20
45
|
end
|
21
46
|
alias_method :id, :unique_key
|
22
47
|
|
48
|
+
def where(field, value)
|
49
|
+
if value.respond_to?(:each)
|
50
|
+
disjunction(field, value)
|
51
|
+
else
|
52
|
+
new(field: field, value: value, quote_value: true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
23
56
|
# Builds a query clause to filter where field does not have the given value.
|
24
|
-
# @param field [Field, String] field
|
25
|
-
# @param value [String] query value
|
26
|
-
# @return [String] query clause
|
27
57
|
def negative(field, value)
|
28
|
-
|
58
|
+
new(field: field, value: value, template: NEGATIVE_QUERY, quote_value: true)
|
29
59
|
end
|
30
60
|
|
31
61
|
# Builds a query clause to filter where field is present (i.e, has any value)
|
32
|
-
# @param field [Field, String] field
|
33
|
-
# @return [String] query clause
|
34
62
|
def present(field)
|
35
|
-
|
63
|
+
new(field: field, value: ANY_VALUE)
|
36
64
|
end
|
37
65
|
|
38
66
|
# Builds a query clause to filter where field is NOT present (no values)
|
39
|
-
# @param field [Field, String] field
|
40
|
-
# @return [String] query clause
|
41
67
|
def absent(field)
|
42
|
-
|
68
|
+
new(field: "-#{field}", value: ANY_VALUE)
|
43
69
|
end
|
44
70
|
|
45
71
|
# Builds a query clause to filter where field contains at least one of a set of values.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
def or_values(field, values)
|
50
|
-
build(field, QueryValue.or_values(values))
|
72
|
+
def disjunction(field, values)
|
73
|
+
value = values.map { |v| quote(v) }.join(" ")
|
74
|
+
new(field: field, value: value, template: DISJUNCTION)
|
51
75
|
end
|
52
76
|
|
53
77
|
# Builds a query clause to filter where date field value is earlier than a date/time value.
|
54
|
-
|
55
|
-
|
56
|
-
# @return [String] query clause
|
57
|
-
def before(field, date_time)
|
58
|
-
value = "[* TO %s]" % Ddr::Utils.solr_date(date_time)
|
59
|
-
build(field, value)
|
78
|
+
def before(field, value)
|
79
|
+
new(field: field, value: "[* TO %s]" % Ddr::Utils.solr_date(value))
|
60
80
|
end
|
81
|
+
alias_method :before_date_time, :before
|
61
82
|
|
62
83
|
# Builds a query clause to filter where date field value is earlier than a number of days before now.
|
63
|
-
|
64
|
-
|
65
|
-
# @return [String] query clause
|
66
|
-
def before_days(field, days)
|
67
|
-
value = BEFORE_DAYS % days.to_i
|
68
|
-
build(field, value)
|
84
|
+
def before_days(field, value)
|
85
|
+
new(field: field, value: "[* TO NOW-%iDAYS]" % value)
|
69
86
|
end
|
70
87
|
|
71
88
|
# Builds a "term query" clause to filter where field contains value.
|
72
|
-
# Double quotes are escaped.
|
73
|
-
# @param field [Field, String] field
|
74
|
-
# @param value [String] query value
|
75
|
-
# @return [String] Solr term query
|
76
89
|
def term(field, value)
|
77
|
-
|
90
|
+
new(field: field, value: value, template: TERM_QUERY)
|
78
91
|
end
|
92
|
+
|
79
93
|
end
|
80
94
|
|
81
95
|
end
|
@@ -1,23 +1,39 @@
|
|
1
|
-
require "delegate"
|
2
|
-
|
3
1
|
module Ddr::Index
|
4
|
-
class QueryParams
|
2
|
+
class QueryParams
|
5
3
|
|
6
|
-
attr_reader :
|
4
|
+
attr_reader :query
|
7
5
|
|
8
6
|
def initialize(query)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
@query = query
|
8
|
+
end
|
9
|
+
|
10
|
+
def params
|
11
|
+
{ q: q_param,
|
12
|
+
fq: filter_queries,
|
13
|
+
fl: fields,
|
14
|
+
sort: sort,
|
15
15
|
rows: rows,
|
16
16
|
}.select { |k, v| v.present? }
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
19
|
+
def q_param
|
20
|
+
query.q.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def filter_queries
|
24
|
+
query.filter_clauses.map(&:to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def fields
|
28
|
+
query.fields.join(",")
|
29
|
+
end
|
30
|
+
|
31
|
+
def sort
|
32
|
+
query.sort.join(",")
|
33
|
+
end
|
34
|
+
|
35
|
+
def rows
|
36
|
+
query.rows
|
21
37
|
end
|
22
38
|
|
23
39
|
end
|
data/lib/ddr/index/sort_order.rb
CHANGED
@@ -2,18 +2,26 @@ require "virtus"
|
|
2
2
|
|
3
3
|
module Ddr::Index
|
4
4
|
class SortOrder
|
5
|
-
include Virtus.value_object
|
5
|
+
include Virtus.value_object
|
6
6
|
|
7
7
|
ASC = "asc"
|
8
8
|
DESC = "desc"
|
9
9
|
|
10
10
|
values do
|
11
|
-
attribute :field,
|
11
|
+
attribute :field, FieldAttribute
|
12
12
|
attribute :order, String
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_s
|
16
|
-
[field, order].join(" ")
|
16
|
+
[ field, order ].join(" ")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.asc(field)
|
20
|
+
new(field: field, order: ASC)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.desc(field)
|
24
|
+
new(field: field, order: DESC)
|
17
25
|
end
|
18
26
|
|
19
27
|
end
|
data/lib/ddr/models/version.rb
CHANGED
data/spec/index/filter_spec.rb
CHANGED
@@ -6,59 +6,101 @@ module Ddr::Index
|
|
6
6
|
describe "equality" do
|
7
7
|
describe "when the other is a Filter instance" do
|
8
8
|
describe "and the clauses are equal" do
|
9
|
-
subject { described_class.new(["foo:bar", "spam:eggs"]) }
|
10
|
-
let(:other) { described_class.new(["foo:bar", "spam:eggs"]) }
|
9
|
+
subject { described_class.new(clauses: ["foo:bar", "spam:eggs"]) }
|
10
|
+
let(:other) { described_class.new(clauses: ["foo:bar", "spam:eggs"]) }
|
11
11
|
specify { expect(subject).to eq other }
|
12
12
|
end
|
13
13
|
describe "and the clauses are not equal" do
|
14
|
-
subject { described_class.new(["foo:bar", "bam:baz"]) }
|
15
|
-
let(:other) { described_class.new(["foo:bar", "spam:eggs"]) }
|
14
|
+
subject { described_class.new(clauses: ["foo:bar", "bam:baz"]) }
|
15
|
+
let(:other) { described_class.new(clauses: ["foo:bar", "spam:eggs"]) }
|
16
16
|
specify { expect(subject).not_to eq other }
|
17
17
|
end
|
18
18
|
end
|
19
19
|
describe "when the other is not a Filter instance" do
|
20
|
-
subject { described_class.new(["foo:bar", "spam:eggs"]) }
|
20
|
+
subject { described_class.new(clauses: ["foo:bar", "spam:eggs"]) }
|
21
21
|
let(:other) { double(clauses: ["foo:bar", "spam:eggs"]) }
|
22
22
|
specify { expect(subject).not_to eq other }
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
describe "class methods" do
|
27
|
-
describe ".
|
28
|
-
|
29
|
-
|
27
|
+
describe ".is_governed_by" do
|
28
|
+
describe "with an object" do
|
29
|
+
subject { described_class.is_governed_by(Item.new(pid: "test:1")) }
|
30
|
+
its(:clauses) {
|
31
|
+
are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
|
32
|
+
}
|
33
|
+
end
|
34
|
+
describe "with an ID" do
|
35
|
+
subject { described_class.is_governed_by("test:1") }
|
36
|
+
its(:clauses) {
|
37
|
+
are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
|
38
|
+
}
|
39
|
+
end
|
30
40
|
end
|
31
|
-
describe "
|
32
|
-
|
41
|
+
describe ".is_member_of_collection" do
|
42
|
+
describe "with an object" do
|
43
|
+
subject { described_class.is_member_of_collection(Item.new(pid: "test:1")) }
|
44
|
+
its(:clauses) {
|
45
|
+
are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
|
46
|
+
}
|
47
|
+
end
|
48
|
+
describe "with an ID" do
|
49
|
+
subject { described_class.is_member_of_collection("test:1") }
|
50
|
+
its(:clauses) {
|
51
|
+
are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
describe ".has_content" do
|
56
|
+
subject { described_class.has_content }
|
57
|
+
its(:clauses) { are_expected.to eq([QueryClause.where(:active_fedora_model, ["Component", "Attachment", "Target"])]) }
|
58
|
+
end
|
59
|
+
describe ".where" do
|
60
|
+
subject { described_class.where("foo"=>"bar", "spam"=>"eggs", "stuff"=>["dog", "cat", "bird"]) }
|
61
|
+
its(:clauses) {
|
62
|
+
are_expected.to eq([QueryClause.where("foo", "bar"),
|
63
|
+
QueryClause.where("spam", "eggs"),
|
64
|
+
QueryClause.where("stuff", ["dog", "cat", "bird"])
|
65
|
+
])
|
66
|
+
}
|
67
|
+
end
|
68
|
+
describe ".raw" do
|
69
|
+
subject { described_class.raw("foo:bar", "spam:eggs") }
|
33
70
|
its(:clauses) { are_expected.to eq(["foo:bar", "spam:eggs"]) }
|
34
71
|
end
|
35
|
-
describe "
|
36
|
-
subject {
|
37
|
-
its(:clauses) { are_expected.to eq(["
|
72
|
+
describe ".negative" do
|
73
|
+
subject { described_class.negative("foo", "bar") }
|
74
|
+
its(:clauses) { are_expected.to eq([QueryClause.negative("foo", "bar")]) }
|
38
75
|
end
|
39
|
-
describe "
|
40
|
-
subject {
|
41
|
-
its(:clauses) { are_expected.to eq(["foo
|
76
|
+
describe ".present" do
|
77
|
+
subject { described_class.present("foo") }
|
78
|
+
its(:clauses) { are_expected.to eq([QueryClause.present("foo")]) }
|
42
79
|
end
|
43
|
-
describe "
|
44
|
-
subject {
|
45
|
-
its(:clauses) { are_expected.to eq(["
|
80
|
+
describe ".absent" do
|
81
|
+
subject { described_class.absent("foo") }
|
82
|
+
its(:clauses) { are_expected.to eq([QueryClause.absent("foo")]) }
|
46
83
|
end
|
47
|
-
describe "
|
48
|
-
subject {
|
49
|
-
its(:clauses) { are_expected.to eq(["foo
|
84
|
+
describe ".before_days" do
|
85
|
+
subject { described_class.before_days("foo", 60) }
|
86
|
+
its(:clauses) { are_expected.to eq([QueryClause.before_days("foo", 60)]) }
|
50
87
|
end
|
51
|
-
describe "
|
52
|
-
subject {
|
53
|
-
its(:clauses) {
|
88
|
+
describe ".before" do
|
89
|
+
subject { described_class.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400")) }
|
90
|
+
its(:clauses) {
|
91
|
+
are_expected.to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
|
92
|
+
}
|
54
93
|
end
|
55
94
|
end
|
56
95
|
|
57
|
-
describe "
|
96
|
+
describe "API methods" do
|
58
97
|
describe "#where" do
|
59
98
|
it "adds raw query filters for the hash of conditions" do
|
60
99
|
subject.where("foo"=>"bar", "spam"=>"eggs", "stuff"=>["dog", "cat", "bird"])
|
61
|
-
expect(subject.clauses).to eq(["
|
100
|
+
expect(subject.clauses).to eq([QueryClause.where("foo", "bar"),
|
101
|
+
QueryClause.where("spam", "eggs"),
|
102
|
+
QueryClause.where("stuff", ["dog", "cat", "bird"])
|
103
|
+
])
|
62
104
|
end
|
63
105
|
end
|
64
106
|
describe "#raw" do
|
@@ -70,31 +112,31 @@ module Ddr::Index
|
|
70
112
|
describe "#negative" do
|
71
113
|
it "adds a negation query clause" do
|
72
114
|
subject.negative("foo", "bar")
|
73
|
-
expect(subject.clauses).to eq(["
|
115
|
+
expect(subject.clauses).to eq([QueryClause.negative("foo", "bar")])
|
74
116
|
end
|
75
117
|
end
|
76
118
|
describe "#present" do
|
77
119
|
it "adds a \"field present\" query clause" do
|
78
120
|
subject.present("foo")
|
79
|
-
expect(subject.clauses).to eq(["foo
|
121
|
+
expect(subject.clauses).to eq([QueryClause.present("foo")])
|
80
122
|
end
|
81
123
|
end
|
82
124
|
describe "#absent" do
|
83
125
|
it "adds a \"field not present\" query clause" do
|
84
126
|
subject.absent("foo")
|
85
|
-
expect(subject.clauses).to eq(["
|
127
|
+
expect(subject.clauses).to eq([QueryClause.absent("foo")])
|
86
128
|
end
|
87
129
|
end
|
88
130
|
describe "#before_days" do
|
89
131
|
it "adds a date range query clause" do
|
90
132
|
subject.before_days("foo", 60)
|
91
|
-
expect(subject.clauses).to eq(["foo
|
133
|
+
expect(subject.clauses).to eq([QueryClause.before_days("foo", 60)])
|
92
134
|
end
|
93
135
|
end
|
94
136
|
describe "#before" do
|
95
137
|
it "adds a date range query clause" do
|
96
138
|
subject.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))
|
97
|
-
expect(subject.clauses).to eq(["foo
|
139
|
+
expect(subject.clauses).to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
|
98
140
|
end
|
99
141
|
end
|
100
142
|
end
|
@@ -6,90 +6,111 @@ module Ddr::Index
|
|
6
6
|
subject { described_class.new { id "test:1" } }
|
7
7
|
specify {
|
8
8
|
expect(subject.query.rows).to eq 1
|
9
|
-
expect(subject.query.q).to eq "
|
9
|
+
expect(subject.query.q).to eq QueryClause.id("test:1")
|
10
10
|
}
|
11
11
|
end
|
12
|
-
|
13
12
|
describe "q" do
|
14
13
|
subject { described_class.new { q "foo:bar" } }
|
15
14
|
specify { expect(subject.query.q).to eq "foo:bar" }
|
16
15
|
end
|
17
|
-
|
18
16
|
describe "asc" do
|
19
|
-
subject { described_class.new { asc "foo" } }
|
20
|
-
specify {
|
17
|
+
subject { described_class.new { asc "foo", "bar" } }
|
18
|
+
specify {
|
19
|
+
expect(subject.query.sort).to eq [SortOrder.asc("foo"), SortOrder.asc("bar")]
|
20
|
+
}
|
21
21
|
end
|
22
|
-
|
23
22
|
describe "desc" do
|
24
|
-
subject { described_class.new { desc "foo" } }
|
25
|
-
specify {
|
23
|
+
subject { described_class.new { desc "foo", "bar" } }
|
24
|
+
specify {
|
25
|
+
expect(subject.query.sort).to eq [SortOrder.desc("foo"), SortOrder.desc("bar")]
|
26
|
+
}
|
26
27
|
end
|
27
|
-
|
28
28
|
describe "filter" do
|
29
29
|
subject { described_class.new { filter Filter.where("foo"=>"bar") } }
|
30
30
|
specify { expect(subject.query.filters).to eq [Filter.where("foo"=>"bar")] }
|
31
31
|
end
|
32
|
-
|
32
|
+
describe "filters" do
|
33
|
+
subject {
|
34
|
+
described_class.new { filters Filter.where("foo"=>"bar"), Filter.where("bing"=>"bang") }
|
35
|
+
}
|
36
|
+
specify {
|
37
|
+
expect(subject.query.filters).to eq([Filter.where("foo"=>"bar"),
|
38
|
+
Filter.where("bing"=>"bang")
|
39
|
+
])
|
40
|
+
}
|
41
|
+
end
|
33
42
|
describe "field" do
|
34
43
|
subject { described_class.new { field "foo", "bar" } }
|
35
44
|
specify { expect(subject.query.fields).to include("foo", "bar") }
|
36
45
|
end
|
37
|
-
|
38
46
|
describe "fields" do
|
39
47
|
subject { described_class.new { fields "foo", "bar" } }
|
40
48
|
specify { expect(subject.query.fields).to include("foo", "bar") }
|
41
49
|
end
|
42
|
-
|
43
50
|
describe "sort" do
|
44
51
|
subject { described_class.new { sort "foo"=>"asc", "bar"=>"desc" } }
|
45
|
-
specify {
|
52
|
+
specify {
|
53
|
+
expect(subject.query.sort).to eq([SortOrder.new(field: "foo", order: "asc"),
|
54
|
+
SortOrder.new(field: "bar", order: "desc")
|
55
|
+
])
|
56
|
+
}
|
46
57
|
end
|
47
|
-
|
48
58
|
describe "order_by" do
|
49
59
|
subject { described_class.new { order_by "foo"=>"asc", "bar"=>"desc" } }
|
50
60
|
specify { expect(subject.query.sort).to eq [SortOrder.new(field: "foo", order: "asc"), SortOrder.new(field: "bar", order: "desc")] }
|
51
61
|
end
|
52
|
-
|
53
62
|
describe "limit" do
|
54
63
|
subject { described_class.new { limit 5 } }
|
55
64
|
specify { expect(subject.query.rows).to eq 5 }
|
56
65
|
end
|
57
|
-
|
58
66
|
describe "rows" do
|
59
67
|
subject { described_class.new { rows 5 } }
|
60
68
|
specify { expect(subject.query.rows).to eq 5 }
|
61
69
|
end
|
62
|
-
|
63
70
|
describe "raw" do
|
64
71
|
subject { described_class.new { raw "foo:bar" } }
|
65
72
|
specify { expect(subject.query.filters).to eq [Filter.raw("foo:bar")] }
|
66
73
|
end
|
67
|
-
|
68
74
|
describe "where" do
|
69
75
|
subject { described_class.new { where "foo"=>"bar" } }
|
70
76
|
specify { expect(subject.query.filters).to eq [Filter.where("foo"=>"bar")] }
|
71
77
|
end
|
72
|
-
|
73
78
|
describe "absent" do
|
74
79
|
subject { described_class.new { absent "foo" } }
|
75
80
|
specify { expect(subject.query.filters).to eq [Filter.absent("foo")] }
|
76
81
|
end
|
77
|
-
|
78
82
|
describe "present" do
|
79
83
|
subject { described_class.new { present "foo" } }
|
80
84
|
specify { expect(subject.query.filters).to eq [Filter.present("foo")] }
|
81
85
|
end
|
82
|
-
|
83
86
|
describe "before" do
|
84
|
-
subject {
|
85
|
-
|
87
|
+
subject {
|
88
|
+
described_class.new { before "foo", DateTime.parse("2015-12-14T20:40:06Z") }
|
89
|
+
}
|
90
|
+
specify {
|
91
|
+
expect(subject.query.filters).to eq [Filter.before("foo", DateTime.parse("2015-12-14T20:40:06Z"))]
|
92
|
+
}
|
86
93
|
end
|
87
|
-
|
88
94
|
describe "before_days" do
|
89
95
|
subject { described_class.new { before_days "foo", 7 } }
|
90
96
|
specify { expect(subject.query.filters).to eq [Filter.before_days("foo", 7)] }
|
91
97
|
end
|
92
98
|
end
|
93
99
|
|
100
|
+
describe "using static filters" do
|
101
|
+
describe "has_content" do
|
102
|
+
before { subject.has_content }
|
103
|
+
specify { expect(subject.query.filters).to eq [Filter.has_content] }
|
104
|
+
end
|
105
|
+
describe "is_governed_by" do
|
106
|
+
before { subject.is_governed_by "test:1" }
|
107
|
+
specify { expect(subject.query.filters).to eq [Filter.is_governed_by("test:1")] }
|
108
|
+
end
|
109
|
+
describe "is_governed_by" do
|
110
|
+
before { subject.is_member_of_collection "test:1" }
|
111
|
+
specify { expect(subject.query.filters).to eq [Filter.is_member_of_collection("test:1")] }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
94
115
|
end
|
95
116
|
end
|