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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7626ae0687a31a055b912eaa725f049317bc44c38f18ff51b060f71ac188afba
4
- data.tar.gz: 49de3d0d889bf1ab67e1f424f1c9421b47378e2f5ed10ce6c5cb3e261fcc1e92
3
+ metadata.gz: d8b0938bb39253068f0b78cd62841b08aa118f9ae51fb8e8e49c59a47cc5d6dc
4
+ data.tar.gz: 59fa97d3a17ab1b7330a1af92399a09aceb8843b81f1adb4f667580e495685f1
5
5
  SHA512:
6
- metadata.gz: 8775ea40ef291da68cbd8e3527bfc5202a29b30a3664b80649070b288d29c92befb6e596ddcc5a81a8b8ef8af32db6f76302576f1a1a405b3fc2121bdbf54fc3
7
- data.tar.gz: 8cbcf0794b7ad7597f306cc885479afd61ee1eabb030770d2610f776218e2b005a1b3397e65064bdd00181aab1af8abe91c783575c1b29e54c6ba9296d212de4
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- readymade (0.2.1)
4
+ readymade (0.2.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # Readymade 0.2.1
1
+ # Readymade
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/readymade.png)](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
 
@@ -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
- nested_forms.each do |n_form|
83
- n_form.errors.each do |code, text|
84
- errors.add("#{n_form.humanized_name}.#{code}", text)
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 Rails.version.to_f > 6.0
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
+
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Readymade
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.5'
5
5
  end
data/lib/readymade.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'readymade/model/api_attachable'
3
4
  require 'readymade/controller/serialization'
4
5
  require 'readymade/action'
5
6
  require 'readymade/form'
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.1
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-04-21 00:00:00.000000000 Z
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