Skip to content

Commit

Permalink
Allow 'dot syntax' for accessing nested views. Add :default view as a…
Browse files Browse the repository at this point in the history
…lias to self

Signed-off-by: Jordan Hollinger <[email protected]>
  • Loading branch information
jhollinger committed Jul 10, 2024
1 parent d4100bf commit 237f761
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
16 changes: 11 additions & 5 deletions lib/blueprinter/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class << self

# Initialize subclass
def self.inherited(subclass)
subclass.views = {}
subclass.views = { default: subclass }
subclass.fields = fields.dup
subclass.extensions = extensions.dup
subclass.blueprint_name = subclass.name ? [subclass.name] : blueprint_name.dup
Expand All @@ -26,18 +26,24 @@ def self.inspect

# A descriptive name for the Blueprint view, e.g. "WidgetBlueprint:extended"
def self.to_s
blueprint_name.join ':'
blueprint_name.join '.'
end

# Access a child view
# MyBlueprint[:extended]
# MyBlueprint[:extended][:plus]
# MyBlueprint["extended.plus"]
def self.[](view)
views.fetch(view)
rescue KeyError
raise Blueprinter::Errors::UnknownView, "View '#{view}' could not be found in Blueprint '#{self}'"
view.to_s.split('.').reduce(self) do |blueprint, child|
blueprint.views[child.to_sym] ||
raise(Errors::UnknownView, "View '#{child}' could not be found in Blueprint '#{blueprint}'")
end
end

# Define a new child view, which is a subclass of self
def self.view(name, &definition)
raise Errors::InvalidBlueprint, "View name may not contain '.'" if name.to_s =~ /\./

views[name] = Class.new(self)
views[name].blueprint_name << name
views[name].class_eval(&definition) if definition
Expand Down
34 changes: 24 additions & 10 deletions spec/v2/name_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class NamedBlueprint < Blueprinter::V2
end

it 'should find a view by name' do
expect(NamedBlueprint[:extended].to_s).to eq "NamedBlueprint:extended"
expect(NamedBlueprint[:extended].inspect).to eq "NamedBlueprint:extended"
expect(NamedBlueprint[:extended].to_s).to eq "NamedBlueprint.extended"
expect(NamedBlueprint[:extended].inspect).to eq "NamedBlueprint.extended"
end

it 'should raise for an invalid view name' do
Expand All @@ -38,8 +38,8 @@ class NamedBlueprint < Blueprinter::V2
end

it 'should find a view by name' do
expect(blueprint[:extended].to_s).to eq "MyBlueprint:extended"
expect(blueprint[:extended].inspect).to eq "MyBlueprint:extended"
expect(blueprint[:extended].to_s).to eq "MyBlueprint.extended"
expect(blueprint[:extended].inspect).to eq "MyBlueprint.extended"
end
end

Expand Down Expand Up @@ -78,14 +78,28 @@ class NamedBlueprint < Blueprinter::V2
expect(blueprint.to_s).to eq "MyBlueprint"
expect(blueprint.inspect).to eq "MyBlueprint"

expect(blueprint[:foo].to_s).to eq "MyBlueprint:foo"
expect(blueprint[:foo].inspect).to eq "MyBlueprint:foo"
expect(blueprint[:foo].to_s).to eq "MyBlueprint.foo"
expect(blueprint[:foo].inspect).to eq "MyBlueprint.foo"

expect(blueprint[:foo][:bar].to_s).to eq "MyBlueprint:foo:bar"
expect(blueprint[:foo][:bar].inspect).to eq "MyBlueprint:foo:bar"
expect(blueprint[:foo][:bar].to_s).to eq "MyBlueprint.foo.bar"
expect(blueprint[:foo][:bar].inspect).to eq "MyBlueprint.foo.bar"

expect(blueprint[:foo][:bar][:zorp].to_s).to eq "MyBlueprint:foo:bar:zorp"
expect(blueprint[:foo][:bar][:zorp].inspect).to eq "MyBlueprint:foo:bar:zorp"
expect(blueprint[:foo][:bar][:zorp].to_s).to eq "MyBlueprint.foo.bar.zorp"
expect(blueprint[:foo][:bar][:zorp].inspect).to eq "MyBlueprint.foo.bar.zorp"
end

it 'should find deeply nested names using dot syntax' do
expect(blueprint["foo"].to_s).to eq "MyBlueprint.foo"
expect(blueprint["foo.bar"].to_s).to eq "MyBlueprint.foo.bar"
expect(blueprint["foo.bar.zorp"].to_s).to eq "MyBlueprint.foo.bar.zorp"
end
end

it "should not contain periods" do
blueprint = Class.new(Blueprinter::V2)
expect { blueprint.view :"foo.bar" }.to raise_error(
Blueprinter::Errors::InvalidBlueprint,
/name may not contain/
)
end
end

0 comments on commit 237f761

Please sign in to comment.