Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Conflict when root and object property share the same name #99

Merged
merged 7 commits into from
Jul 5, 2018

Conversation

akxcv
Copy link
Contributor

@akxcv akxcv commented Apr 21, 2018

Fixes #95.

Why does it fail?

First, we normalize the schema, which includes wrapping it in a root, if given. (This also happens with namespaces.)

Then, the normalized schema is passed to the Builder along with the instance (from the example given in #95, we get something like instance: #<Foo:0x00007fb2651a1db8>, schema: { foo: { foo: String, bar: String } }

Afterward, the Builder iterates through the schema's key-value pairs. When instance.respond_to?(:foo), the Builder calls itself again, this time with instance.foo as the instance and { foo: String, bar: String } as the schema. You should see the problem now.

My proposed fix

I found that the builder only needs to know the actual schema, without any roots or namespaces. So, the current algorithm of serialization is copy -> build -> wrap instead of copy&wrap -> build.

I've split Copier into Copier and Wrapper, which should make their respective responsibilities clearer.

P.S I couldn't come up with any good real-world examples of this use-case for the specs 😞

carrier.camelize ? Surrealist::HashUtils.camelize_hash(hash) : hash
copied_schema = Surrealist::Copier.deep_copy(schema)
built_schema = Builder.new(carrier, copied_schema, instance).call
wrapped_schema = Surrealist::Wrapper.wrap(built_schema, carrier, instance.class.name)
Copy link
Contributor Author

@akxcv akxcv Apr 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code makes me feel a bit anxious, maybe we should encapsulate this via something like a command pattern here?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right, and it would be very nice of you to refactor this part a bit.

@@ -3,6 +3,8 @@
module Surrealist
# A helper class for hashes transformations.
module HashUtils
EMPTY_HASH = {}.freeze
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashUtils seems like a more obvious place to store this.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

@nesaulov
Copy link
Owner

@akxcv thank you for the PR and such a detailed explanation! I am vacationing right now, so I'll review this next week

carrier.camelize ? Surrealist::HashUtils.camelize_hash(hash) : hash
copied_schema = Surrealist::Copier.deep_copy(schema)
built_schema = Builder.new(carrier, copied_schema, instance).call
wrapped_schema = Surrealist::Wrapper.wrap(built_schema, carrier, instance.class.name)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right, and it would be very nice of you to refactor this part a bit.

@@ -3,6 +3,8 @@
module Surrealist
# A helper class for hashes transformations.
module HashUtils
EMPTY_HASH = {}.freeze
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

# @param [Bool] namespaces_condition whether to wrap into namespace.
#
# @return [Hash] deeply copied hash, possibly wrapped.
def possibly_wrapped_hash(hash, klass, carrier, namespaces_condition)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this also doesn't look good in fact. Could you please leave a TODO note to refactor this later?

},
},
}
end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add spaces between lets?

@nesaulov
Copy link
Owner

nesaulov commented Jun 2, 2018

hey @akxcv, any updates on this?

@akxcv
Copy link
Contributor Author

akxcv commented Jun 3, 2018

@nesaulov I've fixed everything but the first of your comments on my machine. Thinking about how to refactor this part better.

@akxcv
Copy link
Contributor Author

akxcv commented Jun 29, 2018

Added a TODO comment. Let's release the fix already :)

Copy link
Owner

@nesaulov nesaulov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright then. Thanks for your help!

@nesaulov nesaulov merged commit fd4c83b into nesaulov:master Jul 5, 2018
@akxcv akxcv deleted the patch-95/fix-root-prop-same-name branch July 6, 2018 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Conflict when root and and object property share the same name
2 participants