ddr-models 2.4.12 → 2.4.13

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 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