blueprinter 0.30.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +24 -2
- data/lib/blueprinter/base.rb +3 -0
- data/lib/blueprinter/configuration.rb +10 -0
- data/lib/blueprinter/extension.rb +22 -0
- data/lib/blueprinter/extensions.rb +37 -0
- data/lib/blueprinter/reflection.rb +71 -0
- data/lib/blueprinter/version.rb +1 -1
- data/lib/blueprinter/view.rb +0 -4
- data/lib/blueprinter/view_collection.rb +13 -1
- data/lib/blueprinter.rb +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbfbe1f528a76df294a8a0a481287bae62501177d7ce4a61d9123b0f86b324ad
|
4
|
+
data.tar.gz: fd176efc51674471cf7626e8e88bb9bd67c7b6a4f3c9349be1f9526969abb1de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b8d633ae1d043fd0093a767da7bc75b37d771bbc1ea9188d28a2ae0645023f5c8cf54b20733f3d0b5d4f234df0ed017c850d3b5a2a8dae2f29f865dbd9bf6df
|
7
|
+
data.tar.gz: 8ec5c9f89365950a92ae56400898bf9b1a5b8e372905d6be66024b6f733d11b85cd23bf2374eccb0d82e21b25c377f3b67cef2514db7ffd9b378605986bb2ea7
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 1.0.1 - 2024/01/19
|
2
|
+
* 🐛 [BUGFIX] Fixes an issue where serialization performance would become degraded when using a Blueprint that leverages transformers. See [#381](https://github.com/procore-oss/blueprinter/pull/381). Thanks to [@Pritilender](https://github.com/Pritilender).
|
3
|
+
|
4
|
+
## 1.0.0 - 2024/01/17
|
5
|
+
* 🚀 [BREAKING] Allow transformers to be included across views. See [README](https://github.com/procore-oss/blueprinter#transform-across-views), PR [#372](https://github.com/procore-oss/blueprinter/pull/372) and issue [#225](https://github.com/procore-oss/blueprinter/issues/225) for details. Note this changes the behavior of transformers which were previously only applied to the view they were defined on. Thanks to [@njbbaer](https://github.com/njbbaer) and [@bhooshiek-narendiran](https://github.com/bhooshiek-narendiran).
|
6
|
+
* 🚀 [FEATURE] Introduce extension API, with initial support for pre_render hook. See [#358](https://github.com/procore-oss/blueprinter/pull/358) for details. Thanks to [@jhollinger](https://github.com/jhollinger).
|
7
|
+
* 💅 [ENHANCEMENT] Add reflection on views, fields, and associations. See PR [#357](https://github.com/procore-oss/blueprinter/pull/357), and issue [#341](https://github.com/procore-oss/blueprinter/issues/341) for details. Thanks to [@jhollinger](https://github.com/jhollinger).
|
8
|
+
|
1
9
|
## 0.30.0 - 2023/09/16
|
2
10
|
* 🚀 [FEATURE] Allow configuring custom array-like classes to be treated as collections when serializing. More details can be found [here](https://github.com/procore-oss/blueprinter/pull/327). Thanks to [@toddnestor](https://github.com/toddnestor).
|
3
11
|
* 💅 [ENHANCEMENT] Reduce object allocations in fields calculations to save some memory. More details can be found [here](https://github.com/procore-oss/blueprinter/pull/327). Thanks to [@nametoolong](https://github.com/nametoolong).
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[![Test](https://github.com/procore-oss/blueprinter/actions/workflows/test.yaml/badge.svg?branch=master)](https://github.com/procore-oss/blueprinter/actions/workflows/test.yaml)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/blueprinter.svg)](https://badge.fury.io/rb/blueprinter)
|
3
|
-
[![
|
3
|
+
[![Discord](https://img.shields.io/badge/Chat-EDEDED?logo=discord)](https://discord.gg/PbntEMmWws)
|
4
4
|
|
5
5
|
<img src="blueprinter_logo.svg" width="25%">
|
6
6
|
|
@@ -765,7 +765,7 @@ processing and transforming of resulting view field hashes prior to serializatio
|
|
765
765
|
|
766
766
|
Use `transform` to specify one transformer to be included for serialization.
|
767
767
|
A transformer is a class, extending `Blueprinter::Transformer` and implementing the `transform` method.
|
768
|
-
|
768
|
+
The modified `hash` object will be the resulting hash passed to serialization.
|
769
769
|
|
770
770
|
#### Example
|
771
771
|
|
@@ -800,6 +800,28 @@ class UserBlueprint < Blueprinter::Base
|
|
800
800
|
end
|
801
801
|
```
|
802
802
|
|
803
|
+
#### Transform across views
|
804
|
+
|
805
|
+
Transformers can be included across views:
|
806
|
+
|
807
|
+
```ruby
|
808
|
+
class UserBlueprint < Blueprinter::Base
|
809
|
+
transform DefaultTransformer
|
810
|
+
|
811
|
+
view :normal do
|
812
|
+
transform ViewTransformer
|
813
|
+
end
|
814
|
+
|
815
|
+
view :extended do
|
816
|
+
include_view :normal
|
817
|
+
end
|
818
|
+
end
|
819
|
+
```
|
820
|
+
|
821
|
+
Both the `normal` and `extended` views have `DefaultTransformer` and `ViewTransformer` applied.
|
822
|
+
|
823
|
+
Transformers are executed in a top-down order, so `DefaultTransformer` will be executed first, followed by `ViewTransformer`.
|
824
|
+
|
803
825
|
#### Global Transforms
|
804
826
|
|
805
827
|
You can also specify global default transformers. Create one or more transformer classes extending from `Blueprinter::Transformer` and set the `default_transformers` configuration
|
data/lib/blueprinter/base.rb
CHANGED
@@ -17,10 +17,12 @@ require_relative 'helpers/base_helpers'
|
|
17
17
|
require_relative 'view'
|
18
18
|
require_relative 'view_collection'
|
19
19
|
require_relative 'transformer'
|
20
|
+
require_relative 'reflection'
|
20
21
|
|
21
22
|
module Blueprinter
|
22
23
|
class Base
|
23
24
|
include BaseHelpers
|
25
|
+
extend Reflection
|
24
26
|
|
25
27
|
# Specify a field or method name used as an identifier. Usually, this is
|
26
28
|
# something like :id
|
@@ -256,6 +258,7 @@ module Blueprinter
|
|
256
258
|
def self.prepare(object, view_name:, local_options:, root: nil, meta: nil)
|
257
259
|
raise BlueprinterError, "View '#{view_name}' is not defined" unless view_collection.view? view_name
|
258
260
|
|
261
|
+
object = Blueprinter.configuration.extensions.pre_render(object, self, view_name, local_options)
|
259
262
|
data = prepare_data(object, view_name, local_options)
|
260
263
|
prepend_root_and_meta(data, root, meta)
|
261
264
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'extensions'
|
4
|
+
|
3
5
|
module Blueprinter
|
4
6
|
class Configuration
|
5
7
|
attr_accessor :association_default, :datetime_format, :deprecations, :field_default, :generator, :if, :method,
|
@@ -22,6 +24,14 @@ module Blueprinter
|
|
22
24
|
@custom_array_like_classes = []
|
23
25
|
end
|
24
26
|
|
27
|
+
def extensions
|
28
|
+
@extensions ||= Extensions.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def extensions=(list)
|
32
|
+
@extensions = Extensions.new(list)
|
33
|
+
end
|
34
|
+
|
25
35
|
def array_like_classes
|
26
36
|
@array_like_classes ||= [
|
27
37
|
Array,
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blueprinter
|
4
|
+
#
|
5
|
+
# Base class for all extensions. All extension methods are implemented as no-ops.
|
6
|
+
#
|
7
|
+
class Extension
|
8
|
+
#
|
9
|
+
# Called eary during "render", this method receives the object to be rendered and
|
10
|
+
# may return a modified (or new) object to be rendered.
|
11
|
+
#
|
12
|
+
# @param object [Object] The object to be rendered
|
13
|
+
# @param _blueprint [Class] The Blueprinter class
|
14
|
+
# @param _view [Symbol] The blueprint view
|
15
|
+
# @param _options [Hash] Options passed to "render"
|
16
|
+
# @return [Object] The object to continue rendering
|
17
|
+
#
|
18
|
+
def pre_render(object, _blueprint, _view, _options)
|
19
|
+
object
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blueprinter
|
4
|
+
#
|
5
|
+
# Stores and runs Blueprinter extensions. An extension is any object that implements one or more of the
|
6
|
+
# extension methods:
|
7
|
+
#
|
8
|
+
# The Render Extension intercepts an object before rendering begins. The return value from this
|
9
|
+
# method is what is ultimately rendered.
|
10
|
+
#
|
11
|
+
# def pre_render(object, blueprint, view, options)
|
12
|
+
# # returns original, modified, or new object
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class Extensions
|
16
|
+
def initialize(extensions = [])
|
17
|
+
@extensions = extensions
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_a
|
21
|
+
@extensions.dup
|
22
|
+
end
|
23
|
+
|
24
|
+
# Appends an extension
|
25
|
+
def <<(ext)
|
26
|
+
@extensions << ext
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Runs the object through all Render Extensions and returns the final result
|
31
|
+
def pre_render(object, blueprint, view, options = {})
|
32
|
+
@extensions.reduce(object) do |acc, ext|
|
33
|
+
ext.pre_render(acc, blueprint, view, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blueprinter
|
4
|
+
#
|
5
|
+
# Public methods for reflecting on a Blueprint.
|
6
|
+
#
|
7
|
+
module Reflection
|
8
|
+
Field = Struct.new(:name, :display_name, :options)
|
9
|
+
Association = Struct.new(:name, :display_name, :blueprint, :view, :options)
|
10
|
+
|
11
|
+
#
|
12
|
+
# Returns a Hash of views keyed by name.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# widget_view = WidgetBlueprint.reflections[:default]
|
17
|
+
# category = widget_view.associations[:category]
|
18
|
+
# category.blueprint
|
19
|
+
# => CategoryBlueprint
|
20
|
+
# category.view
|
21
|
+
# => :default
|
22
|
+
#
|
23
|
+
# @return [Hash<Symbol, Blueprinter::Reflection::View>]
|
24
|
+
#
|
25
|
+
def reflections
|
26
|
+
@reflections ||= view_collection.views.transform_values do |view|
|
27
|
+
View.new(view.name, view_collection)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Represents a view within a Blueprint.
|
33
|
+
#
|
34
|
+
class View
|
35
|
+
attr_reader :name
|
36
|
+
|
37
|
+
def initialize(name, view_collection)
|
38
|
+
@name = name
|
39
|
+
@view_collection = view_collection
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Returns a Hash of fields in this view (recursive) keyed by method name.
|
44
|
+
#
|
45
|
+
# @return [Hash<Symbol, Blueprinter::Reflection::Field>]
|
46
|
+
#
|
47
|
+
def fields
|
48
|
+
@fields ||= @view_collection.fields_for(name).each_with_object({}) do |field, obj|
|
49
|
+
next if field.options[:association]
|
50
|
+
|
51
|
+
obj[field.method] = Field.new(field.method, field.name, field.options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Returns a Hash of associations in this view (recursive) keyed by method name.
|
57
|
+
#
|
58
|
+
# @return [Hash<Symbol, Blueprinter::Reflection::Association>]
|
59
|
+
#
|
60
|
+
def associations
|
61
|
+
@associations ||= @view_collection.fields_for(name).each_with_object({}) do |field, obj|
|
62
|
+
next unless field.options[:association]
|
63
|
+
|
64
|
+
blueprint = field.options.fetch(:blueprint)
|
65
|
+
view = field.options[:view] || :default
|
66
|
+
obj[field.method] = Association.new(field.method, field.name, blueprint, view, field.options)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/blueprinter/version.rb
CHANGED
data/lib/blueprinter/view.rb
CHANGED
@@ -16,10 +16,6 @@ module Blueprinter
|
|
16
16
|
@sort_by_definition = Blueprinter.configuration.sort_fields_by.eql?(:definition)
|
17
17
|
end
|
18
18
|
|
19
|
-
def transformers
|
20
|
-
view_transformers.empty? ? Blueprinter.configuration.default_transformers : view_transformers
|
21
|
-
end
|
22
|
-
|
23
19
|
def track_definition_order(method, viewable: true)
|
24
20
|
return unless @sort_by_definition
|
25
21
|
|
@@ -35,7 +35,9 @@ module Blueprinter
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def transformers(view_name)
|
38
|
-
|
38
|
+
included_transformers = gather_transformers_from_included_views(view_name).reverse
|
39
|
+
all_transformers = [*views[:default].view_transformers, *included_transformers].uniq
|
40
|
+
all_transformers.empty? ? Blueprinter.configuration.default_transformers : all_transformers
|
39
41
|
end
|
40
42
|
|
41
43
|
def [](view_name)
|
@@ -89,5 +91,15 @@ module Blueprinter
|
|
89
91
|
ordered_fields[definition.name] = fields[definition.name]
|
90
92
|
end
|
91
93
|
end
|
94
|
+
|
95
|
+
def gather_transformers_from_included_views(view_name)
|
96
|
+
current_view = views[view_name]
|
97
|
+
already_included_transformers = current_view.included_view_names.flat_map do |included_view_name|
|
98
|
+
next [] if view_name == included_view_name
|
99
|
+
|
100
|
+
gather_transformers_from_included_views(included_view_name)
|
101
|
+
end
|
102
|
+
[*already_included_transformers, *current_view.view_transformers].uniq
|
103
|
+
end
|
92
104
|
end
|
93
105
|
end
|
data/lib/blueprinter.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blueprinter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Procore Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Blueprinter is a JSON Object Presenter for Ruby that takes business objects
|
14
14
|
and breaks them down into simple hashes and serializes them to JSON. It can be used
|
@@ -30,6 +30,8 @@ files:
|
|
30
30
|
- lib/blueprinter/configuration.rb
|
31
31
|
- lib/blueprinter/deprecation.rb
|
32
32
|
- lib/blueprinter/empty_types.rb
|
33
|
+
- lib/blueprinter/extension.rb
|
34
|
+
- lib/blueprinter/extensions.rb
|
33
35
|
- lib/blueprinter/extractor.rb
|
34
36
|
- lib/blueprinter/extractors/association_extractor.rb
|
35
37
|
- lib/blueprinter/extractors/auto_extractor.rb
|
@@ -40,6 +42,7 @@ files:
|
|
40
42
|
- lib/blueprinter/formatters/date_time_formatter.rb
|
41
43
|
- lib/blueprinter/helpers/base_helpers.rb
|
42
44
|
- lib/blueprinter/helpers/type_helpers.rb
|
45
|
+
- lib/blueprinter/reflection.rb
|
43
46
|
- lib/blueprinter/transformer.rb
|
44
47
|
- lib/blueprinter/version.rb
|
45
48
|
- lib/blueprinter/view.rb
|
@@ -67,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '0'
|
69
72
|
requirements: []
|
70
|
-
rubygems_version: 3.4.
|
73
|
+
rubygems_version: 3.4.19
|
71
74
|
signing_key:
|
72
75
|
specification_version: 4
|
73
76
|
summary: Simple Fast Declarative Serialization Library
|