ddr-models 2.4.12 → 2.4.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe3c3a2916bd8e30cc51399f093248fc985a1e15
4
- data.tar.gz: d69c882f8ae41711e03e300fa5d8ace5289e969f
3
+ metadata.gz: 7e305b209128c60e1cf1a0231c117686f834f491
4
+ data.tar.gz: c4fa26a45ebf460c892c9e5770dc2b10f2a326db
5
5
  SHA512:
6
- metadata.gz: e78d004f27dfba444dab593e87935a4ec38f20efcad6607ab6266f585e7306790bca55a079e7a7522f7b7cdc7cc737fdb468d1c146b4d198dcc53e19f3495890
7
- data.tar.gz: b84791fba767c9599d84fba408f9b0e79bdcb268263aeea8644b32d716f171e2620d9f97f2e550002dff225b0a4991f05b12b73f67a26daf938ca6d4fffae5de
6
+ metadata.gz: ddd8c567e7ec34286dc13eba223a0dedb0b0db7773196b8cecbfa179c4e1c8cc44e6794692fd50deabf9afc37e116e6a35068b2b3fc6b13d525d6425c4201b76
7
+ data.tar.gz: a8139759bcd54585aa374f987598a8cdbfc27fabacb914ea841c980e271e384b1273ddd08d40c12f7724e3d836881435f9e09e40214dee42004f9a1ceff60c9d
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
33
33
  s.add_dependency "cancancan", "~> 1.12"
34
34
  s.add_dependency "ddr-antivirus", "~> 2.1.1"
35
35
  s.add_dependency "virtus", "~> 1.0.5"
36
- s.add_dependency "hashie", "~> 3.4.3"
36
+ s.add_dependency "hashie", "~> 3.4", "< 3.4.4"
37
37
 
38
38
  s.add_development_dependency "bundler", "~> 1.11"
39
39
  s.add_development_dependency "rake"
@@ -4,14 +4,12 @@ module Ddr
4
4
 
5
5
  autoload :AbstractQueryResult
6
6
  autoload :Connection
7
- autoload :CSVOptions
8
7
  autoload :CSVQueryResult
9
8
  autoload :DocumentBuilder
10
9
  autoload :Field
11
10
  autoload :FieldAttribute
12
11
  autoload :Fields
13
12
  autoload :Filter
14
- autoload :Filters
15
13
  autoload :LegacyLicenseFields
16
14
  autoload :Query
17
15
  autoload :QueryBuilder
@@ -19,7 +17,6 @@ module Ddr
19
17
  autoload :QueryParams
20
18
  autoload :QueryResult
21
19
  autoload :Response
22
- autoload :SolrCSVOptions
23
20
  autoload :SortOrder
24
21
  autoload :UniqueKeyField
25
22
 
@@ -2,16 +2,15 @@ module Ddr::Index
2
2
  class AbstractQueryResult
3
3
  include Enumerable
4
4
 
5
- attr_reader :query, :conn
5
+ attr_reader :query
6
6
  delegate :params, to: :query
7
7
 
8
8
  def initialize(query)
9
9
  @query = query.dup.freeze
10
- @conn = Connection.new
11
10
  end
12
11
 
13
12
  def count
14
- response = conn.select(params, rows: 0)
13
+ response = Connection.select(params, rows: 0)
15
14
  response.num_found
16
15
  end
17
16
 
@@ -1,17 +1,36 @@
1
+ require "rsolr"
2
+ require "forwardable"
3
+
1
4
  module Ddr::Index
2
- class Connection < SimpleDelegator
5
+ #
6
+ # Wraps an RSolr connection
7
+ #
8
+ class Connection
3
9
 
4
- def initialize
5
- super RSolr.connect(ActiveFedora.solr_config)
6
- end
10
+ module Methods
11
+ extend Forwardable
7
12
 
8
- def select(params, extra={})
9
- Response.new get("select", params: params.merge(extra))
10
- end
13
+ delegate [:get, :paginate] => :solr
14
+
15
+ def solr
16
+ RSolr.connect(ActiveFedora.solr_config)
17
+ end
11
18
 
12
- def page(*args)
13
- Response.new paginate(*args)
19
+ def select(params, extra={})
20
+ Response.new get("select", params: params.merge(extra))
21
+ end
22
+
23
+ def page(*args)
24
+ Response.new paginate(*args)
25
+ end
26
+
27
+ def count(params)
28
+ select(params, rows: 0).num_found
29
+ end
14
30
  end
15
31
 
32
+ extend Methods
33
+ include Methods
34
+
16
35
  end
17
36
  end
@@ -3,65 +3,65 @@ require "csv"
3
3
  module Ddr::Index
4
4
  class CSVQueryResult < AbstractQueryResult
5
5
 
6
- MAX_ROWS = 10**8
7
- MV_SEP = ";"
6
+ MAX_ROWS = 10**8 # Just set to a really high number :)
7
+ CSV_MV_SEPARATOR = ";"
8
8
 
9
- attr_reader :mv_sep
9
+ delegate :headers, :to_s, :to_csv, to: :table
10
10
 
11
- delegate :read, :each, to: :csv
12
-
13
- def initialize(query, mv_sep: MV_SEP)
14
- super(query)
15
- @mv_sep = mv_sep
11
+ def delete_empty_columns!
12
+ table.by_col!.delete_if { |c, vals| vals.all?(&:nil?) }
16
13
  end
17
14
 
18
- def csv
19
- CSV.new(data, csv_opts.to_h)
15
+ def each(&block)
16
+ table.by_row!.each(&block)
20
17
  end
21
18
 
22
- def to_s
23
- read.to_csv
19
+ def [](index_or_header)
20
+ table.by_col_or_row![index_or_header]
24
21
  end
25
22
 
26
- def rows
27
- query.rows || MAX_ROWS
23
+ def table
24
+ @table ||= CSV.parse(data, csv_opts)
28
25
  end
29
26
 
30
27
  def csv_opts
31
- @csv_opts ||= CSVOptions.new(headers: csv_headers)
28
+ { headers: csv_headers,
29
+ return_headers: false,
30
+ write_headers: true,
31
+ }
32
32
  end
33
33
 
34
34
  def solr_csv_opts
35
- @solr_csv_opts ||= SolrCSVOptions.new(col_sep: csv_opts.col_sep,
36
- quote_char: csv_opts.quote_char,
37
- header: solr_csv_header,
38
- mv_sep: mv_sep,
39
- rows: rows)
35
+ { "csv.mv.separator" => CSV_MV_SEPARATOR,
36
+ "csv.header" => solr_csv_header?,
37
+ "rows" => solr_csv_rows,
38
+ "wt" => "csv",
39
+ }
40
40
  end
41
41
 
42
- def headers
43
- @headers ||= query.fields.map(&:heading)
42
+ def query_field_headings
43
+ query.fields.map { |f| f.respond_to?(:heading) ? f.heading : f.to_s }
44
44
  end
45
45
 
46
46
  def csv_headers
47
- if headers.empty?
48
- :first_row
49
- else
50
- headers
51
- end
47
+ query.fields.empty? ? :first_row : query_field_headings
52
48
  end
53
49
 
54
- def solr_csv_header
50
+ def solr_csv_header?
55
51
  csv_headers == :first_row
56
52
  end
57
53
 
54
+ def solr_csv_rows
55
+ query.rows || MAX_ROWS
56
+ end
57
+
58
58
  def solr_csv_params
59
- params.merge solr_csv_opts.params
59
+ params.merge(solr_csv_opts)
60
60
  end
61
61
 
62
62
  def data
63
- raw = conn.get("select", params: solr_csv_params)
64
- raw.gsub(/\\#{mv_sep}/, mv_sep)
63
+ raw = Connection.get("select", params: solr_csv_params)
64
+ raw.gsub(/\\#{CSV_MV_SEPARATOR}/, CSV_MV_SEPARATOR)
65
65
  end
66
66
 
67
67
  end
@@ -57,6 +57,16 @@ module Ddr::Index
57
57
  self.clauses << QueryClause.before_days(field, value)
58
58
  self
59
59
  end
60
+
61
+ def join(**args)
62
+ self.clauses << QueryClause.join(**args)
63
+ self
64
+ end
65
+
66
+ def regexp(field, value)
67
+ self.clauses << QueryClause.regexp(field, value)
68
+ self
69
+ end
60
70
  end
61
71
 
62
72
  module ClassMethods
@@ -68,16 +78,16 @@ module Ddr::Index
68
78
  model "Component", "Attachment", "Target"
69
79
  end
70
80
 
71
- def is_governed_by(object_or_id)
72
- term is_governed_by: internal_uri(object_or_id)
81
+ def is_governed_by(arg)
82
+ term is_governed_by: get_uri(arg)
73
83
  end
74
84
 
75
- def is_member_of_collection(object_or_id)
76
- term is_member_of_collection: internal_uri(object_or_id)
85
+ def is_member_of_collection(arg)
86
+ term is_member_of_collection: get_uri(arg)
77
87
  end
78
88
 
79
- def is_part_of(object_or_id)
80
- term is_part_of: internal_uri(object_or_id)
89
+ def is_part_of(arg)
90
+ term is_part_of: get_uri(arg)
81
91
  end
82
92
 
83
93
  def model(*models)
@@ -86,11 +96,14 @@ module Ddr::Index
86
96
 
87
97
  private
88
98
 
89
- def internal_uri(object_or_id)
90
- if object_or_id.respond_to?(:internal_uri)
91
- object_or_id.internal_uri
99
+ def get_uri(arg)
100
+ case arg
101
+ when ActiveFedora::Base
102
+ arg.internal_uri
103
+ when String
104
+ arg.start_with?("info:fedora/") ? arg : "info:fedora/#{arg}"
92
105
  else
93
- ActiveFedora::Base.internal_uri(object_or_id)
106
+ raise TypeError, "Argument must be a String or ActiveFedora::Base instance: #{arg.class}"
94
107
  end
95
108
  end
96
109
 
@@ -5,6 +5,7 @@ module Ddr::Index
5
5
  class Query
6
6
  include Virtus.model
7
7
  extend Forwardable
8
+ extend Deprecation
8
9
 
9
10
  attribute :q, String
10
11
  attribute :fields, Array[FieldAttribute], default: [ ]
@@ -12,9 +13,15 @@ module Ddr::Index
12
13
  attribute :sort, Array[String], default: [ ]
13
14
  attribute :rows, Integer
14
15
 
15
- delegate [:count, :docs, :pids, :each_pid, :all] => :result
16
+ delegate [:count, :docs, :ids, :each_id, :all] => :result
16
17
  delegate :params => :query_params
17
18
 
19
+ def self.build(*args, &block)
20
+ new.tap do |query|
21
+ query.build(*args, &block)
22
+ end
23
+ end
24
+
18
25
  def initialize(**args, &block)
19
26
  super(**args)
20
27
  if block_given?
@@ -31,12 +38,22 @@ module Ddr::Index
31
38
  URI.encode_www_form(params)
32
39
  end
33
40
 
41
+ def pids
42
+ Deprecation.warn(QueryResult, "`pids` is deprecated; use `ids` instead.")
43
+ ids
44
+ end
45
+
46
+ def each_pid(&block)
47
+ Deprecation.warn(QueryResult, "`each_pid` is deprecated; use `each_id` instead.")
48
+ each_id(&block)
49
+ end
50
+
34
51
  def result
35
52
  QueryResult.new(self)
36
53
  end
37
54
 
38
- def csv(**opts)
39
- CSVQueryResult.new(self, **opts)
55
+ def csv
56
+ CSVQueryResult.new(self)
40
57
  end
41
58
 
42
59
  def filter_clauses
@@ -47,10 +64,19 @@ module Ddr::Index
47
64
  QueryParams.new(self)
48
65
  end
49
66
 
50
- def build(&block)
51
- QueryBuilder.new(self, &block)
67
+ def build(*args, &block)
68
+ QueryBuilder.new(self, *args, &block)
52
69
  self
53
70
  end
54
71
 
72
+ def ==(other)
73
+ other.instance_of?(self.class) &&
74
+ other.q == self.q &&
75
+ other.fields == self.fields &&
76
+ other.filters == self.filters &&
77
+ other.rows == self.rows &&
78
+ other.sort == self.sort
79
+ end
80
+
55
81
  end
56
82
  end
@@ -28,9 +28,6 @@ module Ddr::Index
28
28
  #
29
29
  # See also: asc, order_by
30
30
  #
31
- # id [doc_id]
32
- # For selecting a single document by ID.
33
- #
34
31
  # filter [filter1], ...
35
32
  # Adds filters to the query.
36
33
  #
@@ -48,6 +45,12 @@ module Ddr::Index
48
45
  # fields [field], ...
49
46
  # Alias for: field
50
47
  #
48
+ # id [doc_id]
49
+ # For selecting a single document by ID.
50
+ #
51
+ # join [from: {field1}, to: {field2}, where: {condition}]
52
+ # Adds a Solr join clause (see https://wiki.apache.org/solr/Join)
53
+ #
51
54
  # limit [int]
52
55
  # Limits the number of documents returned by the query.
53
56
  #
@@ -74,6 +77,11 @@ module Ddr::Index
74
77
  # raw [clause1], ...
75
78
  # Adds a filter of "raw" query clauses (i.e., pre-constructed).
76
79
  #
80
+ # regexp [field], [regexp]
81
+ # Adds a filter selecting documents where the field has a value
82
+ # matching the regular expression.
83
+ # Slashes (/) in the regexp will be escaped as required by Solr.
84
+ #
77
85
  # rows [int]
78
86
  # Alias for: limit
79
87
  #
@@ -91,24 +99,12 @@ module Ddr::Index
91
99
  #
92
100
  class QueryBuilder
93
101
 
94
- # Builds a Query object
95
- # @yield [builder] a new QueryBuilder instance.
96
- # @return [Query]
97
- def self.build
98
- Deprecation.warn(self,
99
- "`Ddr::Index::QueryBuilder.build` is deprecated and will be removed in ddr-models 3.0." \
100
- " Use `Ddr::Index::QueryBuilder.new` instead.")
101
- builder = new
102
- yield builder
103
- builder.query
104
- end
105
-
106
102
  attr_reader :query
107
103
 
108
- def initialize(query = nil, &block)
109
- @query = query || Query.new
104
+ def initialize(*args, &block)
105
+ @query = args.first.is_a?(Query) ? args.shift : Query.new
110
106
  if block_given?
111
- instance_eval &block
107
+ instance_exec(*args, &block)
112
108
  end
113
109
  end
114
110
 
@@ -146,11 +142,6 @@ module Ddr::Index
146
142
  # @param orderings [Hash<Field, String>]
147
143
  # @return [QueryBuilder] self
148
144
  def order_by(*orderings)
149
- unless orderings.first.is_a? Hash
150
- Deprecation.warn(QueryBuilder, "`order_by` will require a hash of orderings in ddr-models 3.0.")
151
- field, order = orderings
152
- return order_by(field => order)
153
- end
154
145
  query.sort += orderings.first.map { |field, order| SortOrder.new(field: field, order: order) }
155
146
  self
156
147
  end
@@ -12,6 +12,7 @@ module Ddr::Index
12
12
  STANDARD_QUERY = "%{field}:%{value}"
13
13
  NEGATIVE_QUERY = "-%{field}:%{value}"
14
14
  DISJUNCTION = "{!lucene q.op=OR df=%{field}}%{value}"
15
+ REGEXP_QUERY = "%{field}:/%{value}/"
15
16
 
16
17
  values do
17
18
  attribute :field, FieldAttribute
@@ -29,7 +30,6 @@ module Ddr::Index
29
30
  end
30
31
 
31
32
  class << self
32
-
33
33
  def quote(value)
34
34
  # Derived from Blacklight::Solr::SearchBuilderBehavior#solr_param_quote
35
35
  unless value =~ /\A[a-zA-Z0-9$_\-\^]+\z/
@@ -75,6 +75,16 @@ module Ddr::Index
75
75
  new(field: field, value: value, template: DISJUNCTION)
76
76
  end
77
77
 
78
+ # Builds a Solr join clause
79
+ # @see https://wiki.apache.org/solr/Join
80
+ def join(from:, to:, where:)
81
+ field, value = where.to_a.first
82
+ from_field = FieldAttribute.coerce(from)
83
+ to_field = FieldAttribute.coerce(to)
84
+ template = "{!join from=#{from_field} to=#{to_field}}%{field}:%{value}"
85
+ new(field: field, value: value, template: template, quote_value: true)
86
+ end
87
+
78
88
  # Builds a query clause to filter where date field value is earlier than a date/time value.
79
89
  def before(field, value)
80
90
  new(field: field, value: "[* TO %s]" % Ddr::Utils.solr_date(value))
@@ -91,6 +101,11 @@ module Ddr::Index
91
101
  new(field: field, value: value, template: TERM_QUERY)
92
102
  end
93
103
 
104
+ # Builds a regular expression query clause
105
+ def regexp(field, value)
106
+ val = value.gsub(/\//, "\\/")
107
+ new(field: field, value: val, template: REGEXP_QUERY)
108
+ end
94
109
  end
95
110
 
96
111
  end
@@ -1,5 +1,6 @@
1
1
  module Ddr::Index
2
2
  class QueryResult < AbstractQueryResult
3
+ extend Deprecation
3
4
 
4
5
  PAGE_SIZE = 1000
5
6
 
@@ -14,7 +15,7 @@ module Ddr::Index
14
15
  end
15
16
 
16
17
  def each_unpaginated(&block)
17
- conn.select(params).docs.each(&block)
18
+ Connection.select(params).docs.each(&block)
18
19
  end
19
20
 
20
21
  def each_paginated(&block)
@@ -22,15 +23,31 @@ module Ddr::Index
22
23
  end
23
24
 
24
25
  def pids
26
+ Deprecation.warn(QueryResult,
27
+ "`pids` is deprecated; use `ids` instead." \
28
+ " (called from #{caller.first})"
29
+ )
30
+ ids
31
+ end
32
+
33
+ def ids
25
34
  Enumerator.new do |e|
26
35
  each do |doc|
27
- e << doc[Fields::PID]
36
+ e << doc[Fields::ID]
28
37
  end
29
38
  end
30
39
  end
31
40
 
32
41
  def each_pid(&block)
33
- pids.each(&block)
42
+ Deprecation.warn(QueryResult,
43
+ "`each_pid` is deprecated; use `each_id` instead." \
44
+ " (called from #{caller.first})"
45
+ )
46
+ each_id(&block)
47
+ end
48
+
49
+ def each_id(&block)
50
+ ids.each(&block)
34
51
  end
35
52
 
36
53
  def docs
@@ -41,6 +58,21 @@ module Ddr::Index
41
58
  end
42
59
  end
43
60
 
61
+ def objects
62
+ Enumerator.new do |e|
63
+ each_id do |id|
64
+ e << ActiveFedora::Base.find(id)
65
+ end
66
+ end
67
+ end
68
+
69
+ def facet_fields
70
+ response = Connection.select(params, rows: 0)
71
+ response.facet_fields.each_with_object({}) do |(field, values), memo|
72
+ memo[field] = Hash[*values]
73
+ end
74
+ end
75
+
44
76
  def all
45
77
  to_a
46
78
  end
@@ -62,7 +94,7 @@ module Ddr::Index
62
94
  def page(num)
63
95
  page_params = params.dup
64
96
  page_size = page_params.delete(:rows) || PAGE_SIZE
65
- response = conn.page num, page_size, "select", params: page_params
97
+ response = Connection.page(num, page_size, "select", params: page_params)
66
98
  response.docs
67
99
  end
68
100
 
@@ -1,12 +1,29 @@
1
+ require "delegate"
2
+
1
3
  module Ddr::Index
4
+ #
5
+ # Wraps an index query response
6
+ #
2
7
  class Response < SimpleDelegator
3
8
 
4
9
  def docs
5
- self["response"]["docs"]
10
+ response["docs"]
6
11
  end
7
12
 
8
13
  def num_found
9
- self["response"]["numFound"].to_i
14
+ response["numFound"].to_i
15
+ end
16
+
17
+ def facet_counts
18
+ self["facet_counts"] || {}
19
+ end
20
+
21
+ def facet_fields
22
+ facet_counts["facet_fields"] || {}
23
+ end
24
+
25
+ def response
26
+ self["response"]
10
27
  end
11
28
 
12
29
  end
@@ -12,8 +12,7 @@ module Ddr::Models
12
12
 
13
13
  module ClassMethods
14
14
  def find(pid_or_uri)
15
- pid = pid_or_uri.sub(/\Ainfo:fedora\//, "")
16
- query = Ddr::Index::QueryBuilder.build { |q| q.id(pid) }
15
+ query = Ddr::Index::Query.new { id pid_or_uri.sub(/\Ainfo:fedora\//, "") }
17
16
  if doc = query.docs.first
18
17
  return doc
19
18
  end
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "2.4.12"
3
+ VERSION = "2.4.13"
4
4
  end
5
5
  end
@@ -0,0 +1,44 @@
1
+ module Ddr::Index
2
+ RSpec.describe CSVQueryResult do
3
+
4
+ subject { described_class.new(query) }
5
+
6
+ before do
7
+ Item.create(title: ["Testing 1"],
8
+ identifier: ["test1"],
9
+ description: ["The process of eliminating errors."])
10
+ Item.create(title: ["Testing 2"],
11
+ identifier: ["test2"])
12
+ Item.create(title: ["Testing 3"])
13
+ end
14
+
15
+ let(:query) {
16
+ Ddr::Index::Query.new do
17
+ fields Ddr::Index::Fields::ID
18
+ fields Ddr::Index::Fields.descmd
19
+ end
20
+ }
21
+
22
+ specify {
23
+ expect(subject["title"]).to contain_exactly("Testing 1", "Testing 2", "Testing 3")
24
+ expect(subject["identifier"]).to contain_exactly("test1", "test2", nil)
25
+ expect(subject["description"]).to contain_exactly("The process of eliminating errors.", nil, nil)
26
+ expect(subject["creator"]).to contain_exactly(nil, nil, nil)
27
+ expect(subject.headers).to include("creator")
28
+ expect(subject.to_s).to match(/creator/)
29
+ }
30
+
31
+ describe "#delete_empty_columns!" do
32
+ specify {
33
+ subject.delete_empty_columns!
34
+ expect(subject["title"]).to contain_exactly("Testing 1", "Testing 2", "Testing 3")
35
+ expect(subject["identifier"]).to contain_exactly("test1", "test2", nil)
36
+ expect(subject["description"]).to contain_exactly("The process of eliminating errors.", nil, nil)
37
+ expect(subject["creator"]).to contain_exactly(nil, nil, nil)
38
+ expect(subject.headers).to contain_exactly("pid", "title", "identifier", "description")
39
+ expect(subject.to_s).not_to match(/creator/)
40
+ }
41
+ end
42
+
43
+ end
44
+ end
@@ -37,6 +37,12 @@ module Ddr::Index
37
37
  are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
38
38
  }
39
39
  end
40
+ describe "with a URI" do
41
+ subject { described_class.is_governed_by("info:fedora/test:1") }
42
+ its(:clauses) {
43
+ are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
44
+ }
45
+ end
40
46
  end
41
47
  describe ".is_member_of_collection" do
42
48
  describe "with an object" do
@@ -51,6 +57,32 @@ module Ddr::Index
51
57
  are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
52
58
  }
53
59
  end
60
+ describe "with a URI" do
61
+ subject { described_class.is_member_of_collection("info:fedora/test:1") }
62
+ its(:clauses) {
63
+ are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
64
+ }
65
+ end
66
+ end
67
+ describe ".is_part_of" do
68
+ describe "with an object" do
69
+ subject { described_class.is_part_of(Item.new(pid: "test:1")) }
70
+ its(:clauses) {
71
+ are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
72
+ }
73
+ end
74
+ describe "with an ID" do
75
+ subject { described_class.is_part_of("test:1") }
76
+ its(:clauses) {
77
+ are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
78
+ }
79
+ end
80
+ describe "with a URI" do
81
+ subject { described_class.is_part_of("info:fedora/test:1") }
82
+ its(:clauses) {
83
+ are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
84
+ }
85
+ end
54
86
  end
55
87
  describe ".has_content" do
56
88
  subject { described_class.has_content }
@@ -107,6 +139,20 @@ module Ddr::Index
107
139
  are_expected.to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
108
140
  }
109
141
  end
142
+ describe ".join" do
143
+ subject {
144
+ described_class.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})
145
+ }
146
+ its(:clauses) {
147
+ are_expected.to eq([QueryClause.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})])
148
+ }
149
+ end
150
+ describe ".regexp" do
151
+ subject { described_class.regexp("foo", "foo/bar.*") }
152
+ its(:clauses) {
153
+ are_expected.to eq([QueryClause.regexp("foo", "foo/bar.*")])
154
+ }
155
+ end
110
156
  end
111
157
 
112
158
  describe "API methods" do
@@ -166,6 +212,13 @@ module Ddr::Index
166
212
  expect(subject.clauses).to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
167
213
  end
168
214
  end
215
+ describe "#join" do
216
+ it "adds a join query clause" do
217
+ subject.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})
218
+ expect(subject.clauses).to eq([QueryClause.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})])
219
+ end
220
+ end
221
+
169
222
  end
170
223
 
171
224
  end
@@ -1,6 +1,5 @@
1
1
  module Ddr::Index
2
2
  RSpec.describe QueryBuilder do
3
-
4
3
  describe "DSL" do
5
4
  describe "id" do
6
5
  subject { described_class.new { id "test:1" } }
@@ -95,6 +94,22 @@ module Ddr::Index
95
94
  subject { described_class.new { before_days "foo", 7 } }
96
95
  specify { expect(subject.query.filters).to eq [Filter.before_days("foo", 7)] }
97
96
  end
97
+ describe "join" do
98
+ subject {
99
+ described_class.new do
100
+ join from: :id, to: :collection_uri, where: {admin_set: "dvs"}
101
+ end
102
+ }
103
+ specify {
104
+ expect(subject.query.filters).to eq [Filter.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})]
105
+ }
106
+ end
107
+ describe "regexp" do
108
+ subject { described_class.new { regexp "foo", "foo/bar.*" } }
109
+ specify {
110
+ expect(subject.query.filters).to eq [Filter.regexp("foo", "foo/bar.*")]
111
+ }
112
+ end
98
113
  end
99
114
 
100
115
  describe "using static filters" do
@@ -112,5 +127,14 @@ module Ddr::Index
112
127
  end
113
128
  end
114
129
 
130
+ describe "passing local vars" do
131
+ let(:local_var) { double(bar: "bar") }
132
+ subject {
133
+ described_class.new(local_var) { |foo| asc foo.bar }
134
+ }
135
+ specify {
136
+ expect(subject.query.sort).to eq [SortOrder.asc("bar")]
137
+ }
138
+ end
115
139
  end
116
140
  end
@@ -52,6 +52,16 @@ module Ddr::Index
52
52
  its(:to_s) { is_expected.to eq "{!lucene q.op=OR df=foo}\"Jungle Fever\" bar" }
53
53
  end
54
54
  end
55
+ describe ".join" do
56
+ subject {
57
+ described_class.join(from: :id, to: :collection_uri, where: { admin_set: "dvs"})
58
+ }
59
+ its(:to_s) { is_expected.to eq "{!join from=id to=collection_uri_ssim}admin_set_ssi:dvs" }
60
+ end
61
+ describe ".regexp" do
62
+ subject { described_class.regexp("foo", "foo/bar.*") }
63
+ its(:to_s) { is_expected.to eq "foo:/foo\\/bar.*/" }
64
+ end
55
65
  end
56
66
 
57
67
  end
@@ -1,20 +1,16 @@
1
1
  module Ddr::Index
2
2
  RSpec.describe Query do
3
-
4
- describe "initialized with attributes" do
5
- let(:id) { UniqueKeyField.instance }
6
- let(:foo) { Field.new("foo") }
7
- let(:spam) { Field.new("spam") }
8
- let(:filter) { Filter.where(spam=>"eggs") }
9
- let(:sort_order) { SortOrder.new(field: foo, order: "asc") }
10
- let(:fields) { [id, foo, spam] }
11
-
3
+ describe ".build" do
4
+ let(:local1) { double(value: "foo:bar") }
5
+ let(:local2) { double(value: "foo") }
12
6
  subject {
13
- described_class.new(q: "foo:bar",
14
- filters: [filter],
15
- fields: fields,
16
- sort: sort_order,
17
- rows: 50)
7
+ described_class.build(local1, local2) do |l1, l2|
8
+ q l1.value
9
+ where "spam"=>"eggs"
10
+ fields :id, "foo", "spam"
11
+ asc l2.value
12
+ limit 50
13
+ end
18
14
  }
19
15
 
20
16
  its(:to_s) {
@@ -25,7 +21,52 @@ module Ddr::Index
25
21
  }
26
22
  end
27
23
 
28
- describe "initialized with a block" do
24
+ describe "initialization" do
25
+ describe "with attributes" do
26
+ let(:id) { UniqueKeyField.instance }
27
+ let(:foo) { Field.new("foo") }
28
+ let(:spam) { Field.new("spam") }
29
+ let(:filter) { Filter.where(spam=>"eggs") }
30
+ let(:sort_order) { SortOrder.new(field: foo, order: "asc") }
31
+ let(:fields) { [id, foo, spam] }
32
+
33
+ subject {
34
+ described_class.new(q: "foo:bar",
35
+ filters: [filter],
36
+ fields: fields,
37
+ sort: sort_order,
38
+ rows: 50)
39
+ }
40
+
41
+ its(:to_s) {
42
+ is_expected.to eq "q=foo%3Abar&fq=spam%3Aeggs&fl=id%2Cfoo%2Cspam&sort=foo+asc&rows=50"
43
+ }
44
+ its(:params) {
45
+ is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["spam:eggs"], sort: "foo asc", rows: 50})
46
+ }
47
+ end
48
+
49
+ describe "with a block" do
50
+ subject {
51
+ described_class.new do
52
+ q "foo:bar"
53
+ where "spam"=>"eggs"
54
+ fields :id, "foo", "spam"
55
+ asc "foo"
56
+ limit 50
57
+ end
58
+ }
59
+
60
+ its(:to_s) {
61
+ is_expected.to eq "q=foo%3Abar&fq=spam%3Aeggs&fl=id%2Cfoo%2Cspam&sort=foo+asc&rows=50"
62
+ }
63
+ its(:params) {
64
+ is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["spam:eggs"], sort: "foo asc", rows: 50})
65
+ }
66
+ end
67
+ end
68
+
69
+ describe "equality" do
29
70
  subject {
30
71
  described_class.new do
31
72
  q "foo:bar"
@@ -35,14 +76,16 @@ module Ddr::Index
35
76
  limit 50
36
77
  end
37
78
  }
38
-
39
- its(:to_s) {
40
- is_expected.to eq "q=foo%3Abar&fq=spam%3Aeggs&fl=id%2Cfoo%2Cspam&sort=foo+asc&rows=50"
41
- }
42
- its(:params) {
43
- is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["spam:eggs"], sort: "foo asc", rows: 50})
44
- }
79
+ let(:other) do
80
+ described_class.new do
81
+ q "foo:bar"
82
+ where "spam"=>"eggs"
83
+ fields :id, "foo", "spam"
84
+ asc "foo"
85
+ limit 50
86
+ end
87
+ end
88
+ it { is_expected.to eq other }
45
89
  end
46
-
47
90
  end
48
91
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddr-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.12
4
+ version: 2.4.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Coble
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-13 00:00:00.000000000 Z
12
+ date: 2016-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -227,14 +227,20 @@ dependencies:
227
227
  requirements:
228
228
  - - "~>"
229
229
  - !ruby/object:Gem::Version
230
- version: 3.4.3
230
+ version: '3.4'
231
+ - - "<"
232
+ - !ruby/object:Gem::Version
233
+ version: 3.4.4
231
234
  type: :runtime
232
235
  prerelease: false
233
236
  version_requirements: !ruby/object:Gem::Requirement
234
237
  requirements:
235
238
  - - "~>"
236
239
  - !ruby/object:Gem::Version
237
- version: 3.4.3
240
+ version: '3.4'
241
+ - - "<"
242
+ - !ruby/object:Gem::Version
243
+ version: 3.4.4
238
244
  - !ruby/object:Gem::Dependency
239
245
  name: bundler
240
246
  requirement: !ruby/object:Gem::Requirement
@@ -473,14 +479,12 @@ files:
473
479
  - lib/ddr/index.rb
474
480
  - lib/ddr/index/abstract_query_result.rb
475
481
  - lib/ddr/index/connection.rb
476
- - lib/ddr/index/csv_options.rb
477
482
  - lib/ddr/index/csv_query_result.rb
478
483
  - lib/ddr/index/document_builder.rb
479
484
  - lib/ddr/index/field.rb
480
485
  - lib/ddr/index/field_attribute.rb
481
486
  - lib/ddr/index/fields.rb
482
487
  - lib/ddr/index/filter.rb
483
- - lib/ddr/index/filters.rb
484
488
  - lib/ddr/index/legacy_license_fields.rb
485
489
  - lib/ddr/index/query.rb
486
490
  - lib/ddr/index/query_builder.rb
@@ -488,7 +492,6 @@ files:
488
492
  - lib/ddr/index/query_params.rb
489
493
  - lib/ddr/index/query_result.rb
490
494
  - lib/ddr/index/response.rb
491
- - lib/ddr/index/solr_csv_options.rb
492
495
  - lib/ddr/index/sort_order.rb
493
496
  - lib/ddr/index/unique_key_field.rb
494
497
  - lib/ddr/jobs.rb
@@ -647,6 +650,7 @@ files:
647
650
  - spec/fixtures/sample.pdf
648
651
  - spec/fixtures/target.png
649
652
  - spec/helpers/models_helper_spec.rb
653
+ - spec/index/csv_query_result_spec.rb
650
654
  - spec/index/fields_spec.rb
651
655
  - spec/index/filter_spec.rb
652
656
  - spec/index/query_builder_spec.rb
@@ -823,6 +827,7 @@ test_files:
823
827
  - spec/fixtures/sample.pdf
824
828
  - spec/fixtures/target.png
825
829
  - spec/helpers/models_helper_spec.rb
830
+ - spec/index/csv_query_result_spec.rb
826
831
  - spec/index/fields_spec.rb
827
832
  - spec/index/filter_spec.rb
828
833
  - spec/index/query_builder_spec.rb
@@ -1,14 +0,0 @@
1
- require "csv"
2
- require "hashie"
3
-
4
- module Ddr::Index
5
- class CSVOptions < Hashie::Dash
6
-
7
- property :headers, default: CSV::DEFAULT_OPTIONS[:headers]
8
- property :return_headers, default: true
9
- property :write_headers, default: true
10
- property :col_sep, default: CSV::DEFAULT_OPTIONS[:col_sep]
11
- property :quote_char, default: CSV::DEFAULT_OPTIONS[:quote_char]
12
-
13
- end
14
- end
@@ -1,26 +0,0 @@
1
- module Ddr::Index
2
- module Filters
3
- extend Deprecation
4
-
5
- def self.is_governed_by(pid)
6
- Deprecation.warn(self,
7
- "`Ddr::Index:Filters.is_governed_by` is deprecated and will be removed in ddr-models 3.0." \
8
- " Use `Ddr::Index::Filter.is_governed_by` instead.")
9
- Filter.is_governed_by(pid)
10
- end
11
-
12
- private
13
-
14
- def self.const_missing(name)
15
- if name == :HAS_CONTENT
16
- Deprecation.warn(self,
17
- "`Ddr::Index::Filters::#{name}` is deprecated and will be removed in ddr-models 3.0." \
18
- " Use `Ddr::Index::Filter.has_content` instead.")
19
- Filter.has_content
20
- else
21
- super
22
- end
23
- end
24
-
25
- end
26
- end
@@ -1,18 +0,0 @@
1
- require "hashie"
2
-
3
- module Ddr::Index
4
- class SolrCSVOptions < Hashie::Trash
5
-
6
- property "csv.header", from: :header, default: false
7
- property "csv.separator", from: :col_sep, default: ","
8
- property "csv.encapsulator", from: :quote_char, default: '"'
9
- property "csv.mv.separator", from: :mv_sep, default: ","
10
- property :wt, default: "csv"
11
- property :rows
12
-
13
- def params
14
- to_h.reject { |k, v| v.nil? }
15
- end
16
-
17
- end
18
- end