-
-
Notifications
You must be signed in to change notification settings - Fork 17
Added support for passing userInfo to Encoder #61
base: master
Are you sure you want to change the base?
Conversation
…ataEncoder to Encoder These changes allow for data to be passed through the TemplateRenderer all the way through to the Encoder that is passed to the view model objects during encoding. This allows for passing request-level information such as locale to the view model objects for selecting formatting, language, etc. during view model encoding. Existing public APIs (TemplateDataEncoder.encode) were augmented with default values for the new argument to maintain backwards API compatibility, while providing for the new functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
Maybe instead of mapping the user info, we could store the entire dictionary in a single key? That way we don't lose any keys that can't convert to CodingUserInfoKey
.
For example:
var encodingInfo: [CodingUserInfoKey: Any]
encodingInfo["renderUserInfo"] = userInfo
@@ -4,13 +4,13 @@ public final class TemplateDataEncoder { | |||
public init() {} | |||
|
|||
/// Encode an `Encodable` item to `TemplateData`. | |||
public func encode<E>(_ encodable: E, on worker: Worker) throws -> Future<TemplateData> where E: Encodable { | |||
public func encode<E>(_ encodable: E, on worker: Worker, userInfo: [CodingUserInfoKey: Any] = [:]) throws -> Future<TemplateData> where E: Encodable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we pass this to the init method instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I too thought about mapping the entire dictionary to a single key. I chose against it because it makes the semantics of the Encoder.userInfo call a bit odd:
let myUserInfo: [AnyHashable: Any] = [
"myKey" : "myData"
]
renderer.render(path, context, userInfo: myUserInfo)
public func encode(to encoder: Encoder) throws {
let myData = (encoder.userInfo[CodingUserInfoKey(rawValue: "renderUserInfo")] as? [AnyHashable: Any])["myKey"]
However, whatever you think is best. Just let me know and I'll align with your suggestion.
As for the init(), no problem I'll change it.
This change was made as requested by code review.
I'm not sure why this performance test would fail. No code changes affect the performance-tested code, I've double-checked... |
This change allows the userInfo passed to render to be passed down the TemplateDateEncoder chain. This provides for the ability for Request-level information to be passed all the way into the view model during the Encoder process.
The only minor quirk is that the type on userInfo passed to render is very broad [AnyHashable: Any] where the type on Encoder.userInfo is [CodingUserInfoKey: Any]. I opted to filter for the subset and document the filter. I'm happy to consider alternatives.
Any feedback on alternatives to making such information available are happily accepted.