Skip to content

Commit dd86213

Browse files
committed
Append duplicate views instead of overwriting them (except :default)
1 parent f01f713 commit dd86213

File tree

3 files changed

+31
-13
lines changed

3 files changed

+31
-13
lines changed

lib/blueprinter/v2/dsl.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ module V2
55
# Methods for defining Blueprint fields and views
66
module DSL
77
#
8-
# Define a new child view, which is a subclass of self.
8+
# Define a new child view, which is a subclass of self. If a view with this name already exists, the definition will be appended.
99
#
1010
# @param name [Symbol] Name of the view
11-
# @param fields [Boolean] Inherit fields from parents
12-
# @param options [Boolean] Inherit options from parents
13-
# @param extensions [Boolean] Inherit extensions from parents
11+
# @param fields [Boolean] Inherit fields from parents (default true)
12+
# @param options [Boolean] Inherit options from parents (default true)
13+
# @param extensions [Boolean] Inherit extensions from parents (default true)
1414
# @yield Define the view in the block
1515
#
16-
def view(name, fields: true, options: true, extensions: true, &definition)
16+
def view(name, fields: nil, options: nil, extensions: nil, &definition)
1717
raise Errors::InvalidBlueprint, "View name may not contain '.'" if name.to_s =~ /\./
1818

1919
name = name.to_sym
@@ -22,7 +22,7 @@ def view(name, fields: true, options: true, extensions: true, &definition)
2222
end
2323

2424
#
25-
# Define a new partial.
25+
# Define a new partial. If a partial with this name already exists, it will be replaced.
2626
#
2727
# @param name [Symbol] Name of the partial to create or import
2828
# @yield Define a new partial in the block

lib/blueprinter/v2/view_builder.rb

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def []=(name, definition)
3131
name = name.to_sym
3232
raise Errors::InvalidBlueprint, "You may not redefine the default view" if name == :default
3333

34-
@pending[name] = definition
34+
@pending[name] ||= []
35+
@pending[name] << definition
3536
end
3637

3738
#
@@ -46,14 +47,18 @@ def [](name)
4647
@mut.synchronize do
4748
next if @views.key?(name)
4849

49-
p = @pending[name]
50+
defs = @pending[name]
51+
inherit_fields = defs.reduce(true) { |acc, d| d.fields.nil? ? acc : d.fields }
52+
inherit_options = defs.reduce(true) { |acc, d| d.options.nil? ? acc : d.options }
53+
inherit_extensions = defs.reduce(true) { |acc, d| d.extensions.nil? ? acc : d.extensions }
54+
5055
view = Class.new(@parent)
5156
view.views.reset
5257
view.append_name(name)
53-
view.schema.clear unless p.fields
54-
view.options.clear unless p.options
55-
view.extensions.clear unless p.extensions
56-
view.class_eval(&p.definition) if p.definition
58+
view.schema.clear unless inherit_fields
59+
view.options.clear unless inherit_options
60+
view.extensions.clear unless inherit_extensions
61+
defs.each { |d| view.class_eval(&d.definition) if d.definition }
5762
view.eval!(false)
5863
@views[name] = view
5964
end
@@ -66,6 +71,7 @@ def fetch(name)
6671
self[name] || raise(KeyError, "View '#{name}' not found")
6772
end
6873

74+
# Yield each name and view
6975
def each(&block)
7076
enum = Enumerator.new do |y|
7177
y.yield(:default, self[:default])
@@ -77,7 +83,9 @@ def each(&block)
7783
# Create a duplicate of this builder with a different default view
7884
def dup_for(blueprint)
7985
builder = self.class.new(blueprint)
80-
@pending.each { |name, definition| builder[name] = definition }
86+
@pending.each do |name, defs|
87+
defs.each { |d| builder[name] = d }
88+
end
8189
builder
8290
end
8391

spec/v2/view_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,15 @@
9191
it "can opt out of inheriting extensions" do
9292
expect(blueprint[:minimal].extensions).to eq([])
9393
end
94+
95+
it "can be extended" do
96+
bp1 = Class.new(Blueprinter::V2::Base) do
97+
view(:foo) { fields :id, :name }
98+
end
99+
bp2 = Class.new(bp1) do
100+
view(:foo) { field :description }
101+
end
102+
expect(bp2.reflections[:foo].fields.keys.sort).to eq %i(description id name)
103+
end
94104
end
95105
end

0 commit comments

Comments
 (0)