blueprinter 0.23.0 → 0.24.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 +16 -1
- data/README.md +20 -0
- data/lib/blueprinter/base.rb +22 -0
- data/lib/blueprinter/extractors/association_extractor.rb +2 -0
- data/lib/blueprinter/version.rb +1 -1
- data/lib/blueprinter/view.rb +13 -1
- data/lib/blueprinter/view_collection.rb +33 -14
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d5e6d18d1ccf85eebe25b2aef41b629fbdad10a2972684e458bfbf268f266f0
|
4
|
+
data.tar.gz: a60400a4b58cb8d26db31838b8da490096b747d17b3912e119db413796d9f5ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c58a220d1187a9fa39514158b7e585576010b030da4430a41263ea4dc47f43d1a115e4b475230dfc4a995e1607f870b280d26182d012109013b3303fd75d7cd
|
7
|
+
data.tar.gz: a9a8380551402f4aace847aa1333269e4e2d6052dcf220ea94dbe8f2976a7abb6172558926417438085ca56f57ca744d6a94f1694380ab44c98df37aba9751c3
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.24.0 - 2020/6/22
|
2
|
+
* 🚀 [FEATURE] Add an `options` option to associations to facilitate passing options from one blueprint to another. [#220](https://github.com/procore/blueprinter/pull/220). Thanks to [@mcclayton](https://github.com/mcclayton).
|
3
|
+
|
4
|
+
## 0.23.4 - 2020/4/28
|
5
|
+
* 🚀 [FEATURE] Public class method `has_view?` on Blueprinter::Base subclasses introduced in [#213](https://github.com/procore/blueprinter/pull/213). Thanks to [@spencerneste](https://github.com/spencerneste).
|
6
|
+
|
7
|
+
## 0.23.3 - 2020/4/7
|
8
|
+
* 🐛 [BUGFIX] Fixes issue where `exclude` fields in deeply nested views were not respected. Resolved issue [207](https://github.com/procore/blueprinter/issues/207) in [#208](https://github.com/procore/blueprinter/pull/208) by [@tpltn](https://github.com/tpltn).
|
9
|
+
|
10
|
+
## 0.23.2 - 2020/3/16
|
11
|
+
* 🐛 [BUGFIX] Fixes issue where fields "bled" into other views due to merge side-effects. Resolved issue [205](https://github.com/procore/blueprinter/issues/205) in [#204](https://github.com/procore/blueprinter/pull/204) by [@trevorrjohn](https://github.com/trevorrjohn).
|
12
|
+
|
13
|
+
## 0.23.1 - 2020/3/13
|
14
|
+
* 🐛 [BUGFIX] Fixes #172 where views would unintentionally ignore `sort_fields_by: :definition` configuration. Resolved in [#197](https://github.com/procore/blueprinter/pull/197) by [@wlkrw](https://github.com/wlkrw).
|
15
|
+
|
16
|
+
## 0.23.0 - 2020/1/31
|
2
17
|
* 🚀 [FEATURE] Configurable default extractor introduced in [#198](https://github.com/procore/blueprinter/pull/198) by [@wlkrw](https://github.com/wlkrw). You can now set a default extractor like so:
|
3
18
|
```
|
4
19
|
Blueprinter.configure do |config|
|
data/README.md
CHANGED
@@ -355,6 +355,26 @@ Output:
|
|
355
355
|
}
|
356
356
|
```
|
357
357
|
|
358
|
+
It is also possible to pass options from one Blueprint to another via an association.
|
359
|
+
For example:
|
360
|
+
```ruby
|
361
|
+
class VehicleBlueprint < Blueprinter::Base
|
362
|
+
identifier :uuid
|
363
|
+
field :full_name do |vehicle, options|
|
364
|
+
"#{vehicle.model} #{options[:trim]}"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
class DriverBlueprint < Blueprinter::Base
|
369
|
+
identifier :uuid
|
370
|
+
|
371
|
+
view :normal do
|
372
|
+
fields :first_name, :last_name
|
373
|
+
association :vehicles, blueprint: vehicle_blueprint, options: { trim: 'LX' }
|
374
|
+
end
|
375
|
+
end
|
376
|
+
```
|
377
|
+
|
358
378
|
---
|
359
379
|
</details>
|
360
380
|
|
data/lib/blueprinter/base.rb
CHANGED
@@ -427,8 +427,30 @@ module Blueprinter
|
|
427
427
|
# @return [View] a Blueprinter::View object
|
428
428
|
def self.view(view_name)
|
429
429
|
@current_view = view_collection[view_name]
|
430
|
+
view_collection[:default].track_definition_order(view_name)
|
430
431
|
yield
|
431
432
|
@current_view = view_collection[:default]
|
432
433
|
end
|
434
|
+
|
435
|
+
# Check whether or not a Blueprint supports the supplied view.
|
436
|
+
# It accepts a view name.
|
437
|
+
#
|
438
|
+
# @param view_name [Symbol] the view name
|
439
|
+
#
|
440
|
+
# @example With the following Blueprint
|
441
|
+
#
|
442
|
+
# class ExampleBlueprint < Blueprinter::Base
|
443
|
+
# view :custom do
|
444
|
+
# end
|
445
|
+
# end
|
446
|
+
#
|
447
|
+
# ExampleBlueprint.has_view?(:custom) => true
|
448
|
+
# ExampleBlueprint.has_view?(:doesnt_exist) => false
|
449
|
+
#
|
450
|
+
# @return [Boolean] a boolean value indicating if the view is
|
451
|
+
# supported by this Blueprint.
|
452
|
+
def self.has_view?(view_name)
|
453
|
+
view_collection.has_view? view_name
|
454
|
+
end
|
433
455
|
end
|
434
456
|
end
|
@@ -9,6 +9,8 @@ module Blueprinter
|
|
9
9
|
|
10
10
|
def extract(association_name, object, local_options, options={})
|
11
11
|
options_without_default = options.reject { |k,_| k == :default || k == :default_if }
|
12
|
+
# Merge in assocation options hash
|
13
|
+
local_options = local_options.merge(options[:options]) if options[:options].is_a?(Hash)
|
12
14
|
value = @extractor.extract(association_name, object, local_options, options_without_default)
|
13
15
|
return default_value(options) if use_default_value?(value, options[:default_if])
|
14
16
|
view = options[:view] || :default
|
data/lib/blueprinter/version.rb
CHANGED
data/lib/blueprinter/view.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Blueprinter
|
2
2
|
# @api private
|
3
|
+
DefinitionPlaceholder = Struct.new :name, :view?
|
3
4
|
class View
|
4
|
-
attr_reader :excluded_field_names, :fields, :included_view_names, :name, :transformers
|
5
|
+
attr_reader :excluded_field_names, :fields, :included_view_names, :name, :transformers, :definition_order
|
5
6
|
|
6
7
|
def initialize(name, fields: {}, included_view_names: [], excluded_view_names: [],transformers: [])
|
7
8
|
@name = name
|
@@ -9,6 +10,14 @@ module Blueprinter
|
|
9
10
|
@included_view_names = included_view_names
|
10
11
|
@excluded_field_names = excluded_view_names
|
11
12
|
@transformers = transformers
|
13
|
+
@definition_order = []
|
14
|
+
@sort_by_definition = Blueprinter.configuration.sort_fields_by.eql?(:definition)
|
15
|
+
end
|
16
|
+
|
17
|
+
def track_definition_order(method, is_view = true)
|
18
|
+
if @sort_by_definition
|
19
|
+
@definition_order << DefinitionPlaceholder.new(method, is_view)
|
20
|
+
end
|
12
21
|
end
|
13
22
|
|
14
23
|
def inherit(view)
|
@@ -30,11 +39,13 @@ module Blueprinter
|
|
30
39
|
end
|
31
40
|
|
32
41
|
def include_view(view_name)
|
42
|
+
track_definition_order(view_name)
|
33
43
|
included_view_names << view_name
|
34
44
|
end
|
35
45
|
|
36
46
|
def include_views(view_names)
|
37
47
|
view_names.each do |view_name|
|
48
|
+
track_definition_order(view_name)
|
38
49
|
included_view_names << view_name
|
39
50
|
end
|
40
51
|
end
|
@@ -54,6 +65,7 @@ module Blueprinter
|
|
54
65
|
end
|
55
66
|
|
56
67
|
def <<(field)
|
68
|
+
track_definition_order(field.name,false)
|
57
69
|
fields[field.name] = field
|
58
70
|
end
|
59
71
|
end
|
@@ -23,9 +23,10 @@ module Blueprinter
|
|
23
23
|
def fields_for(view_name)
|
24
24
|
return identifier_fields if view_name == :identifier
|
25
25
|
|
26
|
-
fields = sortable_fields(view_name)
|
27
|
-
sorted_fields = sort_by_definition ? fields : fields.sort_by(&:name)
|
28
|
-
|
26
|
+
fields, excluded_fields = sortable_fields(view_name)
|
27
|
+
sorted_fields = sort_by_definition ? sort_by_def(view_name, fields) : fields.values.sort_by(&:name)
|
28
|
+
|
29
|
+
(identifier_fields + sorted_fields).reject { |field| excluded_fields.include?(field.name) }
|
29
30
|
end
|
30
31
|
|
31
32
|
def transformers(view_name)
|
@@ -42,28 +43,46 @@ module Blueprinter
|
|
42
43
|
views[:identifier].fields.values
|
43
44
|
end
|
44
45
|
|
46
|
+
# @param [String] view_name
|
47
|
+
# @return [Array<(Hash, Hash<String, NilClass>)>] fields, excluded_fields
|
45
48
|
def sortable_fields(view_name)
|
49
|
+
excluded_fields = {}
|
46
50
|
fields = views[:default].fields
|
47
51
|
fields = merge_fields(fields, views[view_name].fields)
|
48
52
|
views[view_name].included_view_names.each do |included_view_name|
|
49
|
-
if view_name
|
50
|
-
fields = merge_fields(fields, sortable_fields(included_view_name))
|
51
|
-
end
|
52
|
-
end
|
53
|
+
next if view_name == included_view_name
|
53
54
|
|
54
|
-
|
55
|
-
fields
|
55
|
+
view_fields, view_excluded_fields = sortable_fields(included_view_name)
|
56
|
+
fields = merge_fields(fields, view_fields)
|
57
|
+
excluded_fields.merge!(view_excluded_fields)
|
56
58
|
end
|
57
59
|
|
58
|
-
|
60
|
+
views[view_name].excluded_field_names.each { |name| excluded_fields[name] = nil }
|
61
|
+
|
62
|
+
[fields, excluded_fields]
|
59
63
|
end
|
60
64
|
|
61
|
-
|
62
|
-
|
63
|
-
|
65
|
+
# select and order members of fields according to traversal of the definition_orders
|
66
|
+
def sort_by_def(view_name, fields)
|
67
|
+
ordered_fields = {}
|
68
|
+
views[:default].definition_order.each { |definition| add_to_ordered_fields(ordered_fields, definition, fields, view_name) }
|
69
|
+
ordered_fields.values
|
70
|
+
end
|
71
|
+
|
72
|
+
# view_name_filter allows to follow definition order all the way down starting from the view_name given to sort_by_def()
|
73
|
+
# but include no others at the top-level
|
74
|
+
def add_to_ordered_fields(ordered_fields, definition, fields, view_name_filter = nil)
|
75
|
+
if definition.view?
|
76
|
+
if view_name_filter.nil? || view_name_filter == definition.name
|
77
|
+
views[definition.name].definition_order.each { |_definition| add_to_ordered_fields(ordered_fields, _definition, fields) }
|
78
|
+
end
|
64
79
|
else
|
65
|
-
|
80
|
+
ordered_fields[definition.name] = fields[definition.name]
|
66
81
|
end
|
67
82
|
end
|
83
|
+
|
84
|
+
def merge_fields(source_fields, included_fields)
|
85
|
+
source_fields.merge included_fields
|
86
|
+
end
|
68
87
|
end
|
69
88
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blueprinter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Hess
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: factory_bot
|
@@ -123,6 +123,20 @@ dependencies:
|
|
123
123
|
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '3.7'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rspec-rails
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "<"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 4.0.0
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "<"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 4.0.0
|
126
140
|
- !ruby/object:Gem::Dependency
|
127
141
|
name: sqlite3
|
128
142
|
requirement: !ruby/object:Gem::Requirement
|