ar2dto 0.0.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +120 -5
- data/lib/ar2dto/active_model.rb +32 -0
- data/lib/ar2dto/config.rb +23 -0
- data/lib/ar2dto/converter.rb +67 -0
- data/lib/ar2dto/dto.rb +35 -0
- data/lib/ar2dto/has_dto.rb +47 -0
- data/lib/ar2dto/model_config.rb +45 -0
- data/lib/ar2dto/version.rb +1 -1
- data/lib/ar2dto.rb +18 -1
- metadata +116 -8
- data/lib/ar2dto/base.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cd53b73405906d2f5110639476b122164c9ed031ee9c790738060616e8b37d9
|
4
|
+
data.tar.gz: 01c473e3681f934e0fca8991d0dd49f637a93920134c4a7baedaefed344e325b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65921f1573108b6cb20bcd39457a51e6e71bd9c1c49e44247f799534c827a362980438aaad65350cf107e627f915ebfd2996c32e4d1969f3aa07196cfe159482
|
7
|
+
data.tar.gz: 8a659e862bafd7fc0165f4b7f38ae385fa22b9550194df05cbb42f11ce0709f8bd5a443cb61c874b7096b41e9e48a3d6dd28379c94899e3ddff2aa67fed1edc8
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# AR2DTO ![AR2DTO](docs/images/logo.png)
|
2
2
|
|
3
|
-
AR2DTO (ActiveRecord to DTO, pronounced R2-D2 or Artoo-Detoo) is a gem that lets you create DTOs (data transfer objects) from your ActiveRecord models. It is a simple and small gem
|
3
|
+
AR2DTO (ActiveRecord to DTO, pronounced R2-D2 or Artoo-Detoo) is a gem that lets you create [DTOs](https://martinfowler.com/eaaCatalog/dataTransferObject.html) (data transfer objects) from your ActiveRecord models. It is a simple and small gem to encourage the usage of simpler objects across an app rather than ActiveRecord models, to help with coupling issues in large Rails apps.
|
4
4
|
|
5
5
|
![CI](https://github.com/santib/ar2dto/workflows/CI/badge.svg)
|
6
6
|
|
@@ -10,17 +10,27 @@ AR2DTO (ActiveRecord to DTO, pronounced R2-D2 or Artoo-Detoo) is a gem that lets
|
|
10
10
|
- [Why AR2DTO?](#why-ar2dto)
|
11
11
|
- [Installation](#installation)
|
12
12
|
- [Usage](#usage)
|
13
|
+
- [Global configuration](#global-configuration)
|
13
14
|
- [Setting up your models](#setting-up-your-models)
|
15
|
+
- [DTO class](#dto-class)
|
16
|
+
- [#to_dto](#to_dto)
|
17
|
+
- [.to_dto](#to_dto-1)
|
14
18
|
- [Development](#development)
|
15
19
|
- [Contributing](#contributing)
|
16
20
|
- [License](#license)
|
17
21
|
- [Code of Conduct](#code-of-conduct)
|
18
22
|
|
19
23
|
## Motivation
|
20
|
-
|
24
|
+
|
25
|
+
ActiveRecord is a very powerful tool and extensively used in most Rails apps. When working on large Rails apps, having such powerful objects all over the place can have a negative impact on the maintainability of the app. This is even more clear when trying to create domain boundaries within a Rails monolith. When there is communication between different components you probably don't want to share an ActiveRecord model with other components, if you do that, you'll be giving direct access to your component's tables from anywhere. For that reason, we want to create POROs that look like ActiveRecord models but that are much simpler and only carry data. This could be done by hand, but with this gem, we are trying to help you avoid having to write all the boilerplate to create these objects. As a corollary, by using this gem you are standardizing how things are done, and how your data-only objects look like.
|
21
26
|
|
22
27
|
### Why AR2DTO?
|
23
|
-
|
28
|
+
|
29
|
+
- It lets you work with objects that are similar to ActiveRecord models but without DB access or business logic.
|
30
|
+
- It impedes ActiveRecord models leaking through its methods.
|
31
|
+
- It helps you reduce boilerplate.
|
32
|
+
- It provides a standard way to work with data-only objects.
|
33
|
+
- It is a very small gem focused on solving one specific problem.
|
24
34
|
|
25
35
|
## Installation
|
26
36
|
|
@@ -39,10 +49,115 @@ Or install it yourself as:
|
|
39
49
|
$ gem install ar2dto
|
40
50
|
|
41
51
|
## Usage
|
42
|
-
|
52
|
+
|
53
|
+
In the following sections, we explain the API provided by the gem and some basic usage.
|
54
|
+
|
55
|
+
Many aspects of AR2DTO are [configurable for individual models](#setting-up-your-models); typically this is achieved by passing options to the has_dto method within a given model. Some aspects of AR2DTO are [configured globally](#global-configuration) for all models.
|
56
|
+
|
57
|
+
### Global Configuration
|
58
|
+
Global configuration options affect all threads and models where has_dto has been defined. A common place to put these settings is in a Rails initializer file such as `config/initializers/ar2dto.rb`.
|
59
|
+
These settings are assigned directly on the `AR2DTO.configure` object.
|
60
|
+
|
61
|
+
Configuration options are:
|
62
|
+
- `active_model_compliace`: DTO objects behaves like `ActiveModel` objects to play well with other parts of Rails and its ecosystem. Defaults to `true`.
|
63
|
+
- `except`: array of attributes to exclude from the DTO. Defaults to `[]`.
|
64
|
+
- `delete_suffix`: suffix to be delete from the model name. Defaults to `nil`.
|
65
|
+
- `add_suffix`: suffix to be added to the model name. Defaults to `"DTO"`.
|
66
|
+
|
67
|
+
Syntax examples:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
# config/initializers/ar2dto.rb
|
71
|
+
|
72
|
+
AR2DTO.configure do |config|
|
73
|
+
config.active_model_compliance = true
|
74
|
+
config.except = [:updated_at]
|
75
|
+
config.delete_suffix = nil
|
76
|
+
config.add_suffix = "DTO"
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
OR
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# config/initializers/ar2dto.rb
|
84
|
+
|
85
|
+
AR2DTO.configure.active_model_compliance = true
|
86
|
+
AR2DTO.configure.except = [:updated_at]
|
87
|
+
AR2DTO.configure.delete_suffix = nil
|
88
|
+
AR2DTO.configure.add_suffix = "DTO"
|
89
|
+
```
|
90
|
+
|
91
|
+
These options are intended to be set only once, during app initialization.
|
43
92
|
|
44
93
|
### Setting up your models
|
45
|
-
|
94
|
+
|
95
|
+
To use the gem, you need to add `has_dto` to your ActiveRecord models. For example:
|
96
|
+
```ruby
|
97
|
+
class User < ApplicationRecord
|
98
|
+
has_dto
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
This will dynamically create a class called `UserDTO` and will add two methods to your ActiveRecord model: [#to_dto](#to_dto) and [.to_dto](#to_dto-1).
|
103
|
+
|
104
|
+
### DTO class
|
105
|
+
|
106
|
+
This class is dynamically created based on your models that declare `has_dto`. The goal of these classes is to be data-only. They don't have access to the DB, business logic, or calculate things on the fly. They just store the data and provide them in a read-only fashion through plain simple methods.
|
107
|
+
|
108
|
+
In addition to that, and optionally, you can have these objects be compliant with the [ActiveModel API](https://github.com/rails/rails/blob/main/activemodel/lib/active_model/lint.rb), you can do that by configuring it globally with:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
# config/initializers/ar2dto.rb
|
112
|
+
|
113
|
+
AR2DTO.configure do |config|
|
114
|
+
config.active_model_compliance = true
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
With this, it'll be even easier to interchange ActiveRecord models for DTOs, because other parts of Rails and other gems will continue to work (e.g. Rails route helpers).
|
119
|
+
|
120
|
+
### #to_dto
|
121
|
+
|
122
|
+
When calling `#to_dto` on an ActiveRecord model, a DTO object will be initialized with the model attributes. As an example:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
user = User.create!(name: 'John', email: 'john@example.com')
|
126
|
+
user_dto = user.to_dto
|
127
|
+
# #<UserDTO:0x00007fab8ce66a10 @name="John" @email="john@example.com">
|
128
|
+
```
|
129
|
+
|
130
|
+
`user_dto` will be an instance of `UserDTO` and, by default, it will be initialized with the same attributes as the model, that is: `id`, `name`, `email`, `created_at`, and `updated_at`.
|
131
|
+
|
132
|
+
You can then use `user_dto` across your app, and even share it with other components, without having to worry about others making queries, modifying data, or even running business logic, where they shouldn't.
|
133
|
+
|
134
|
+
This method accepts the same options as `ActiveRecord`'s `#as_json`, they are `except`, `only`, `methods`, and `include`.
|
135
|
+
|
136
|
+
`except`
|
137
|
+
Excludes attributes from the model when creating the DTO.
|
138
|
+
|
139
|
+
`only`
|
140
|
+
Selects the only attributes that should be included when creating the DTO.
|
141
|
+
|
142
|
+
`methods`
|
143
|
+
Run methods defined in the model and stores the values into the DTO as attributes.
|
144
|
+
|
145
|
+
`include`
|
146
|
+
Includes an association into the DTO. The association is also converted into a DTO in case of a `has_one`/`belongs_to` association, or into an `Array` of DTOs in case of a `has_many` association. The associations accepts the same options explained above.
|
147
|
+
|
148
|
+
### .to_dto
|
149
|
+
|
150
|
+
This method is similar to `#to_dto` but meant for `ActiveRecord::Relation`. So that running:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
User.last(10).to_dto
|
154
|
+
```
|
155
|
+
|
156
|
+
will return an `Array` consisting of 10 `UserDTO`. With this you are forcing the executing of the query, having collections of simple data objects, and avoiding other parts of the app from modifying the query.
|
157
|
+
|
158
|
+
It accepts the same options as `#to_dto` and uses them create each DTO.
|
159
|
+
|
160
|
+
:warning: **Warning!** Given that this method executes the query and brings records into memory, you have to be careful when and how to use it. You may not want to bring all records from a large table into memory. Consider combining it with things such as pagination or batch processing.
|
46
161
|
|
47
162
|
## Development
|
48
163
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
module ActiveModel
|
5
|
+
def self.included(base)
|
6
|
+
base.include ::ActiveModel::Conversion
|
7
|
+
base.extend ::ActiveModel::Naming
|
8
|
+
base.extend ::ActiveModel::Translation
|
9
|
+
base.extend ::AR2DTO::ActiveModel::ClassMethods
|
10
|
+
|
11
|
+
base.class_eval do
|
12
|
+
def persisted?
|
13
|
+
id.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
def errors
|
17
|
+
@errors ||= ::ActiveModel::Errors.new(self.class.original_model)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_partial_path
|
21
|
+
self.class.original_model._to_partial_path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def model_name
|
28
|
+
::ActiveModel::Name.new(original_model)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
class Config
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def self.reset!
|
8
|
+
instance.active_model_compliance = true
|
9
|
+
instance.except = []
|
10
|
+
instance.delete_suffix = nil
|
11
|
+
instance.add_suffix = "DTO"
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :active_model_compliance, :except, :delete_suffix, :add_suffix
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@active_model_compliance = true
|
18
|
+
@except = []
|
19
|
+
@delete_suffix = nil
|
20
|
+
@add_suffix = "DTO"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
class Converter
|
5
|
+
ALLOWED_TYPES = [Symbol, BigDecimal, Regexp, IO, Range, Time, Date, DateTime,
|
6
|
+
URI::Generic, Pathname, IPAddr, Process::Status, Exception].freeze
|
7
|
+
attr_reader :model, :options
|
8
|
+
|
9
|
+
def initialize(model, options)
|
10
|
+
@model = model
|
11
|
+
@options = apply_configs(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def serializable_hash
|
15
|
+
hash = model.serializable_hash(options&.except(:methods, :include))
|
16
|
+
hash = add_methods(hash)
|
17
|
+
add_associations(hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def apply_configs(options)
|
23
|
+
options[:except] = Array(model.class.ar2dto.except) | Array(options[:except])
|
24
|
+
options
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_methods(hash)
|
28
|
+
options&.dig(:methods)&.each do |method|
|
29
|
+
hash[method.to_s] = data_only(model.send(method))
|
30
|
+
end
|
31
|
+
hash
|
32
|
+
end
|
33
|
+
|
34
|
+
def data_only(object)
|
35
|
+
if object.respond_to?(:to_dto)
|
36
|
+
object.to_dto
|
37
|
+
elsif object.is_a?(::AR2DTO::DTO) || ALLOWED_TYPES.include?(object.class)
|
38
|
+
object
|
39
|
+
else
|
40
|
+
object.as_json
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_associations(hash)
|
45
|
+
includes.each do |association, opts|
|
46
|
+
records = model.send(association)
|
47
|
+
hash[association.to_s] = records ? records_dto(records, opts) : nil
|
48
|
+
end
|
49
|
+
hash
|
50
|
+
end
|
51
|
+
|
52
|
+
def includes
|
53
|
+
includes = options&.dig(:include)
|
54
|
+
return includes if includes.is_a?(Hash)
|
55
|
+
|
56
|
+
Array(includes).flat_map { |n| n.is_a?(Hash) ? n.to_a : [[n, {}]] }.to_h
|
57
|
+
end
|
58
|
+
|
59
|
+
def records_dto(records, opts)
|
60
|
+
if records.respond_to?(:to_ary)
|
61
|
+
records.to_ary.map { |a| a.to_dto(opts) }
|
62
|
+
else
|
63
|
+
records.to_dto(opts)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/ar2dto/dto.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
class DTO
|
5
|
+
def self.[](original_model)
|
6
|
+
Class.new(self) do
|
7
|
+
include ::AR2DTO::ActiveModel if original_model.ar2dto.active_model_compliance
|
8
|
+
define_singleton_method(:original_model) { original_model }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(data = {})
|
13
|
+
attribute_names = self.class.original_model.attribute_names
|
14
|
+
|
15
|
+
data.each do |key, value|
|
16
|
+
if attribute_names.include?(key)
|
17
|
+
instance_variable_set("@#{key}", value)
|
18
|
+
singleton_class.attr_reader(key)
|
19
|
+
else
|
20
|
+
define_singleton_method(key) { value }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
super()
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
if other.instance_of?(self.class)
|
29
|
+
as_json == other.as_json
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
# Extensions to `ActiveRecord::Base`.
|
5
|
+
module HasDTO
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ::AR2DTO::HasDTO::ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Declare this in your model to expose the DTO helpers.
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def has_dto(options = {})
|
15
|
+
include ::AR2DTO::HasDTO::InstanceMethods
|
16
|
+
ar2dto.setup_config(options)
|
17
|
+
|
18
|
+
begin
|
19
|
+
ar2dto.namespaced_class_name.constantize
|
20
|
+
rescue NameError
|
21
|
+
ar2dto.namespace.const_set(ar2dto.class_name, AR2DTO::DTO[self])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api public
|
26
|
+
def to_dto(options = {})
|
27
|
+
all.map { |record| record.to_dto(options) }
|
28
|
+
end
|
29
|
+
|
30
|
+
# @api public
|
31
|
+
def ar2dto
|
32
|
+
@ar2dto ||= AR2DTO::ModelConfig.new(self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Wrap the following methods in a module so we can include them only in the
|
37
|
+
# ActiveRecord models that declare `has_dto`.
|
38
|
+
module InstanceMethods
|
39
|
+
# @api public
|
40
|
+
def to_dto(options = {})
|
41
|
+
self.class.ar2dto.namespaced_class_name.constantize.new(
|
42
|
+
AR2DTO::Converter.new(self, options).serializable_hash
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AR2DTO
|
4
|
+
class ModelConfig
|
5
|
+
attr_reader :model, :model_config
|
6
|
+
|
7
|
+
def initialize(model)
|
8
|
+
@model = model
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup_config(model_config)
|
12
|
+
@model_config ||= model_config
|
13
|
+
end
|
14
|
+
|
15
|
+
def active_model_compliance
|
16
|
+
@active_model_compliance ||= global_config.active_model_compliance
|
17
|
+
end
|
18
|
+
|
19
|
+
def except
|
20
|
+
@except ||= Array(global_config.except) | Array(model_config[:except])
|
21
|
+
end
|
22
|
+
|
23
|
+
def class_name
|
24
|
+
@class_name ||= namespaced_class_name.split("::").last
|
25
|
+
end
|
26
|
+
|
27
|
+
def namespace
|
28
|
+
@namespace ||= namespaced_class_name.deconstantize.presence&.constantize || Object
|
29
|
+
end
|
30
|
+
|
31
|
+
def namespaced_class_name
|
32
|
+
@namespaced_class_name ||= model_config[:class_name] || model_name_replaced_suffix
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def model_name_replaced_suffix
|
38
|
+
"#{model.name.delete_suffix(global_config.delete_suffix.to_s)}#{global_config.add_suffix}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def global_config
|
42
|
+
AR2DTO::Config.instance
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/ar2dto/version.rb
CHANGED
data/lib/ar2dto.rb
CHANGED
@@ -1,8 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_record"
|
4
|
+
require "active_model"
|
5
|
+
require "singleton"
|
6
|
+
|
7
|
+
require_relative "ar2dto/active_model"
|
8
|
+
require_relative "ar2dto/dto"
|
9
|
+
require_relative "ar2dto/config"
|
10
|
+
require_relative "ar2dto/converter"
|
11
|
+
require_relative "ar2dto/model_config"
|
3
12
|
require_relative "ar2dto/version"
|
13
|
+
require_relative "ar2dto/has_dto"
|
14
|
+
|
15
|
+
ActiveRecord::Base.include ::AR2DTO::HasDTO
|
4
16
|
|
5
17
|
module AR2DTO
|
6
18
|
class Error < StandardError; end
|
7
|
-
|
19
|
+
|
20
|
+
def self.configure
|
21
|
+
@config ||= AR2DTO::Config.instance
|
22
|
+
yield @config if block_given?
|
23
|
+
@config
|
24
|
+
end
|
8
25
|
end
|
metadata
CHANGED
@@ -1,15 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar2dto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Santiago Bartesaghi
|
8
|
-
|
8
|
+
- Martín Jaime Morón
|
9
|
+
- Sebastian Herrera
|
10
|
+
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
|
-
date: 2022-
|
13
|
+
date: 2022-07-26 00:00:00.000000000 Z
|
12
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activemodel
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '5.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '5.2'
|
13
29
|
- !ruby/object:Gem::Dependency
|
14
30
|
name: activerecord
|
15
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,9 +40,95 @@ dependencies:
|
|
24
40
|
- - ">="
|
25
41
|
- !ruby/object:Gem::Version
|
26
42
|
version: '5.2'
|
27
|
-
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: database_cleaner-active_record
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.8.0
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.8.0
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rake
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 13.0.1
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 13.0.1
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rspec
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.9.0
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 3.9.0
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rubocop
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 1.28.2
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.28.2
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: sqlite3
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - "~>"
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 1.4.2
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - "~>"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.4.2
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: zeitwerk
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 2.6.0
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 2.6.0
|
127
|
+
description:
|
28
128
|
email:
|
29
129
|
- santib@hey.com
|
130
|
+
- martinmoron7@gmail.com
|
131
|
+
- sebaherrera93@gmail.com
|
30
132
|
executables: []
|
31
133
|
extensions: []
|
32
134
|
extra_rdoc_files: []
|
@@ -34,7 +136,12 @@ files:
|
|
34
136
|
- LICENSE.txt
|
35
137
|
- README.md
|
36
138
|
- lib/ar2dto.rb
|
37
|
-
- lib/ar2dto/
|
139
|
+
- lib/ar2dto/active_model.rb
|
140
|
+
- lib/ar2dto/config.rb
|
141
|
+
- lib/ar2dto/converter.rb
|
142
|
+
- lib/ar2dto/dto.rb
|
143
|
+
- lib/ar2dto/has_dto.rb
|
144
|
+
- lib/ar2dto/model_config.rb
|
38
145
|
- lib/ar2dto/version.rb
|
39
146
|
homepage: https://github.com/santib/ar2dto
|
40
147
|
licenses:
|
@@ -44,7 +151,8 @@ metadata:
|
|
44
151
|
source_code_uri: https://github.com/santib/ar2dto
|
45
152
|
bug_tracker_uri: https://github.com/santib/ar2dto/issues
|
46
153
|
changelog_uri: https://github.com/santib/ar2dto/releases
|
47
|
-
|
154
|
+
rubygems_mfa_required: 'true'
|
155
|
+
post_install_message:
|
48
156
|
rdoc_options: []
|
49
157
|
require_paths:
|
50
158
|
- lib
|
@@ -59,8 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
167
|
- !ruby/object:Gem::Version
|
60
168
|
version: '0'
|
61
169
|
requirements: []
|
62
|
-
rubygems_version: 3.
|
63
|
-
signing_key:
|
170
|
+
rubygems_version: 3.0.3
|
171
|
+
signing_key:
|
64
172
|
specification_version: 4
|
65
173
|
summary: Easing the creation of DTOs from your ActiveRecord models.
|
66
174
|
test_files: []
|
data/lib/ar2dto/base.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module AR2DTO
|
2
|
-
module Base
|
3
|
-
def self.included(model)
|
4
|
-
namespace = model.name.deconstantize.presence&.constantize || Object
|
5
|
-
|
6
|
-
namespace.const_set("#{model.name.split('::').last}DTO", Class.new do
|
7
|
-
include ::ActiveModel::Model
|
8
|
-
attr_reader :attributes
|
9
|
-
attr_accessor *model.column_names
|
10
|
-
|
11
|
-
def initialize(attributes)
|
12
|
-
@attributes = attributes
|
13
|
-
super
|
14
|
-
end
|
15
|
-
|
16
|
-
def ==(other)
|
17
|
-
attributes == other.attributes
|
18
|
-
end
|
19
|
-
end)
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_dto
|
23
|
-
"#{self.class.name}DTO".constantize.new(attributes)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|