zizia 4.0.2.alpha.01 → 4.0.3.alpha.01
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +2 -28
- data/lib/zizia/always_invalid_validator.rb +0 -17
- data/lib/zizia/csv_template.rb +0 -9
- data/lib/zizia/engine.rb +0 -32
- data/lib/zizia/hash_mapper.rb +0 -44
- data/lib/zizia/hyrax/hyrax_basic_metadata_mapper.rb +0 -149
- data/lib/zizia/hyrax/hyrax_default_updater.rb +0 -11
- data/lib/zizia/hyrax/hyrax_delete_files_updater.rb +0 -16
- data/lib/zizia/hyrax/hyrax_metadata_only_updater.rb +0 -58
- data/lib/zizia/hyrax/hyrax_record_importer.rb +0 -247
- data/lib/zizia/hyrax/metadata_only_stack.rb +0 -70
- data/lib/zizia/importer.rb +0 -58
- data/lib/zizia/input_record.rb +0 -65
- data/lib/zizia/metadata_mapper.rb +0 -83
- data/lib/zizia/parser.rb +0 -132
- data/lib/zizia/parsers/csv_parser.rb +0 -45
- data/lib/zizia/record_importer.rb +0 -44
- data/lib/zizia/spec/fakes/fake_parser.rb +0 -22
- data/lib/zizia/spec/shared_examples/a_mapper.rb +0 -32
- data/lib/zizia/spec/shared_examples/a_parser.rb +0 -73
- data/lib/zizia/spec/shared_examples/a_validator.rb +0 -29
- data/lib/zizia/spec.rb +0 -14
- data/lib/zizia/validator.rb +0 -106
- data/lib/zizia/validators/csv_format_validator.rb +0 -26
- data/lib/zizia/validators/title_validator.rb +0 -30
- data/lib/zizia/version.rb +0 -5
- data/lib/zizia.rb +0 -66
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
class MetadataOnlyStack
|
5
|
-
def self.build_stack
|
6
|
-
ActionDispatch::MiddlewareStack.new.tap do |middleware|
|
7
|
-
# Wrap everything in a database transaction, if the save of the resource
|
8
|
-
# fails then roll back any database AdminSetChangeSet
|
9
|
-
middleware.use Hyrax::Actors::TransactionalRequest
|
10
|
-
|
11
|
-
# Ensure you are mutating the most recent version
|
12
|
-
# middleware.use Hyrax::Actors::OptimisticLockValidator
|
13
|
-
|
14
|
-
# Attach files from a URI (for BrowseEverything)
|
15
|
-
# middleware.use Hyrax::Actors::CreateWithRemoteFilesActor
|
16
|
-
|
17
|
-
# Attach files uploaded in the form to the UploadsController
|
18
|
-
# In Californica, for command line import,
|
19
|
-
# we are using the CreateWithFilesActor to attach
|
20
|
-
# local files with a file:// url, not via the UploadsController,
|
21
|
-
# so we never use the CreateWithFilesActor
|
22
|
-
# middleware.use Hyrax::Actors::CreateWithFilesActor
|
23
|
-
|
24
|
-
# Add/remove the resource to/from a collection
|
25
|
-
middleware.use Hyrax::Actors::CollectionsMembershipActor
|
26
|
-
|
27
|
-
# Add/remove to parent work
|
28
|
-
# middleware.use Hyrax::Actors::AddToWorkActor
|
29
|
-
|
30
|
-
# Add/remove children (works or file_sets)
|
31
|
-
# middleware.use Hyrax::Actors::AttachMembersActor
|
32
|
-
|
33
|
-
# Set the order of the children (works or file_sets)
|
34
|
-
# middleware.use Hyrax::Actors::ApplyOrderActor
|
35
|
-
|
36
|
-
# Sets the default admin set if they didn't supply one
|
37
|
-
# middleware.use Hyrax::Actors::DefaultAdminSetActor
|
38
|
-
|
39
|
-
# Decode the private/public/institution on the form into permisisons on
|
40
|
-
# the model
|
41
|
-
# We aren't using this in Californica, we're just setting the visibility
|
42
|
-
# at import time
|
43
|
-
# middleware.use Hyrax::Actors::InterpretVisibilityActor
|
44
|
-
|
45
|
-
# Handles transfering ownership of works from one user to another
|
46
|
-
# We aren't using this in Californica
|
47
|
-
# middleware.use Hyrax::Actors::TransferRequestActor
|
48
|
-
|
49
|
-
# Copies default permissions from the PermissionTemplate to the work
|
50
|
-
# middleware.use Hyrax::Actors::ApplyPermissionTemplateActor
|
51
|
-
|
52
|
-
# Remove attached FileSets when destroying a work
|
53
|
-
# middleware.use Hyrax::Actors::CleanupFileSetsActor
|
54
|
-
|
55
|
-
# Destroys the trophies in the database when the work is destroyed
|
56
|
-
# middleware.use Hyrax::Actors::CleanupTrophiesActor
|
57
|
-
|
58
|
-
# Destroys the feature tag in the database when the work is destroyed
|
59
|
-
# middleware.use Hyrax::Actors::FeaturedWorkActor
|
60
|
-
|
61
|
-
# Persist the metadata changes on the resource
|
62
|
-
middleware.use Hyrax::Actors::ModelActor
|
63
|
-
|
64
|
-
# Start the workflow for this work
|
65
|
-
# middleware.use Hyrax::Actors::InitializeWorkflowActor
|
66
|
-
end
|
67
|
-
end
|
68
|
-
# rubocop:enable Metrics/MethodLength
|
69
|
-
end
|
70
|
-
end
|
data/lib/zizia/importer.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
##
|
5
|
-
# The chief entry point for bulk import of records. `Importer` accepts a
|
6
|
-
# {Parser} on initialization and iterates through its {Parser#records}, importing
|
7
|
-
# each using a given {RecordImporter}.
|
8
|
-
#
|
9
|
-
# @example Importing in bulk from a CSV file
|
10
|
-
# parser = Zizia::Parser.for(file: File.new('path/to/import.csv'))
|
11
|
-
#
|
12
|
-
# Zizia::Importer.new(parser: parser).import if parser.validate
|
13
|
-
#
|
14
|
-
class Importer
|
15
|
-
extend Forwardable
|
16
|
-
|
17
|
-
##
|
18
|
-
# @!attribute [rw] parser
|
19
|
-
# @return [Parser]
|
20
|
-
# @!attribute [rw] record_importer
|
21
|
-
# @return [RecordImporter]
|
22
|
-
attr_accessor :parser, :record_importer
|
23
|
-
|
24
|
-
##
|
25
|
-
# @!method records()
|
26
|
-
# @see Parser#records
|
27
|
-
def_delegator :parser, :records, :records
|
28
|
-
|
29
|
-
##
|
30
|
-
# @param parser [Parser] The parser to use as the source for import
|
31
|
-
# records.
|
32
|
-
# @param record_importer [RecordImporter] An object to handle import of
|
33
|
-
# each record
|
34
|
-
def initialize(parser:, record_importer: RecordImporter.new)
|
35
|
-
self.parser = parser
|
36
|
-
self.record_importer = record_importer
|
37
|
-
end
|
38
|
-
|
39
|
-
# Do not attempt to run an import if there are no records. Instead, just write to the log.
|
40
|
-
def no_records_message
|
41
|
-
Rails.logger.error "[zizia] event: empty_import, batch_id: #{record_importer.batch_id}"
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# Import each record in {#records}.
|
46
|
-
#
|
47
|
-
# @return [void]
|
48
|
-
def import
|
49
|
-
no_records_message && return unless records.count.positive?
|
50
|
-
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
51
|
-
Rails.logger.info "[zizia] event: start_import, batch_id: #{record_importer.batch_id}, expecting to import #{records.count} records."
|
52
|
-
records.each { |record| record_importer.import(record: record) }
|
53
|
-
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
54
|
-
elapsed_time = end_time - start_time
|
55
|
-
Rails.logger.info "[zizia] event: finish_import, batch_id: #{record_importer.batch_id}, successful_record_count: #{record_importer.success_count}, failed_record_count: #{record_importer.failure_count}, elapsed_time: #{elapsed_time}, elapsed_time_per_record: #{elapsed_time / records.count}"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/lib/zizia/input_record.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
##
|
5
|
-
# @example Building an importer with the factory
|
6
|
-
# record = InputRecord.from({some: :metadata}, mapper: MyMapper.new)
|
7
|
-
# record.some # => :metadata
|
8
|
-
#
|
9
|
-
class InputRecord
|
10
|
-
##
|
11
|
-
# @!attribute [rw] mapper
|
12
|
-
# @return [#map_fields]
|
13
|
-
attr_accessor :mapper
|
14
|
-
|
15
|
-
##
|
16
|
-
# @param mapper [#map_fields]
|
17
|
-
def initialize(mapper: Zizia.config.metadata_mapper_class.new)
|
18
|
-
self.mapper = mapper
|
19
|
-
end
|
20
|
-
|
21
|
-
class << self
|
22
|
-
##
|
23
|
-
# @param metadata [Object]
|
24
|
-
# @param mapper [#map_fields]
|
25
|
-
#
|
26
|
-
# @return [InputRecord] an input record mapping metadata with the given
|
27
|
-
# mapper
|
28
|
-
def from(metadata:, mapper: Zizia.config.metadata_mapper_class.new)
|
29
|
-
mapper.metadata = metadata
|
30
|
-
new(mapper: mapper)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
##
|
35
|
-
# @return [Hash<Symbol, Object>]
|
36
|
-
def attributes
|
37
|
-
mapper.fields.each_with_object({}) do |field, attrs|
|
38
|
-
attrs[field] = public_send(field)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
##
|
43
|
-
# @return [String, nil] an identifier for the representative file; nil if
|
44
|
-
# none is given.
|
45
|
-
def representative_file
|
46
|
-
return mapper.representative_file if
|
47
|
-
mapper.respond_to?(:representative_file)
|
48
|
-
|
49
|
-
nil
|
50
|
-
end
|
51
|
-
|
52
|
-
##
|
53
|
-
# Respond to methods matching mapper fields
|
54
|
-
def method_missing(method_name, *args, &block)
|
55
|
-
return super unless mapper.field?(method_name)
|
56
|
-
mapper.public_send(method_name)
|
57
|
-
end
|
58
|
-
|
59
|
-
##
|
60
|
-
# @see #method_missing
|
61
|
-
def respond_to_missing?(method_name, include_private = false)
|
62
|
-
mapper.field?(method_name) || super
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
##
|
5
|
-
# A null/base mapper that maps no fields.
|
6
|
-
#
|
7
|
-
# Real mapper implementations need to provide `#fields`, enumerating over
|
8
|
-
# `Symbols` that represent the fields on the target object (e.g. an
|
9
|
-
# `ActiveFedora::Base`/`Hyrax::WorkBehavior`) that the mapper can handle.
|
10
|
-
# For each field in `#fields`, the mapper must respond to a matching method
|
11
|
-
# (i.e. `:title` => `#title`), and return the value(s) that should be set to
|
12
|
-
# the target's attributes upon mapping.
|
13
|
-
#
|
14
|
-
# To ease the implementation of field methods, this base class provides
|
15
|
-
# a `#method_missing` that forwards missing method names to a `#map_field`
|
16
|
-
# method. `#map_field` can be implemented to provide a generalized field
|
17
|
-
# mapping when a common pattern will be used for many methods. Callers should
|
18
|
-
# avoid relying on this protected method directly, since mappers may implement
|
19
|
-
# individual field methods in any other way (e.g. `def title; end`) to route
|
20
|
-
# around `#map_field`. Implementations are also free to override
|
21
|
-
# `#method_missing` if desired.
|
22
|
-
#
|
23
|
-
# Mappers generally operate over some input `#metadata`. Example metadata
|
24
|
-
# types that mappers could be implemented over include `Hash`, `CSV`, `XML`,
|
25
|
-
# `RDF::Graph`, etc...; mappers are free to interpret or ignore the contents
|
26
|
-
# of their underlying metadata data structures at their leisure. Values for
|
27
|
-
# fields are /usually/ derived from the `#metadata`, but can also be generated
|
28
|
-
# from complex logic or even hard-coded.
|
29
|
-
#
|
30
|
-
# @example Using a MetadataMapper
|
31
|
-
# mapper = MyMapper.new
|
32
|
-
# mapper.metadata = some_metadata_object
|
33
|
-
# mapper.fields # => [:title, :author, :description]
|
34
|
-
#
|
35
|
-
# mapper.title # => 'Some Title'
|
36
|
-
#
|
37
|
-
# mapper.fields.map { |field| mapper.send(field) }
|
38
|
-
#
|
39
|
-
# @see ImportRecord#attributes for the canonical usage of a `MetadataMapper`.
|
40
|
-
# @see HashMapper for an example implementation with dynamically generated
|
41
|
-
# fields
|
42
|
-
class MetadataMapper
|
43
|
-
##
|
44
|
-
# @!attribute [rw] metadata
|
45
|
-
# @return [Object]
|
46
|
-
attr_accessor :metadata
|
47
|
-
|
48
|
-
##
|
49
|
-
# @param name [Symbol]
|
50
|
-
#
|
51
|
-
# @return [Boolean]
|
52
|
-
def field?(name)
|
53
|
-
fields.include?(name)
|
54
|
-
end
|
55
|
-
|
56
|
-
##
|
57
|
-
# @return [Enumerable<Symbol>] The fields the mapper can process
|
58
|
-
def fields
|
59
|
-
[]
|
60
|
-
end
|
61
|
-
|
62
|
-
def method_missing(method_name, *args, &block)
|
63
|
-
return map_field(method_name) if fields.include?(method_name)
|
64
|
-
super
|
65
|
-
end
|
66
|
-
|
67
|
-
def respond_to_missing?(method_name, include_private = false)
|
68
|
-
field?(method_name) || super
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
|
73
|
-
##
|
74
|
-
# @private
|
75
|
-
#
|
76
|
-
# @param name [Symbol]
|
77
|
-
#
|
78
|
-
# @return [Object]
|
79
|
-
def map_field(_name)
|
80
|
-
raise NotImplementedError
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/lib/zizia/parser.rb
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
##
|
5
|
-
# A generic parser.
|
6
|
-
#
|
7
|
-
# `Parser` implementations provide a stream of `InputRecord`s, derived from an
|
8
|
-
# input object (`file`), through `Parser#records`. This method should be
|
9
|
-
# implemented efficiently for repeated access, generating records lazily if
|
10
|
-
# possible, and caching if appropriate.
|
11
|
-
#
|
12
|
-
# Input validation is handled by an array of `#validators`, which are run in
|
13
|
-
# sequence when `#validate` (or `#validate!`) is called. Errors caught in
|
14
|
-
# validation are accessible via `#errors`, and inputs generating errors result
|
15
|
-
# in `#valid? # => false`.
|
16
|
-
#
|
17
|
-
# A factory method `.for` is provided, and each implementation should
|
18
|
-
# provides a `.match?(**)` which returns `true` if the options passed
|
19
|
-
# indicate the parser can handle the given input. Parsers are checked for
|
20
|
-
# `#match?` in the reverse of load order (i.e. the most recently loaded
|
21
|
-
# `Parser` classes are given precedence).
|
22
|
-
#
|
23
|
-
# @example Getting a parser for a file input
|
24
|
-
# file = File.open('path/to/import/manifest.csv')
|
25
|
-
#
|
26
|
-
# Parser.for(file: file).records
|
27
|
-
#
|
28
|
-
# @example Validating a parser
|
29
|
-
# parser = Parser.for(file: invalid_input)
|
30
|
-
#
|
31
|
-
# parser.valid? # => true (always true before validation)
|
32
|
-
# parser.validate # => false
|
33
|
-
# parser.valid? # => false
|
34
|
-
# parser.errors # => an array of Validation::Error-like structs
|
35
|
-
#
|
36
|
-
# parser.validate! # ValidationError
|
37
|
-
#
|
38
|
-
# rubocop:disable Style/ClassVars
|
39
|
-
class Parser
|
40
|
-
DEFAULT_VALIDATORS = [].freeze
|
41
|
-
@@subclasses = [] # @private
|
42
|
-
|
43
|
-
##
|
44
|
-
# @!attribute [rw] file
|
45
|
-
# @return [File]
|
46
|
-
# @!attribute [rw] validators
|
47
|
-
# @return [Array<Validator>]
|
48
|
-
# @!attribute [r] errors
|
49
|
-
# @return [Array]
|
50
|
-
attr_accessor :file, :validators
|
51
|
-
attr_reader :errors
|
52
|
-
|
53
|
-
##
|
54
|
-
# @param file [File]
|
55
|
-
def initialize(file:, **_opts)
|
56
|
-
self.file = file
|
57
|
-
@errors = []
|
58
|
-
@validators ||= self.class::DEFAULT_VALIDATORS
|
59
|
-
|
60
|
-
yield self if block_given?
|
61
|
-
end
|
62
|
-
|
63
|
-
class << self
|
64
|
-
##
|
65
|
-
# @param file [Object]
|
66
|
-
#
|
67
|
-
# @return [Zizia::Parser] a parser instance appropriate for
|
68
|
-
# the arguments
|
69
|
-
#
|
70
|
-
# @raise [NoParserError]
|
71
|
-
def for(file:)
|
72
|
-
klass =
|
73
|
-
@@subclasses.find { |k| k.match?(file: file) } ||
|
74
|
-
raise(NoParserError)
|
75
|
-
|
76
|
-
klass.new(file: file)
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# @abstract
|
81
|
-
# @return [Boolean]
|
82
|
-
def match?(**_opts); end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
##
|
87
|
-
# @private Register a new class when inherited
|
88
|
-
def inherited(subclass)
|
89
|
-
@@subclasses.unshift subclass
|
90
|
-
super
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
##
|
95
|
-
# @abstract
|
96
|
-
#
|
97
|
-
# @yield [record] gives each record in the file to the block
|
98
|
-
# @yieldparam record [ImportRecord]
|
99
|
-
#
|
100
|
-
# @return [Enumerable<ImportRecord>]
|
101
|
-
def records
|
102
|
-
raise NotImplementedError
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# @return [Boolean] true if the file input is valid
|
107
|
-
def valid?
|
108
|
-
errors.empty?
|
109
|
-
end
|
110
|
-
|
111
|
-
##
|
112
|
-
# @return [Boolean] true if the file input is valid
|
113
|
-
def validate
|
114
|
-
validators.each_with_object(errors) do |validator, errs|
|
115
|
-
errs.concat(validator.validate(parser: self))
|
116
|
-
end
|
117
|
-
|
118
|
-
valid?
|
119
|
-
end
|
120
|
-
|
121
|
-
##
|
122
|
-
# @return [true] always true, unless an error is raised.
|
123
|
-
#
|
124
|
-
# @raise [ValidationError] if the file to parse is invalid
|
125
|
-
def validate!
|
126
|
-
validate || raise(ValidationError)
|
127
|
-
end
|
128
|
-
|
129
|
-
class NoParserError < TypeError; end
|
130
|
-
class ValidationError < RuntimeError; end
|
131
|
-
end # rubocop:enable Style/ClassVars
|
132
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'csv'
|
4
|
-
|
5
|
-
module Zizia
|
6
|
-
##
|
7
|
-
# A parser for CSV files. A single `InputRecord` is returned for each row
|
8
|
-
# parsed from the input.
|
9
|
-
#
|
10
|
-
# Validates the format of the CSV, generating a single error the file is
|
11
|
-
# malformed. This error gives the line number and a message for the first
|
12
|
-
# badly formatted row.
|
13
|
-
#
|
14
|
-
# @see CsvFormatValidator
|
15
|
-
class CsvParser < Parser
|
16
|
-
DEFAULT_VALIDATORS = [CsvFormatValidator.new].freeze
|
17
|
-
EXTENSION = '.csv'
|
18
|
-
|
19
|
-
class << self
|
20
|
-
##
|
21
|
-
# Matches all '.csv' filenames.
|
22
|
-
def match?(file:, **_opts)
|
23
|
-
File.extname(file) == EXTENSION
|
24
|
-
rescue TypeError
|
25
|
-
false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
##
|
30
|
-
# Gives a record for each line in the .csv
|
31
|
-
#
|
32
|
-
# @see Parser#records
|
33
|
-
def records
|
34
|
-
return enum_for(:records) unless block_given?
|
35
|
-
|
36
|
-
file.rewind
|
37
|
-
|
38
|
-
CSV.parse(file.read, headers: true).each do |row|
|
39
|
-
yield InputRecord.from(metadata: row)
|
40
|
-
end
|
41
|
-
rescue CSV::MalformedCSVError => e
|
42
|
-
Rails.logger.error "[zizia] The file #{file} could not be parsed as CSV: #{e}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
class RecordImporter
|
5
|
-
##
|
6
|
-
# @!attribute [rw] batch_id
|
7
|
-
# @return [String] an optional batch id for this import run
|
8
|
-
# @!attribute [rw] success_count
|
9
|
-
# @return [Integer] a count of the records that were successfully created
|
10
|
-
# @!attribute [rw] failure_count
|
11
|
-
# @return [Integer] a count of the records that failed import
|
12
|
-
attr_accessor :batch_id, :success_count, :failure_count
|
13
|
-
|
14
|
-
##
|
15
|
-
# @param record [ImportRecord]
|
16
|
-
#
|
17
|
-
# @return [void]
|
18
|
-
def import(record:)
|
19
|
-
create_for(record: record)
|
20
|
-
rescue Faraday::ConnectionFailed, Ldp::HttpError => e
|
21
|
-
Rails.logger.error "[zizia] #{e}"
|
22
|
-
rescue RuntimeError => e
|
23
|
-
Rails.logger.error "[zizia] #{e}"
|
24
|
-
raise e
|
25
|
-
end
|
26
|
-
|
27
|
-
def import_type
|
28
|
-
raise 'No curation_concern found for import' unless
|
29
|
-
defined?(Hyrax) && Hyrax&.config&.curation_concerns&.any?
|
30
|
-
|
31
|
-
Hyrax.config.curation_concerns.first
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def create_for(record:)
|
37
|
-
Rails.logger.info "[zizia] Creating record: #{record.respond_to?(:title) ? record.title : record}."
|
38
|
-
|
39
|
-
created = import_type.create(record.attributes)
|
40
|
-
|
41
|
-
Rails.logger.info "[zizia] Record created at: #{created.id}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class FakeParser < Zizia::Parser
|
4
|
-
METADATA = [{ 'title' => '1' }, { 'title' => '2' }, { 'title' => '3' }].freeze
|
5
|
-
|
6
|
-
def initialize(file: METADATA)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
def records
|
11
|
-
return enum_for(:records) unless block_given?
|
12
|
-
|
13
|
-
file.each { |hsh| yield Zizia::InputRecord.from(metadata: hsh) }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe FakeParser do
|
18
|
-
it_behaves_like 'a Zizia::Parser' do
|
19
|
-
subject(:parser) { described_class.new }
|
20
|
-
let(:record_count) { 3 }
|
21
|
-
end
|
22
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
shared_examples 'a Zizia::Mapper' do
|
4
|
-
subject(:mapper) { described_class.new }
|
5
|
-
|
6
|
-
before { mapper.metadata = metadata }
|
7
|
-
|
8
|
-
describe '#metadata' do
|
9
|
-
it 'can be set' do
|
10
|
-
expect { mapper.metadata = nil }
|
11
|
-
.to change { mapper.metadata }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#field?' do
|
16
|
-
it 'does not have bogus fields' do
|
17
|
-
expect(mapper.field?(:NOT_A_REAL_FIELD)).to be_falsey
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'has fields that are expected' do
|
21
|
-
if defined?(expected_fields)
|
22
|
-
expected_fields.each do |field|
|
23
|
-
expect(mapper.field?(field)).to be_truthy
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe '#fields' do
|
30
|
-
it { expect(mapper.fields).to contain_exactly(*expected_fields) }
|
31
|
-
end
|
32
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'zizia/always_invalid_validator'
|
4
|
-
|
5
|
-
shared_examples 'a Zizia::Parser' do
|
6
|
-
describe '#file' do
|
7
|
-
it 'is an accessor' do
|
8
|
-
expect { parser.file = :a_new_file }
|
9
|
-
.to change { parser.file }
|
10
|
-
.to(:a_new_file)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#records' do
|
15
|
-
it 'yields records' do
|
16
|
-
unless described_class == Zizia::Parser
|
17
|
-
expect { |b| parser.records(&b) }
|
18
|
-
.to yield_control.exactly(record_count).times
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#valid?' do
|
24
|
-
it 'is valid' do
|
25
|
-
expect(parser).to be_valid
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'when not valid' do
|
29
|
-
before do
|
30
|
-
parser.validators = [Zizia::AlwaysInvalidValidator.new]
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'is invalid' do
|
34
|
-
expect { parser.validate }
|
35
|
-
.to change { parser.valid? }
|
36
|
-
.to be_falsey
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#validate' do
|
42
|
-
it 'is true when valid' do
|
43
|
-
expect(parser.validate).to be_truthy
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'when not valid' do
|
47
|
-
before do
|
48
|
-
parser.validators = [Zizia::AlwaysInvalidValidator.new]
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'is invalid' do
|
52
|
-
expect(parser.validate).to be_falsey
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe '#validate!' do
|
58
|
-
it 'is true when valid' do
|
59
|
-
expect(parser.validate).to be_truthy
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'when not valid' do
|
63
|
-
before do
|
64
|
-
parser.validators = [Zizia::AlwaysInvalidValidator.new]
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'raises a ValidationError' do
|
68
|
-
expect { parser.validate! }
|
69
|
-
.to raise_error Zizia::Parser::ValidationError
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
shared_examples 'a Zizia::Validator' do
|
4
|
-
subject(:validator) { described_class.new }
|
5
|
-
|
6
|
-
define :be_a_validator_error do # |expected|
|
7
|
-
match { false } # { |actual| some_condition }
|
8
|
-
end
|
9
|
-
|
10
|
-
describe '#validate' do
|
11
|
-
context 'without a parser' do
|
12
|
-
it 'raises ArgumentError' do
|
13
|
-
expect { validator.validate }.to raise_error ArgumentError
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'gives an empty error collection for a valid parser' do
|
18
|
-
expect(validator.validate(parser: valid_parser)).not_to be_any if
|
19
|
-
defined?(valid_parser)
|
20
|
-
end
|
21
|
-
|
22
|
-
context 'for an invalid parser' do
|
23
|
-
it 'gives an non-empty error collection' do
|
24
|
-
expect(validator.validate(parser: invalid_parser)).to be_any if
|
25
|
-
defined?(invalid_parser)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/zizia/spec.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zizia
|
4
|
-
##
|
5
|
-
# RSpec test support for {Zizia} importers.
|
6
|
-
#
|
7
|
-
# @see https://relishapp.com/rspec/rspec-core/docs/
|
8
|
-
module Spec
|
9
|
-
require 'zizia/spec/shared_examples/a_mapper'
|
10
|
-
require 'zizia/spec/shared_examples/a_parser'
|
11
|
-
require 'zizia/spec/shared_examples/a_validator'
|
12
|
-
require 'zizia/spec/fakes/fake_parser'
|
13
|
-
end
|
14
|
-
end
|