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

Consider adding a built-in view context #224

Closed
fwgreen opened this issue Apr 17, 2023 · 3 comments
Closed

Consider adding a built-in view context #224

fwgreen opened this issue Apr 17, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@fwgreen
Copy link

fwgreen commented Apr 17, 2023

I apologize if this has been bought up before; I've searched and found no reference to it. While it's good to have the flexibility to create one's own contexts, this can become unwieldy as the number of routes grows. After porting a pet project over to Vapor, I found myself with several contexts like the one below:

struct TelephoneContext : Encodable {
    var assignedPhones: [Telephone]
    var outForServicePhones: [Telephone]
    var availablePhones: [Telephone]

    enum CodingKeys: String, CodingKey {
        case assignedPhones = "assigned_phones"
        case outForServicePhones = "out_for_service_phones"
        case availablePhones = "available_phones"
    }
}
//...
let phoneCtx = TelephoneContext(
    assignedPhones:      try Telephone.listBy(status: .assigned), 
    outForServicePhones: try Telephone.listBy(status: .outForService), 
    availablePhones:     try Telephone.listBy(status: .available)
)

Maybe something result builder based?:

let phoneCtx = Context {
    ("assigned_phones",        try Telephone.listBy(status: .assigned))
    ("out_for_service_phones", try Telephone.listBy(status: .outForService)) 
    ("available_phones",       try Telephone.listBy(status: .available))
}
@fwgreen fwgreen added the enhancement New feature or request label Apr 17, 2023
@fwgreen
Copy link
Author

fwgreen commented Apr 24, 2023

While this does the trick, its reliance on AnyCodable is worrisome:

import AnyCodable
import Vapor

@resultBuilder 
struct ContextBuilder {
    static func buildBlock(_ items: (String, Encodable)...) -> [String: AnyEncodable] {
        items.reduce(into: [:]) { $0[$1.0] = AnyEncodable($1.1) }
    }
}

public struct Context {
    var data: [String: AnyEncodable]

    init(@ContextBuilder items: () throws -> [String: AnyEncodable]) {
        data = try! items()
    }
}

extension ViewRenderer {
    public func render(_ name: String, _ context: Context) async throws -> View {
        return try await self.render(name, context.data)
    }
}

@0xTim
Copy link
Member

0xTim commented Jun 13, 2023

Yeah I think this is probably out of scope for Leaf itself but would make a good community package!

@fwgreen
Copy link
Author

fwgreen commented Nov 15, 2023

This approach is a bit too involved when all I need is the ability to use a dictionary

@fwgreen fwgreen closed this as completed Nov 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants