blueprinter 0.30.0 → 1.0.0
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 +5 -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 +12 -1
- data/lib/blueprinter.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0daefad3d40a1c147e4dff6ae392a0b36f344fac7b79b6a500bc39fbe50885bf
|
4
|
+
data.tar.gz: 41d4753399f53d94030ef650b7433399030ae282fe5e85124cee83f86b7558f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff8384ffb0de03cfa91422313656a6e7ff9375b3335cdab1371e8a60db65a5cd9fbacaac1f32961c86e9bd213678cfdcd5911fc4a183962dbf57df8ff6155e54
|
7
|
+
data.tar.gz: f0cf694fd5984a274f8bfb2a664f7b6baa4406ee98a08a5666c2ccbf0e275627f3ed779e9770f3e6d506dc0b84eecb9ae3546846cd59819e93d1ea4676b63233
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 1.0.0 - 2024/01/17
|
2
|
+
* 🚀 [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).
|
3
|
+
* 🚀 [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).
|
4
|
+
* 💅 [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).
|
5
|
+
|
1
6
|
## 0.30.0 - 2023/09/16
|
2
7
|
* 🚀 [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
8
|
* 💅 [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
|
[](https://github.com/procore-oss/blueprinter/actions/workflows/test.yaml)
|
2
2
|
[](https://badge.fury.io/rb/blueprinter)
|
3
|
-
[](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.concat(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,14 @@ 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
|
+
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.concat(current_view.view_transformers)
|
102
|
+
end
|
92
103
|
end
|
93
104
|
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.0
|
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-18 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
|