readymade 0.2.1 → 0.2.5
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 +4 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +1 -1
- data/README.md +46 -1
- data/lib/readymade/form.rb +20 -4
- data/lib/readymade/model/api_attachable.rb +61 -0
- data/lib/readymade/version.rb +1 -1
- data/lib/readymade.rb +1 -0
- data/readymade.gemspec +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8b0938bb39253068f0b78cd62841b08aa118f9ae51fb8e8e49c59a47cc5d6dc
|
4
|
+
data.tar.gz: 59fa97d3a17ab1b7330a1af92399a09aceb8843b81f1adb4f667580e495685f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5496ed0f230582f69b423e15561ba247d5967b44242fe3baa0611f4056e207ab8752dd2360380dc20a3072fea94ceac176f6098b84a07ea263ecd314ff735f3e
|
7
|
+
data.tar.gz: 99a797b196fc7d20c60026b39e5500c7b5a048ce743d92ae37b55412370b429c52a9623cc74031535811ce9743ba43dc197d923cae99fa4a5623ee368cec9ca2
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.2.5] - 2022-05-19
|
5
|
+
|
6
|
+
# Improvements
|
7
|
+
|
8
|
+
* Form#required_attributes returns `[]` if `params[:_destroy]` present
|
9
|
+
|
10
|
+
## [0.2.4] - 2022-05-12
|
11
|
+
|
12
|
+
### Fixes
|
13
|
+
|
14
|
+
* Fix ApiAttachable empty attachments for non hash assignement
|
15
|
+
|
16
|
+
## [0.2.3] - 2022-05-03
|
17
|
+
|
18
|
+
### Features
|
19
|
+
|
20
|
+
* Add `Readymade::Model::ApiAttachable` - add base64 format to your ActiveStorage
|
21
|
+
|
4
22
|
## [0.2.1] - 2022-04-21
|
5
23
|
|
6
24
|
### Improvements
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# Readymade
|
1
|
+
# Readymade
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/readymade)
|
2
4
|
|
3
5
|
This gems contains basic components to follow [ABDI architecture](https://github.com/OrestF/OrestF/blob/master/abdi/ABDI_architecture.md)
|
4
6
|
|
@@ -149,6 +151,49 @@ class Orders::Operations::Create < Readymade::Operation
|
|
149
151
|
end
|
150
152
|
```
|
151
153
|
|
154
|
+
### Readymade::Controller::Serialization
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
class MyController < ApplicationController
|
158
|
+
include Readymade::Controller::Serialization
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
Serialization helpers for controllers.
|
163
|
+
Dependencies that must be installed on your own:
|
164
|
+
- [blueprinter](https://rubygems.org/gems/blueprinter/)
|
165
|
+
- [pagy](https://rubygems.org/gems/pagy)
|
166
|
+
- [api-pagination](https://rubygems.org/gems/api-pagination)
|
167
|
+
|
168
|
+
### Readymade::Model::ApiAttachable
|
169
|
+
|
170
|
+
Add base64 attachments format for your models
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
class User < ApplicationRecord
|
174
|
+
has_one_attached :avatar
|
175
|
+
has_many_attached :images
|
176
|
+
include Readymade::Model::ApiAttachable
|
177
|
+
# must be included after has_one_attached, has_many_attached declaration
|
178
|
+
# api_file = {
|
179
|
+
# base64: 'iVBORw0KGgoAAA....',
|
180
|
+
# filename: 'my_avatar.png'
|
181
|
+
# }
|
182
|
+
# record.avatar = api_file 🎉
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
copy [spec/support/api_attachable.rb](./spec/support/api_attachable.rb)
|
187
|
+
```ruby
|
188
|
+
def to_api_file(file)
|
189
|
+
{ base64: Base64.encode64(file.read), filename: file.original_filename }
|
190
|
+
end
|
191
|
+
```
|
192
|
+
```ruby
|
193
|
+
# rspec example
|
194
|
+
let(:avatar) { Rack::Test::UploadedFile.new(Rails.root.join('spec/support/assets/test-image.png'), 'image/png') }
|
195
|
+
let(:params) { { user: attributes_for(:user).merge!(avatar: to_api_file(avatar)) } }
|
196
|
+
```
|
152
197
|
|
153
198
|
## Development
|
154
199
|
|
data/lib/readymade/form.rb
CHANGED
@@ -45,6 +45,8 @@ module Readymade
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def required_attributes
|
48
|
+
return [] if params.try(:[], :_destroy).present?
|
49
|
+
|
48
50
|
@required_attributes ||= self.class::REQUIRED_ATTRIBUTES
|
49
51
|
end
|
50
52
|
|
@@ -79,9 +81,17 @@ module Readymade
|
|
79
81
|
|
80
82
|
# copy errors from nested forms into parent form
|
81
83
|
def sync_nested_errors(nested_forms)
|
82
|
-
|
83
|
-
|
84
|
-
errors.
|
84
|
+
if rails_errors_v2?
|
85
|
+
nested_forms.each do |n_form|
|
86
|
+
n_form.errors.each do |code|
|
87
|
+
errors.add("#{n_form.humanized_name}.#{code.attribute}", code.message)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
else
|
91
|
+
nested_forms.each do |n_form|
|
92
|
+
n_form.errors.each do |code, text|
|
93
|
+
errors.add("#{n_form.humanized_name}.#{code}", text)
|
94
|
+
end
|
85
95
|
end
|
86
96
|
end
|
87
97
|
|
@@ -92,7 +102,7 @@ module Readymade
|
|
92
102
|
def sync_errors(from: self, to: record)
|
93
103
|
return if [from, to].any?(&:blank?)
|
94
104
|
|
95
|
-
if
|
105
|
+
if rails_errors_v2?
|
96
106
|
from.errors.messages.each do |key, values|
|
97
107
|
Array.wrap(values).uniq.each do |uv|
|
98
108
|
to.errors.add(key, uv)
|
@@ -145,6 +155,12 @@ module Readymade
|
|
145
155
|
{}
|
146
156
|
end
|
147
157
|
|
158
|
+
private
|
159
|
+
|
160
|
+
def rails_errors_v2?
|
161
|
+
Rails.version.to_f > 6.0
|
162
|
+
end
|
163
|
+
|
148
164
|
# EXAMPLE
|
149
165
|
# class Items::Forms::Create::Value < ::Readymade::Form
|
150
166
|
# PERMITTED_ATTRIBUTES = %i[vat_percent price_type item_category].freeze
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Readymade
|
4
|
+
module Model
|
5
|
+
module ApiAttachable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
# must be included after has_one_attached, has_many_attached declaration
|
8
|
+
# api_file = {
|
9
|
+
# base64: 'iVBORw0KGgoAAA....',
|
10
|
+
# filename: 'my_avatar.png'
|
11
|
+
# }
|
12
|
+
# record.avatar = api_file 🎉
|
13
|
+
|
14
|
+
included do
|
15
|
+
has_one_attached_reflections.map(&:name).each do |attachment_method_name|
|
16
|
+
define_method("#{attachment_method_name}=") do |attachment_file|
|
17
|
+
attachment_file = api_attachment_to_uploaded(attachment_file) if api_attachable_format?(attachment_file)
|
18
|
+
super(attachment_file)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
has_many_attached_reflections.map(&:name).each do |attachment_method_name|
|
23
|
+
define_method("#{attachment_method_name}=") do |attachment_file|
|
24
|
+
attachment_file = Array.wrap(attachment_file).map do |af|
|
25
|
+
api_attachable_format?(af) ? api_attachment_to_uploaded(af) : af
|
26
|
+
end
|
27
|
+
super(attachment_file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class_methods do
|
33
|
+
# rubocop:disable Naming/PredicateName
|
34
|
+
def has_one_attached_reflections
|
35
|
+
reflect_on_all_attachments.filter { |association| association.instance_of?(ActiveStorage::Reflection::HasOneAttachedReflection) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_many_attached_reflections
|
39
|
+
reflect_on_all_attachments.filter { |association| association.instance_of?(ActiveStorage::Reflection::HasManyAttachedReflection) }
|
40
|
+
end
|
41
|
+
# rubocop:enable Naming/PredicateName
|
42
|
+
end
|
43
|
+
|
44
|
+
def api_attachable_format?(attachment_file)
|
45
|
+
attachment_file.respond_to?(:key?) && attachment_file.key?('base64') && attachment_file.key?('filename')
|
46
|
+
end
|
47
|
+
|
48
|
+
def api_attachment_to_uploaded(attachment_file)
|
49
|
+
ActionDispatch::Http::UploadedFile.new(
|
50
|
+
tempfile: Tempfile.new(attachment_file[:filename]).tap do |tf|
|
51
|
+
tf.binmode
|
52
|
+
tf.write(Base64.decode64(attachment_file[:base64]))
|
53
|
+
end,
|
54
|
+
filename: attachment_file[:filename],
|
55
|
+
type: Mime::Type.lookup_by_extension(File.extname(attachment_file[:filename])[1..]).to_s
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/lib/readymade/version.rb
CHANGED
data/lib/readymade.rb
CHANGED
data/readymade.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
26
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
27
|
end
|
28
|
+
spec.files << 'lib/readymade/model/api_attachable.rb'
|
28
29
|
spec.files << 'lib/readymade/controller/serialization.rb'
|
29
30
|
spec.bindir = 'exe'
|
30
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: readymade
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OrestF
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/readymade/controller/serialization.rb
|
77
77
|
- lib/readymade/form.rb
|
78
78
|
- lib/readymade/instant_form.rb
|
79
|
+
- lib/readymade/model/api_attachable.rb
|
79
80
|
- lib/readymade/operation.rb
|
80
81
|
- lib/readymade/response.rb
|
81
82
|
- lib/readymade/version.rb
|