shrine-rom 0.1.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +291 -0
- data/lib/shrine/plugins/rom.rb +124 -0
- data/shrine-rom.gemspec +23 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 78bc603cf077c91b940f0df8d4cd0304c68b4182b0ae6b086e911eb1107a1465
|
4
|
+
data.tar.gz: c0eabd2c656ddd614a21cf729f0c344de88e2dec2874d9c70052262e748b4107
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cea2d2928e38caaf138e9246dd5df636aed3e3de01ee7860a1fedec4c69ce5ba197632423d36be05b644d8d383646e9d86b56ff5b40f1f99795f0a575b82db8a
|
7
|
+
data.tar.gz: bd9e6a7cf0ac72be3ae91a3ed10665c172f202f45aa6523d53c72b06edba96905e24933a1dcf8246af691821e756706afb306a4f08837f1a22382c6973479d0f
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Janko Marohnić
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
# Shrine::Plugins::Rom
|
2
|
+
|
3
|
+
Provides [ROM] integration for [Shrine].
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```sh
|
8
|
+
$ bundle add shrine-rom
|
9
|
+
```
|
10
|
+
|
11
|
+
## Quick start
|
12
|
+
|
13
|
+
Let's asume we have "photos" that have an "image" attachment. We start by
|
14
|
+
configuring Shrine in our initializer, and loading the `rom` plugin provided by
|
15
|
+
shrine-rom:
|
16
|
+
|
17
|
+
```rb
|
18
|
+
# Gemfile
|
19
|
+
gem "shrine", "~> 3.0"
|
20
|
+
gem "shrine-rom"
|
21
|
+
```
|
22
|
+
```rb
|
23
|
+
require "shrine"
|
24
|
+
require "shrine/storage/file_system"
|
25
|
+
|
26
|
+
Shrine.storages = {
|
27
|
+
cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
|
28
|
+
store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"), # permanent
|
29
|
+
}
|
30
|
+
|
31
|
+
Shrine.plugin :rom # ROM integration, provided by shrine-rom
|
32
|
+
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays
|
33
|
+
Shrine.plugin :rack_file # for accepting Rack uploaded file hashes
|
34
|
+
Shrine.plugin :form_assign # for assigning file from form fields
|
35
|
+
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file
|
36
|
+
Shrine.plugin :validation_helpers # for validating uploaded files
|
37
|
+
Shrine.plugin :determine_mime_type # determine MIME type from file content
|
38
|
+
```
|
39
|
+
|
40
|
+
Next, we run a migration that adds an `image_data` text or JSON column to our
|
41
|
+
`photos` table:
|
42
|
+
|
43
|
+
```rb
|
44
|
+
ROM::SQL.migration do
|
45
|
+
change do
|
46
|
+
add_column :photos, :image_data, :text # or :jsonb
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
Now we can define an `ImageUploader` class and include an attachment module
|
52
|
+
into our `Photo` entity:
|
53
|
+
|
54
|
+
```rb
|
55
|
+
class ImageUploader < Shrine
|
56
|
+
# we add some basic validation
|
57
|
+
Attacher.validate do
|
58
|
+
validate_max_size 20*1024*1024
|
59
|
+
validate_mime_type %w[image/jpeg image/png image/webp]
|
60
|
+
validate_extension %w[jpg jpeg png webp]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
```rb
|
65
|
+
class PhotoRepo < ROM::Repository[:photos]
|
66
|
+
commands :create, update: :by_pk, delete: :by_pk
|
67
|
+
struct_namespace Entities
|
68
|
+
|
69
|
+
def find(id)
|
70
|
+
photos.fetch(id)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
```rb
|
75
|
+
module Entities
|
76
|
+
class Photo < ROM::Struct
|
77
|
+
include ImageUploader::Attachment[:image]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
Let's now add fields for our `image` attachment to our HTML form for creating
|
83
|
+
photos:
|
84
|
+
|
85
|
+
```rb
|
86
|
+
# with Forme gem:
|
87
|
+
form @photo, action: "/photos", enctype: "multipart/form-data", namespace: "photo" do |f|
|
88
|
+
f.input :title, type: :text
|
89
|
+
f.input :image, type: :hidden, value: @attacher&.cached_data
|
90
|
+
f.input :image, type: :file
|
91
|
+
f.button "Create"
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
Now in our controller we can attach the uploaded file from request params.
|
96
|
+
We'll assume you're using [dry-validation] for validating user input.
|
97
|
+
|
98
|
+
```rb
|
99
|
+
post "/photos" do
|
100
|
+
@photo = Entities::Photo.new
|
101
|
+
@attacher = @photo.image_attacher
|
102
|
+
|
103
|
+
@attacher.form_assign(params["photo"]) # assigns file and performs validation
|
104
|
+
|
105
|
+
contract = CreatePhotoContract.new(image_attacher: @attacher)
|
106
|
+
result = contract.call(params["photo"])
|
107
|
+
|
108
|
+
if result.success?
|
109
|
+
@attacher.finalize # upload cached file to permanent storage
|
110
|
+
|
111
|
+
attributes = result.to_h
|
112
|
+
attributes.merge!(@attacher.column_values)
|
113
|
+
|
114
|
+
photo_repo.create(attributes)
|
115
|
+
# ...
|
116
|
+
else
|
117
|
+
# ... render view with form ...
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
```rb
|
122
|
+
class CreatePhotoContract < Dry::Validation::Contract
|
123
|
+
option :image_attacher
|
124
|
+
|
125
|
+
params do
|
126
|
+
required(:title).filled(:string)
|
127
|
+
end
|
128
|
+
|
129
|
+
# copy any attacher's validation errors into our dry-validation contract
|
130
|
+
rule(:image) do
|
131
|
+
key.failure("must be present") unless image_attacher.attached?
|
132
|
+
image_attacher.errors.each { |message| key.failure(message) }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
Once the image has been successfully attached to our photo, we can retrieve the
|
138
|
+
image URL by calling `#image_url` on the entity:
|
139
|
+
|
140
|
+
```erb
|
141
|
+
<img src="<%= @photo.image_url %>" />
|
142
|
+
```
|
143
|
+
|
144
|
+
If you want to see a complete example with direct uploads and backgrounding,
|
145
|
+
see the [demo app][demo].
|
146
|
+
|
147
|
+
## Understanding
|
148
|
+
|
149
|
+
The `rom` plugin builds upon Shrine's [`entity`][entity] plugin, providing
|
150
|
+
persistence functionality.
|
151
|
+
|
152
|
+
The attachment module included into the entity provides convenience methods for
|
153
|
+
reading the data attribute:
|
154
|
+
|
155
|
+
```rb
|
156
|
+
photo.image_data #=> '{"id":"path/to/file","storage":"store","metadata":{...}}'
|
157
|
+
|
158
|
+
photo.image #=> #<Shrine::UploadedFile @id="path/to/file" @storage_key=:store ...>
|
159
|
+
photo.image_url #=> "https://s3.amazonaws.com/..."
|
160
|
+
photo.image_attacher #=> #<Shrine::Attacher ...>
|
161
|
+
```
|
162
|
+
|
163
|
+
### Updating
|
164
|
+
|
165
|
+
When updating the attached file for an existing record, it's important to
|
166
|
+
initialize the attacher from that record's current attachment. That way the old
|
167
|
+
file will be automatically deleted on `Attacher#finalize`.
|
168
|
+
|
169
|
+
```rb
|
170
|
+
photo = photo_repo.find(photo_id)
|
171
|
+
photo.image #=> #<Shrine::UploadedFile @id="foo" ...>
|
172
|
+
|
173
|
+
attacher = photo.image_attacher # has current attachment
|
174
|
+
attacher.assign(file)
|
175
|
+
|
176
|
+
photo_repo.update(photo_id, attacher.column_values)
|
177
|
+
|
178
|
+
attacher.finalize # deletes previous attachment
|
179
|
+
```
|
180
|
+
|
181
|
+
### Attacher state
|
182
|
+
|
183
|
+
Unlike the [`model`][model] plugin, the `entity` plugin doesn't memoize the
|
184
|
+
`Shrine::Attacher` instance:
|
185
|
+
|
186
|
+
```rb
|
187
|
+
photo.image_attacher #=> #<Shrine::Attacher:0x00007ffe564085d8>
|
188
|
+
photo.image_attacher #=> #<Shrine::Attacher:0x00007ffe53b2f378> (different instance)
|
189
|
+
```
|
190
|
+
|
191
|
+
So, if you want to update the attacher state, you need to first assign it to a
|
192
|
+
variable:
|
193
|
+
|
194
|
+
```rb
|
195
|
+
attacher = photo.image_attacher
|
196
|
+
attacher.assign(file)
|
197
|
+
attacher.finalize
|
198
|
+
```
|
199
|
+
|
200
|
+
### Persisting
|
201
|
+
|
202
|
+
Normally you'd persist attachment changes explicitly, by using
|
203
|
+
`Attacher#column_data` or `Attacher#column_values`:
|
204
|
+
|
205
|
+
```rb
|
206
|
+
attacher = photo.image_attacher
|
207
|
+
attacher.attach(file)
|
208
|
+
|
209
|
+
photo_repo.create(image_data: attacher.column_data)
|
210
|
+
# or
|
211
|
+
photo_repo.create(attacher.column_values)
|
212
|
+
```
|
213
|
+
|
214
|
+
## Backgrounding
|
215
|
+
|
216
|
+
If you want to delay promotion into a background job, you need to call
|
217
|
+
`Attacher#finalize` _after_ you've persisted the cached file, so that your
|
218
|
+
background job is able to retrieve the record. We'll assume your repository
|
219
|
+
objects are registered using [dry-container].
|
220
|
+
|
221
|
+
```rb
|
222
|
+
Shrine.plugin :backgrounding
|
223
|
+
Shrine::Attacher.destroy_block { Attachment::DestroyJob.perform_async(self.class, data) }
|
224
|
+
```
|
225
|
+
```rb
|
226
|
+
attacher = photo.image_attacher
|
227
|
+
attacher.assign(file)
|
228
|
+
|
229
|
+
photo = photo_repo.create(attacher.column_values)
|
230
|
+
|
231
|
+
attacher.promote_block do |attacher|
|
232
|
+
Attachment::PromoteJob.perform_async(:photo_repo, photo.id, :image, attacher.file_data)
|
233
|
+
end
|
234
|
+
|
235
|
+
attacher.finalize # calls the promote block
|
236
|
+
```
|
237
|
+
```rb
|
238
|
+
class Attachment::PromoteJob
|
239
|
+
include Sidekiq::Worker
|
240
|
+
|
241
|
+
def perform(repo_name, record_id, name, file_data)
|
242
|
+
repo = Application[repo_name] # retrieve repo from container
|
243
|
+
entity = repo.find(record_id)
|
244
|
+
|
245
|
+
attacher = Shrine::Attacher.retrieve(
|
246
|
+
entity: entity,
|
247
|
+
name: name,
|
248
|
+
file: file_data,
|
249
|
+
repository: repo, # repository needs to be passed in
|
250
|
+
)
|
251
|
+
|
252
|
+
attacher.atomic_promote
|
253
|
+
rescue Shrine::AttachmentChanged, # attachment has changed
|
254
|
+
ROM::TupleCountMismatchError # record has been deleted
|
255
|
+
end
|
256
|
+
end
|
257
|
+
```
|
258
|
+
```rb
|
259
|
+
class Attachment::DestroyJob
|
260
|
+
include Sidekiq::Worker
|
261
|
+
|
262
|
+
def perform(attacher_class, data)
|
263
|
+
attacher = Object.const_get(attacher_class).from_data(data)
|
264
|
+
attacher.destroy
|
265
|
+
end
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
## Contributing
|
270
|
+
|
271
|
+
Tests are run with:
|
272
|
+
|
273
|
+
```sh
|
274
|
+
$ bundle exec rake test
|
275
|
+
```
|
276
|
+
|
277
|
+
## Code of Conduct
|
278
|
+
|
279
|
+
Everyone interacting in the Shrine::Rom project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/janko/shrine-rom/blob/master/CODE_OF_CONDUCT.md).
|
280
|
+
|
281
|
+
## License
|
282
|
+
|
283
|
+
[MIT](/LICENSE.txt)
|
284
|
+
|
285
|
+
[ROM]: https://rom-rb.org
|
286
|
+
[Shrine]: https://shrinerb.com
|
287
|
+
[entity]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/entity.md#readme
|
288
|
+
[model]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/model.md#readme
|
289
|
+
[dry-validation]: https://dry-rb.org/gems/dry-validation/
|
290
|
+
[dry-container]: https://dry-rb.org/gems/dry-container/
|
291
|
+
[demo]: /demo
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shrine
|
4
|
+
module Plugins
|
5
|
+
module Rom
|
6
|
+
def self.load_dependencies(uploader)
|
7
|
+
uploader.plugin :entity
|
8
|
+
uploader.plugin :_persistence, plugin: self
|
9
|
+
end
|
10
|
+
|
11
|
+
module AttachmentMethods
|
12
|
+
# Disables model behaviour for ROM::Struct and Hanami::Entity
|
13
|
+
# subclasses.
|
14
|
+
def included(klass)
|
15
|
+
@model = false if klass < ::Dry::Struct
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module AttacherMethods
|
21
|
+
attr_reader :repository
|
22
|
+
|
23
|
+
def initialize(repository: nil, **options)
|
24
|
+
super(**options)
|
25
|
+
@repository = repository
|
26
|
+
end
|
27
|
+
|
28
|
+
# The _persistence plugin uses #rom_persist, #rom_reload and #rom? to
|
29
|
+
# implement the following methods:
|
30
|
+
#
|
31
|
+
# * Attacher#persist
|
32
|
+
# * Attacher#atomic_persist
|
33
|
+
# * Attacher#atomic_promote
|
34
|
+
private
|
35
|
+
|
36
|
+
# Updates the record with attachment column values. Used by the
|
37
|
+
# _persistence plugin.
|
38
|
+
def rom_persist
|
39
|
+
rom.update_record(column_values)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Locks the database row and yields the reloaded record. Used by the
|
43
|
+
# _persistence plugin.
|
44
|
+
def rom_reload
|
45
|
+
rom.retrieve_record { |entity| yield entity }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns true if the data attribute represents a JSON or JSONB column.
|
49
|
+
# Used by the _persistence plugin to determine whether serialization
|
50
|
+
# should be skipped.
|
51
|
+
def rom_hash_attribute?
|
52
|
+
return false unless repository
|
53
|
+
|
54
|
+
column = rom.column_type(attribute)
|
55
|
+
column && [:json, :jsonb].include?(column.to_sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns whether the record is a ROM entity. Used by the _persistence
|
59
|
+
# plugin.
|
60
|
+
def rom?
|
61
|
+
record.is_a?(::ROM::Struct)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns internal ROM wrapper object.
|
65
|
+
def rom
|
66
|
+
fail Shrine::Error, "repository is missing" unless repository
|
67
|
+
|
68
|
+
RomWrapper.new(repository: repository, record: record)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class RomWrapper
|
73
|
+
attr_reader :repository, :record_pk
|
74
|
+
|
75
|
+
def initialize(repository:, record: nil)
|
76
|
+
@repository = repository
|
77
|
+
@record_pk = record.send(relation.primary_key)
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_record(attributes)
|
81
|
+
repository.update(record_pk, attributes)
|
82
|
+
end
|
83
|
+
|
84
|
+
def retrieve_record
|
85
|
+
case adapter
|
86
|
+
when :sql
|
87
|
+
repository.transaction do
|
88
|
+
yield record_relation.lock.one!
|
89
|
+
end
|
90
|
+
else
|
91
|
+
yield record_relation.one!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def column_type(attribute)
|
96
|
+
# sends "json" or "jsonb" string for JSON or JSONB column.
|
97
|
+
# returns nil for String column
|
98
|
+
relation.schema[attribute].type.meta[:db_type]
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def record_relation
|
104
|
+
case adapter
|
105
|
+
when :sql, :mongo then relation.by_pk(record_pk)
|
106
|
+
when :elasticsearch then relation.get(record_pk)
|
107
|
+
else
|
108
|
+
fail Shrine::Error, "unsupported ROM adapter: #{adapter.inspect}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def adapter
|
113
|
+
relation.adapter
|
114
|
+
end
|
115
|
+
|
116
|
+
def relation
|
117
|
+
repository.root
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
register_plugin(:rom, Rom)
|
123
|
+
end
|
124
|
+
end
|
data/shrine-rom.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = "shrine-rom"
|
3
|
+
gem.version = "0.1.0"
|
4
|
+
|
5
|
+
gem.required_ruby_version = ">= 2.3"
|
6
|
+
|
7
|
+
gem.summary = "Provides rom-rb integration for Shrine."
|
8
|
+
gem.homepage = "https://github.com/shrinerb/shrine-rom"
|
9
|
+
gem.authors = ["Janko Marohnić", "Ahmad Musaffa"]
|
10
|
+
gem.email = ["janko.marohnic@gmail.com", "musaffa_csemm@yahoo.com"]
|
11
|
+
gem.license = "MIT"
|
12
|
+
|
13
|
+
gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "*.gemspec"]
|
14
|
+
gem.require_path = "lib"
|
15
|
+
|
16
|
+
gem.add_dependency "shrine", "~> 3.0"
|
17
|
+
gem.add_dependency "rom", "~> 5.0"
|
18
|
+
|
19
|
+
gem.add_development_dependency "rake"
|
20
|
+
gem.add_development_dependency "minitest"
|
21
|
+
gem.add_development_dependency "rom-sql"
|
22
|
+
gem.add_development_dependency "sqlite3"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shrine-rom
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Janko Marohnić
|
8
|
+
- Ahmad Musaffa
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-06-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shrine
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rom
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: minitest
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rom-sql
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: sqlite3
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
description:
|
99
|
+
email:
|
100
|
+
- janko.marohnic@gmail.com
|
101
|
+
- musaffa_csemm@yahoo.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- lib/shrine/plugins/rom.rb
|
109
|
+
- shrine-rom.gemspec
|
110
|
+
homepage: https://github.com/shrinerb/shrine-rom
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '2.3'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.3.3
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Provides rom-rb integration for Shrine.
|
133
|
+
test_files: []
|