shrine-rom 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|