Skip to content

Commit

Permalink
Prevent adding default mapping after mapping block was declared
Browse files Browse the repository at this point in the history
  • Loading branch information
kgiszczak committed Jul 3, 2022
1 parent 6ae865f commit a625ec6
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 5 deletions.
15 changes: 10 additions & 5 deletions lib/shale/mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,11 @@ def attribute(name, type, collection: false, default: nil)

@attributes[name] = Attribute.new(name, type, collection, default)

@hash_mapping.map(name.to_s, to: name)
@json_mapping.map(name.to_s, to: name)
@yaml_mapping.map(name.to_s, to: name)
@toml_mapping.map(name.to_s, to: name)
@xml_mapping.map_element(name.to_s, to: name)
@hash_mapping.map(name.to_s, to: name) unless @hash_mapping.finalized?
@json_mapping.map(name.to_s, to: name) unless @json_mapping.finalized?
@yaml_mapping.map(name.to_s, to: name) unless @yaml_mapping.finalized?
@toml_mapping.map(name.to_s, to: name) unless @toml_mapping.finalized?
@xml_mapping.map_element(name.to_s, to: name) unless @xml_mapping.finalized?

class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
attr_reader :#{name}
Expand Down Expand Up @@ -200,6 +200,7 @@ def #{name}=(val)
# @api public
def hsh(&block)
@hash_mapping = @__hash_mapping_init.dup
@hash_mapping.finalize!
@hash_mapping.instance_eval(&block)
end

Expand All @@ -223,6 +224,7 @@ def hsh(&block)
# @api public
def json(&block)
@json_mapping = @__json_mapping_init.dup
@json_mapping.finalize!
@json_mapping.instance_eval(&block)
end

Expand All @@ -246,6 +248,7 @@ def json(&block)
# @api public
def yaml(&block)
@yaml_mapping = @__yaml_mapping_init.dup
@yaml_mapping.finalize!
@yaml_mapping.instance_eval(&block)
end

Expand All @@ -269,6 +272,7 @@ def yaml(&block)
# @api public
def toml(&block)
@toml_mapping = @__toml_mapping_init.dup
@toml_mapping.finalize!
@toml_mapping.instance_eval(&block)
end

Expand All @@ -293,6 +297,7 @@ def toml(&block)
# @api public
def xml(&block)
@xml_mapping = @__xml_mapping_init.dup
@xml_mapping.finalize!
@xml_mapping.root('')
@xml_mapping.instance_eval(&block)
end
Expand Down
18 changes: 18 additions & 0 deletions lib/shale/mapping/dict.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Dict
def initialize
super
@keys = {}
@finalized = false
end

# Map key to attribute
Expand All @@ -38,9 +39,26 @@ def map(key, to: nil, using: nil)
@keys[key] = Descriptor::Dict.new(name: key, attribute: to, methods: using)
end

# Set the "finalized" instance variable to true
#
# @api private
def finalize!
@finalized = true
end

# Query the "finalized" instance variable
#
# @return [truem false]
#
# @api private
def finalized?
@finalized
end

# @api private
def initialize_dup(other)
@keys = other.instance_variable_get('@keys').dup
@finalized = false
super
end
end
Expand Down
18 changes: 18 additions & 0 deletions lib/shale/mapping/xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def initialize
@content = nil
@root = ''
@default_namespace = Descriptor::XmlNamespace.new
@finalized = false
end

# Map element to attribute
Expand Down Expand Up @@ -169,13 +170,30 @@ def namespace(name, prefix)
@default_namespace.prefix = prefix
end

# Set the "finalized" instance variable to true
#
# @api private
def finalize!
@finalized = true
end

# Query the "finalized" instance variable
#
# @return [truem false]
#
# @api private
def finalized?
@finalized
end

# @api private
def initialize_dup(other)
@elements = other.instance_variable_get('@elements').dup
@attributes = other.instance_variable_get('@attributes').dup
@content = other.instance_variable_get('@content').dup
@root = other.instance_variable_get('@root').dup
@default_namespace = other.instance_variable_get('@default_namespace').dup
@finalized = false

super
end
Expand Down
76 changes: 76 additions & 0 deletions spec/shale/mapper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,54 @@ class Model
class MapperWithModel < Shale::Mapper
model Model
end

# rubocop:disable Lint/EmptyBlock
class FinalizedParent1 < Shale::Mapper
attribute :one, Shale::Type::String

hsh do
end

json do
end

yaml do
end

toml do
end

xml do
end
end

class FinalizedParent2 < Shale::Mapper
hsh do
end

json do
end

yaml do
end

toml do
end

xml do
end

attribute :one, Shale::Type::String
end
# rubocop:enable Lint/EmptyBlock

class FinalizedChild1 < FinalizedParent1
attribute :two, Shale::Type::String
end

class FinalizedChild2 < FinalizedParent2
attribute :two, Shale::Type::String
end
end

RSpec.describe Shale::Mapper do
Expand Down Expand Up @@ -522,4 +570,32 @@ class FooBarBaz < described_class
end
end
end

context 'finalized mapping' do
it 'finalizes maping' do
expect(ShaleMapperTesting::FinalizedParent1.hash_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent1.json_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent1.yaml_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent1.toml_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent1.xml_mapping.elements.keys).to eq([])

expect(ShaleMapperTesting::FinalizedParent2.hash_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent2.json_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent2.yaml_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent2.toml_mapping.keys.keys).to eq([])
expect(ShaleMapperTesting::FinalizedParent2.xml_mapping.elements.keys).to eq([])

expect(ShaleMapperTesting::FinalizedChild1.hash_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild1.json_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild1.yaml_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild1.toml_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild1.xml_mapping.elements.keys).to eq(['two'])

expect(ShaleMapperTesting::FinalizedChild2.hash_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild2.json_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild2.yaml_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild2.toml_mapping.keys.keys).to eq(['two'])
expect(ShaleMapperTesting::FinalizedChild2.xml_mapping.elements.keys).to eq(['two'])
end
end
end
18 changes: 18 additions & 0 deletions spec/shale/mapping/dict_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,38 @@
end
end

describe '#finalize!' do
it 'sets the "finalized" to true' do
obj = described_class.new
obj.finalize!
expect(obj.finalized?).to eq(true)
end
end

describe '#finalized?' do
it 'returns value of "finalized" variable' do
obj = described_class.new
expect(obj.finalized?).to eq(false)
end
end

describe '#initialize_dup' do
it 'duplicates keys instance variable' do
original = described_class.new
original.finalize!
original.map('foo', to: :bar)

duplicate = original.dup
duplicate.map('baz', to: :qux)

expect(original.keys.keys).to eq(['foo'])
expect(original.keys['foo'].attribute).to eq(:bar)
expect(original.finalized?).to eq(true)

expect(duplicate.keys.keys).to eq(%w[foo baz])
expect(duplicate.keys['foo'].attribute).to eq(:bar)
expect(duplicate.keys['baz'].attribute).to eq(:qux)
expect(duplicate.finalized?).to eq(false)
end
end
end
18 changes: 18 additions & 0 deletions spec/shale/mapping/xml_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,25 @@
end
end

describe '#finalize!' do
it 'sets the "finalized" to true' do
obj = described_class.new
obj.finalize!
expect(obj.finalized?).to eq(true)
end
end

describe '#finalized?' do
it 'returns value of "finalized" variable' do
obj = described_class.new
expect(obj.finalized?).to eq(false)
end
end

describe '#initialize_dup' do
it 'duplicates instance variables' do
original = described_class.new
original.finalize!
original.root('root')
original.namespace('http://original.com', 'original')
original.map_element('element', to: :element)
Expand All @@ -370,6 +386,7 @@
expect(original.attributes.keys).to eq(['attribute'])
expect(original.attributes['attribute'].attribute).to eq(:attribute)
expect(original.content.attribute).to eq(:content)
expect(original.finalized?).to eq(true)

expect(duplicate.prefixed_root).to eq('original:root')
expect(duplicate.elements.keys).to eq(%w[http://original.com:element])
Expand All @@ -393,6 +410,7 @@
expect(duplicate.attributes['attribute'].attribute).to eq(:attribute)
expect(duplicate.attributes['attribute_dup'].attribute).to eq(:attribute_dup)
expect(duplicate.content.attribute).to eq(:content_dup)
expect(duplicate.finalized?).to eq(false)
end
end
end

0 comments on commit a625ec6

Please sign in to comment.