kithe 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -42
- data/app/indexing/kithe/indexable/thread_settings.rb +3 -1
- data/app/indexing/kithe/indexable.rb +3 -0
- data/app/models/kithe/asset.rb +9 -21
- data/app/validators/array_inclusion_validator.rb +1 -1
- data/lib/kithe/version.rb +1 -4
- data/lib/shrine/plugins/kithe_derivative_definitions.rb +10 -4
- data/lib/shrine/plugins/kithe_persisted_derivatives.rb +5 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df697bf6cd0128be5ee217fb3eb191af55994b1284e1e05f75da73667e92d8f3
|
4
|
+
data.tar.gz: f388992232e60a99f7a6f7a2743e47a1690152665b9c85adbdf34457ce822104
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '079a440ca120cc56e4a624b335cab990b2dc0f8a7df73821f251ecae4bf17f91000e9f57bc59c01d6a378577c871d1bc5d8a31ccee3a49a8402459edb532c7c0'
|
7
|
+
data.tar.gz: 73ba63882d5df383011c354c648b82f422891018679c8397a13143a937f9f9a12142eac18ea22d3162bb0f3f127b7ba9234a7309a18bd6329013c598ad17737d
|
data/README.md
CHANGED
@@ -7,54 +7,32 @@ An experiment in shareable tools/components for building a digital collections a
|
|
7
7
|
|
8
8
|
Kithe is a toolkit for building digital collections/repository applications in Rails. It comes out of experience in the [samvera](https://samvera.org/) community of open source library-archives-museums digital collections/preservation work (but is not a samvera project).
|
9
9
|
|
10
|
-
Kithe does not use fedora or valkyrie, but stores all metadata using ActiveRecord. Kithe requires you use postgres 9.5+ as your db.
|
10
|
+
Kithe does not use fedora or valkyrie, but stores all metadata using ActiveRecord. Kithe requires you use postgres 9.5+ as your db. It uses [shrine](https://shrinerb.com) for file-handling/asset-storing and tries to support developing your app as a normal Rails/ActiveRecord app. It will not give you a working turnkey application, but is a collection of tools for building an app with certain patterns.
|
11
11
|
|
12
|
-
Kithe
|
12
|
+
Kithe provides tools to supports these architectural patterns:
|
13
13
|
|
14
|
-
|
14
|
+
* [Modelling and Persistence](./guides/modelling.md):
|
15
|
+
* A Collection/Work/Asset model based on Samvera/PCDM, using rails Single-Table Inheritance to support hetereogenous associations with efficient rdbms lookup.
|
16
|
+
* Using Postgres JSONB for "schema-less" flexible storage, via [attr_json](https://github.com/jrochkind/attr_json), supporting complex structured nested repeatable data values.
|
17
|
+
* [Work representatives](./guides/work_representative.md) via ActiveRecord association, using postgres recursive CTE's to compute the "leaf" representative, designed to support efficient use of the DB including pre-loading leaf representatives.
|
18
|
+
* UUIDv4's as internal primary keys, but also provide a "friendlier_id" with a shorter unique alphanumeric identifier for URLs and other UI. By default they are supplied by a postgres stored procedure, but your code can set them to whatever you like.
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
Kithe has beeen developed in tandem with the Science History Institute's in-development [replacement digital collections](https://github.com/sciencehistory/scihist_digicoll) app, and you can look there for a model/canonical/demo kithe use.
|
19
|
-
|
20
|
-
The Science History Institute app is live and working, so kithe is 1.0. We are serious about [semantic verisioning](https://semver.org/) and will endeavor to release backwards breaking changes only with a major release, and minimize major releases.
|
21
|
-
|
22
|
-
While it is working well for us, since it hasn't had wide use, it could still be considered somewhat of an experiment. But you are invited to try it out and see how it works. You are welcome to use it, but also welcome to copy any code or just ideas from kithe.
|
23
|
-
|
24
|
-
Any questions or feedback of any kind are very welcome and encouraged, in the github project issues, samvera slack, or wherever is convenient.
|
25
|
-
|
26
|
-
|
27
|
-
# Kithe parts
|
28
|
-
|
29
|
-
Some guide documentation is available to explain each of kithe's major functionality areas. Definitely start with the modelling guide.
|
30
|
-
|
31
|
-
* [Modelling and Persistence](./guides/modelling.md): It can be somewhwat challenging to figure out a good way to model our data in an rdbms. We give you a hopefully flexible and understandable architecture that is designed to support efficient performance. It's influenced by PCDM and traditional samvera modelling. It's based on [attr_json](https://github.com/jrochkind/attr_json) to let you model arbitrary and complex object-oriented data that gets persisted as a serialized json hash. It uses rails Single Table Inheritance to support hetereogenous associations and collections. The modelling classes in some places use postgres-specific features for efficiency.
|
32
|
-
|
33
|
-
* [Work representatives](./guides/work_representative.md). Built in associations to support "representative", using postgres recursive CTE's to compute the "leaf" representative, designed to support efficient use of the DB including pre-loading leaf representatives.
|
34
|
-
|
35
|
-
* Kithe objects use UUIDv4's as internal primary keys, but also provide a "friendlier_id" with a shorter unique alphanumeric identifier for URLs and other UI. By default they are supplied by a postgres stored procedure, but your code can set them to whatever you like.
|
36
|
-
|
37
|
-
* [Form support](./guides/forms.md): Dealing with complex and _repeatable_ data, as our modelling layer allows, can be tricky in an HTML form. We supply javascript-backed Rails form input help for repeatable and compound/nested data.
|
20
|
+
* [Form support](./guides/forms.md): Easy Rails-like forms for that complex nested and repeatable form data, leaning on simple_form.
|
38
21
|
* An extension to Rails "strong parameters" that make some common patterns for
|
39
|
-
embedded JSON attributes more convenient, [Kithe::Parameters](./app/models/kithe/parameters.rb)
|
40
|
-
|
41
|
-
* [File handling](./guides/file_handling.md): Handling files is at the core of digital repository use cases. We need a file handling framework that is flexible, predictable and reliable, and architected for performance. We try to give you one based on the [shrine](https://shrinerb.com) file attachment toolkit for ruby.
|
22
|
+
embedded JSON attributes more convenient, [Kithe::Parameters](./app/models/kithe/parameters.rb)
|
42
23
|
|
43
|
-
|
24
|
+
* [File handling](./guides/file_handling.md): A framework that let's you easily plug in your own custom characterization and derivatives handling, to be handled in an efficient and flexible way, ordinarily using background jobs. Implemented on top of [shrine](https://shrinerb.com).
|
25
|
+
* [Derivatives](./guides/derivatives.md) handling ensures data consistency without race conditions, and efficient querying patterns, letting you plugin custom derivatives creation, with some standard routines included.
|
44
26
|
|
45
|
-
* [Solr Indexing](./guides/solr_indexing.md):
|
27
|
+
* [Solr Indexing](./guides/solr_indexing.md): Built-in Solr indexing using [traject](https://github.com/traject/traject) for defining mappings from your model objects to what you want in a Solr index. Uses ActiveRecord callbacks to automatically sync saves to solr, with many opportunities for customization.
|
46
28
|
* Not coupled to any other kithe components, could be used independently, hypothetically on any ActiveRecord model.
|
47
|
-
* Written after review of "prior art" in [sunspot](https://github.com/sunspot/sunspot) and [searchkick](https://github.com/ankane/searchkick) (which both used AR callback-based indexing), and others.
|
48
|
-
|
49
|
-
* A [recommended approach for using Blacklight](./guides/blacklight_approach.md) with search result view templates based on actual ActiveRecord models. It is totally optional to use Blacklight at all with kithe, or to use this approach if you do.
|
50
29
|
|
51
|
-
|
30
|
+
* A [recommended approach for using Blacklight](./guides/blacklight_approach.md) with search result view templates based on actual ActiveRecord models. Blacklight use is optional with kithe, but kithe works well with blacklight.
|
52
31
|
|
53
|
-
*
|
32
|
+
* Assorted optional utilities
|
33
|
+
* [Kithe::ConfigBase](./app/models/kithe/config_base.rb) A totally optional solution for managing environmental config variables.
|
54
34
|
|
55
|
-
* [
|
56
|
-
|
57
|
-
* [ArrayInclusionValdaitor](./app/validators/array_inclusion_validator.rb) Useful for validating on attr_json arrays of primitives.
|
35
|
+
* [ArrayInclusionValdaitor](./app/validators/array_inclusion_validator.rb) Useful for validating on attr_json arrays of primitives.
|
58
36
|
|
59
37
|
## Setting up your app to use kithe
|
60
38
|
|
@@ -70,11 +48,28 @@ So you want to start an app that uses kithe. We should later provide better 'get
|
|
70
48
|
|
71
49
|
* Specific additional pre-requisites/requirements can sometimes be found in individual feature docs. And include the Javascript from [cocoon](https://github.com/nathanvda/cocoon), for form support for repeatable-field editing forms. We haven't quite figured out our preferred sane approach for sharing Javascript via kithe.
|
72
50
|
|
73
|
-
|
51
|
+
|
52
|
+
## Why kithe?
|
53
|
+
|
54
|
+
Kithe tries to let you develop your app like "an ordinary Rails app" (in all it's possible variations), while handling some of the rough spots common to the kinds of modelling and administration common to digital collections domains. But developers should be able to use standard Rails patterns and skills to develop an app to your specific local needs, familiar, no more complicated than building any other Rails app. You add features to a kithe app just like building Rails, using whatever patterns you like. We support modern Rails versions, 5.2+.
|
55
|
+
|
56
|
+
In that kithe provides tools and not a turnkey app, develping an app based on kythe in some ways similar to developing an app based on [valkyrie](https://github.com/samvera-labs/valkyrie) (but not hyrax). They both provide basic architecture for modelling/persistence, although in quite different ways. Kithe also provides tools in addition to modelling/persistence, but does _not_ provide the data-mapper/repository pattern valkyrie does, or any built-in abstraction for persisting anywhere but a postgres DB.
|
57
|
+
|
58
|
+
If you are comparing it to a "solution bundle" digital collections platform like hyrax, kithe may seem like more work. But experience has shown us that in our domain, "solution bundles" can turn out less of a "turnkey" approach than they seem, and can have greater development cost over total app lifecycle than anticipated. If you have similar experience that leads you to consider a more 'bespoke' app approach -- you may want to consider kithe. We hope to provide architecturally simple support and standardization for your custom app, taking care of some of the common "hard parts" and leaving you with flexibility to build out the app that meets your needs.
|
59
|
+
|
60
|
+
Kithe has beeen developed in tandem with the Science History Institute's in-development [replacement digital collections](https://github.com/sciencehistory/scihist_digicoll) app, which has been in production for several years using kithe.
|
61
|
+
|
62
|
+
[The University of Minnesota found kithe](https://docs.google.com/presentation/d/1Z4AoIDOaxbY4pt3mDhNt6MfUs6VIMjysKKmaYQpjuk8/edit?usp=sharing) to pair well with GeoBlacklight, an easy way to provide the persistence layer and metadata editing UI that blacklight on it's own lacks.
|
63
|
+
|
64
|
+
We are serious about [semantic verisioning](https://semver.org/) and will endeavor to release backwards breaking changes only with a major release, and minimize major releases.
|
65
|
+
|
66
|
+
Kithe is working well for us, but has had limited (but non-zero) adoption from other institutions. It's still somewhat of an experiment, but one we think is going well. If you would consider developing a digital collections/repository app in "just Rails", we think it's worth investigating if kithe can save you some trouble in some rough common use cases. You are invited to try it out and see how it works, using kithe directly, or copying any code or just ideas from kithe.
|
67
|
+
|
68
|
+
Any questions or feedback of any kind are very welcome and encouraged! In the github project issues, samvera slack, or wherever is convenient.
|
74
69
|
|
75
70
|
## To be done
|
76
71
|
|
77
|
-
Considering some blacklight integration support
|
72
|
+
Considering some additional blacklight integration support, is any needed?
|
78
73
|
|
79
74
|
Other components/features may become more clear as we continue to develop. It's possible that kithe won't (at least for a long time) contain controllers themselves (it may contain some helper methods for controllers), or generalized permissions architecture. Both of these are some of the things most particular to specific apps, that are hard to generalize without creating monsters.
|
80
75
|
|
@@ -85,8 +80,6 @@ This is a Rails 'engine' whose template was created with: `rails plugin new kith
|
|
85
80
|
|
86
81
|
* Note we have chosen not to make it 'mountable' or 'isolated', I think that would be inappropriate for this kind of gem. It _is_ an engine so it can hook into Rails load paths and config as needed.
|
87
82
|
|
88
|
-
|
89
|
-
|
90
83
|
* Note we are currently using the standard rails-generated dummy app in spec/dummy for testing, rather than [engine_cart](https://github.com/cbeer/engine_cart) or [combustion](https://github.com/pat/combustion).
|
91
84
|
* Before you run the tests for the first time, create the database by running: `rails db:setup`. This will create two databases, kithe_development and kithe_test.
|
92
85
|
* Some of the rspec tests depend on [FFmpeg](https://ffmpeg.org/) for testing file derivative transformations. Mac users can install [ffmpeg via homebrew](https://formulae.brew.sh/formula/ffmpeg): `brew install ffmpeg`
|
@@ -97,6 +97,8 @@ module Kithe
|
|
97
97
|
# only call on-finish if we have a writer, batch writers are lazily
|
98
98
|
# created and maybe we never created one
|
99
99
|
if @writer
|
100
|
+
# if we created the writer ourselves locally and nobody
|
101
|
+
# specified an on_finish, close our locally-created writer.
|
100
102
|
on_finish = if @local_writer && @on_finish.nil?
|
101
103
|
proc {|writer| writer.close }
|
102
104
|
else
|
@@ -105,7 +107,7 @@ module Kithe
|
|
105
107
|
on_finish.call(@writer) if on_finish
|
106
108
|
end
|
107
109
|
|
108
|
-
Thread.current[THREAD_CURRENT_KEY] = @
|
110
|
+
Thread.current[THREAD_CURRENT_KEY] = @original_settings
|
109
111
|
end
|
110
112
|
|
111
113
|
private
|
@@ -120,6 +120,9 @@ module Kithe
|
|
120
120
|
#
|
121
121
|
# By default will use a per-update writer, or thread/block-specific writer configured with `self.index_with`,
|
122
122
|
# or you can pass one in.
|
123
|
+
#
|
124
|
+
# This method is part of Kithe API, including allowing local apps to override! Backwards
|
125
|
+
# compatibilty matters for semver with any change to method signature.
|
123
126
|
def update_index(mapper: kithe_indexable_mapper, writer:nil)
|
124
127
|
RecordIndexUpdater.new(self, mapper: mapper, writer: writer).update_index
|
125
128
|
end
|
data/app/models/kithe/asset.rb
CHANGED
@@ -81,31 +81,11 @@ class Kithe::Asset < Kithe::Model
|
|
81
81
|
source = file
|
82
82
|
return false unless source
|
83
83
|
|
84
|
-
|
85
|
-
local_files = _process_kithe_derivatives_without_download(source, only: only, except: except, lazy: lazy)
|
84
|
+
local_files = file_attacher.process_derivatives(:kithe_derivatives, only: only, except: except, lazy: lazy)
|
86
85
|
|
87
86
|
file_attacher.add_persisted_derivatives(local_files)
|
88
87
|
end
|
89
88
|
|
90
|
-
# Working around Shrine's insistence on pre-downloading original before calling derivative processor.
|
91
|
-
# We want to avoid that, so when our `lazy` argument is in use, original does not get eagerly downloaded,
|
92
|
-
# but only gets downloaded if needed to make derivatives.
|
93
|
-
#
|
94
|
-
# This is a somewhat hacky way to do that, loking at the internals of shrine `process_derivatives`,
|
95
|
-
# and pulling them out to skip the parts we don't want. We also lose shrine instrumentation
|
96
|
-
# around this action.
|
97
|
-
#
|
98
|
-
# See: https://github.com/shrinerb/shrine/issues/470
|
99
|
-
#
|
100
|
-
# If that were resolved, the 'ordinary' shrine thing would be to replace calls
|
101
|
-
# to this local private method with:
|
102
|
-
#
|
103
|
-
# file_attacher.process_derivatives(:kithe_derivatives, only: only, except: except, lazy: lazy)
|
104
|
-
#
|
105
|
-
private def _process_kithe_derivatives_without_download(source, **options)
|
106
|
-
processor = file_attacher.class.derivatives_processor(:kithe_derivatives)
|
107
|
-
local_files = file_attacher.instance_exec(source, **options, &processor)
|
108
|
-
end
|
109
89
|
|
110
90
|
# Just a convennience for file_attacher.add_persisted_derivatives (from :kithe_derivatives),
|
111
91
|
# feel free to use that if you want to add more than one etc. By default stores to
|
@@ -144,6 +124,14 @@ class Kithe::Asset < Kithe::Model
|
|
144
124
|
result && result.values.first
|
145
125
|
end
|
146
126
|
|
127
|
+
# Like #update_derivative, but can update multiple at once.
|
128
|
+
#
|
129
|
+
# asset.update_derivatives({ "big_thumb" => big_thumb_io, "small_thumb" => small_thumb_io })
|
130
|
+
#
|
131
|
+
# Options from kithe `add_persisted_derivatives`/shrine `add_derivative` supported.
|
132
|
+
#
|
133
|
+
# asset.update_derivatives({ "big_thumb" => big_thumb_io, "small_thumb" => small_thumb_io }, delete_false)
|
134
|
+
#
|
147
135
|
def update_derivatives(deriv_hash, **options)
|
148
136
|
file_attacher.add_persisted_derivatives(deriv_hash, **options)
|
149
137
|
end
|
@@ -42,7 +42,7 @@ class ArrayInclusionValidator < ActiveModel::EachValidator
|
|
42
42
|
|
43
43
|
unless not_allowed_values.blank?
|
44
44
|
formatted_rejected = not_allowed_values.uniq.collect(&:inspect).join(",")
|
45
|
-
record.errors.add(attribute, :inclusion, options.except(:in).merge!(rejected_values: formatted_rejected, value: value))
|
45
|
+
record.errors.add(attribute, :inclusion, **options.except(:in).merge!(rejected_values: formatted_rejected, value: value))
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
data/lib/kithe/version.rb
CHANGED
@@ -10,7 +10,11 @@ class Shrine
|
|
10
10
|
|
11
11
|
# Register our derivative processor, that will create our registered derivatives,
|
12
12
|
# with our custom options.
|
13
|
-
|
13
|
+
#
|
14
|
+
# We do download: false, so when our `lazy` argument is in use, original does not get eagerly downloaded,
|
15
|
+
# but only gets downloaded if needed to make derivatives. This is great for performance, especially
|
16
|
+
# when running batch job to add just missing derivatives.
|
17
|
+
uploader::Attacher.derivatives(:kithe_derivatives, download: false) do |original, **options|
|
14
18
|
Kithe::Asset::DerivativeCreator.new(self.class.kithe_derivative_definitions,
|
15
19
|
source_io: original,
|
16
20
|
shrine_attacher: self,
|
@@ -44,10 +48,12 @@ class Shrine
|
|
44
48
|
# Tempfile and Dir.mktmpdir may be useful.
|
45
49
|
#
|
46
50
|
# If in order to do your transformation you need additional information about the original,
|
47
|
-
# just add a `
|
51
|
+
# just add a `attacher:` keyword argument to your block, and a `Shrine::Attacher` subclass
|
52
|
+
# will be passed in. You can then get the model object from `attacher.record`, or the
|
53
|
+
# original file as a `Shrine::UploadedFile` object with `attacher.file`.
|
48
54
|
#
|
49
|
-
# define_derivative :thumbnail do |original_file,
|
50
|
-
# record.
|
55
|
+
# define_derivative :thumbnail do |original_file, attacher:|
|
56
|
+
# attacher.record.title, attacher.file.width, attacher.file.content_type # etc
|
51
57
|
# end
|
52
58
|
#
|
53
59
|
# Derivatives are normally uploaded to the Shrine storage labeled :kithe_derivatives,
|
@@ -26,6 +26,11 @@ class Shrine
|
|
26
26
|
# Like the shrine `add_derivatives` method, but also *persists* the
|
27
27
|
# derivatives (saves to db), in a realiably concurrency-safe way.
|
28
28
|
#
|
29
|
+
# For ruby 3 compatibility, make sure you supply local_files as a hash
|
30
|
+
# literal with curly braces:
|
31
|
+
#
|
32
|
+
# attacher.add_persisted_derivatives({ derivative_name1: io_obj1, deriv2: io2 })
|
33
|
+
#
|
29
34
|
# Generally can take any options that shrine `add_derivatives`
|
30
35
|
# can take, including custom `storage` or `metadata` arguments.
|
31
36
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kithe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -70,14 +70,14 @@ dependencies:
|
|
70
70
|
requirements:
|
71
71
|
- - "~>"
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version: '3.
|
73
|
+
version: '3.3'
|
74
74
|
type: :runtime
|
75
75
|
prerelease: false
|
76
76
|
version_requirements: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
78
|
- - "~>"
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version: '3.
|
80
|
+
version: '3.3'
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: shrine-url
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -410,7 +410,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
410
410
|
- !ruby/object:Gem::Version
|
411
411
|
version: '0'
|
412
412
|
requirements: []
|
413
|
-
rubygems_version: 3.
|
413
|
+
rubygems_version: 3.1.6
|
414
414
|
signing_key:
|
415
415
|
specification_version: 4
|
416
416
|
summary: Shareable tools/components for building a digital collections app in Rails.
|