-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfield.rb
More file actions
110 lines (85 loc) · 3.31 KB
/
field.rb
File metadata and controls
110 lines (85 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
require 'berkeley_library/av/constants'
require 'berkeley_library/av/marc/util'
require 'berkeley_library/av/metadata/value'
require 'marc/spec'
module BerkeleyLibrary
module AV
class Metadata
class Field
include AV::Marc::Util
include Comparable
# ------------------------------------------------------------
# Constants
SPEC_TAG_RE = /^([0-9a-z.]{3})/
# ------------------------------------------------------------
# Accessors
attr_reader :order, :label, :tag, :spec, :query, :subfields_separator, :subfield_order
# ------------------------------------------------------------
# Initializer
# rubocop:disable Metrics/ParameterLists
def initialize(order:, label:, spec:, tag: nil, subfields_separator: ' ', subfield_order: [])
@order = order
@label = label
@spec = spec
@query = MARC::Spec.parse_query(spec)
@tag = tag || query.tag_str
@subfields_separator = subfields_separator
@subfield_order = subfield_order
end
# rubocop:enable Metrics/ParameterLists
# ------------------------------------------------------------
# Public methods
def value_from(marc_record)
results = MARC::Spec.execute_query(query, marc_record)
subfield_groups = subfield_groups_from_result(results)
Value.value_for(self, subfield_groups)
end
def same_metadata?(other)
raise ArgumentError, "Not a #{class_name(self)}: #{other}" unless other.is_a?(Field)
%i[tag query subfields_separator subfield_order].all? do |attr|
other.respond_to?(attr) && send(attr) == other.send(attr)
end
end
# ------------------------------
# Object
def to_s
"#{order}. #{query} #{label.inspect}".tap do |str|
str << " #{subfields_separator.inspect}" unless subfields_separator == ' '
str << " $#{subfield_order.join('$')}" unless subfield_order.empty?
end
end
def inspect
"#<#{class_name(self)} #{self}>"
end
def hash
sort_attrs.map { |a| send(a) }.hash
end
# ------------------------------
# Comparable
def <=>(other)
compare_by_attributes(self, other, *sort_attrs)
end
# ------------------------------------------------------------
# Private
private
def sort_attrs
%i[order tag query subfields_separator label subfield_order]
end
def subfield_groups_from_result(marc_result)
if marc_result.is_a?(Array)
return [] if marc_result.empty?
return marc_result.map { |r| subfield_groups_from_result(r) }.flatten unless marc_result[0].is_a?(MARC::Subfield)
end
subfields = subfields_from_result(marc_result)
group_subfields(subfields, order: subfield_order)
end
def subfields_from_result(marc_result)
return marc_result if marc_result.is_a?(Array) && marc_result[0].is_a?(MARC::Subfield)
return [marc_result] if marc_result.is_a?(MARC::Subfield)
return [] unless marc_result.respond_to?(:subfields)
marc_result.subfields
end
end
end
end
end