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

Child handlers #218

Closed
LaylBongers opened this issue Mar 7, 2017 · 3 comments
Closed

Child handlers #218

LaylBongers opened this issue Mar 7, 2017 · 3 comments
Labels
declined A declined request or suggestion request Request for new functionality

Comments

@LaylBongers
Copy link

LaylBongers commented Mar 7, 2017

Why you believe this feature is necessary.

The concept of "Child Action" is commonly used in ASP.NET MVC applications to create functionality behind common elements on a page without wrapping this functionality into the templates directly. An example of this would be a login widget. A quick example from ASP.NET MVC: https://blog.falafel.com/child-actions-asp-net-mvc/

Originally I wrote "Partial Views" in this feature request, but it seems I had confused the names of multiple similar but different features.

A child handler would be invoked from the template (possibly a template that's being extended from, or one that's being included). It would then run the child handler like it would a normal one and insert the result into the page. The child could in turn invoke its own template.

A convincing use-case for this feature.

Where currently, you would have to do this:

#[get("/")]
fn index() -> Template {
    let mut context = HashMap::new();
    context.insert("login", get_login_data()); // First time
    context.insert("home", get_home_data());
    Template::render("home", &context)
}


#[get("/about")]
fn about() -> Template {
    let mut context = HashMap::new();
    context.insert("login", get_login_data()); // Second time, this keeps on going for every page
    context.insert("about", get_about_data());
    Template::render("about", &context)
}

Child handlers would allow this instead:

#[get("/")]
fn index() -> Template {
    Template::render("home", &get_home_data())
}


#[get("/about")]
fn about() -> Template {
    Template::render("about", &get_about_data())
}

#[child("login")]
fn login() -> Template {
    Template::render("login", &get_login_data())
}

Why this feature can't or shouldn't exist outside of Rocket.

This feature would need to be wrapped into rocket_codegen at least for easy usage. It would be possible to support this externally, but this is such a common use case that it's unlikely you don't want to use this in a web application, and moving it externally would complicate the implementation and usage.

@LaylBongers LaylBongers changed the title Partial handlers Child handlers Mar 7, 2017
@SergioBenitez
Copy link
Member

I'm a tad-bit confused about this request. First, let me try to share my understanding of child actions (as I've never worked with ASP.NET MVC), and then I'll try to address the request head on.

My understanding of child actions are as follows: a child action is a request handler than can be invoked from within a template. When invoked, the child action (a request handler) runs as if it was handling the current request itself. However, instead of using the resulting value to issue a response to the client, the value is passed back to the template. The template can use the value as it sees fit.

Additionally, it seems that, from your example, all child actions can be invoked from any template. As a result, child actions are like implicitly invokable functions.

Okay, hopefully I've understood this right.

It seems that, then, a child action is really just a global function available to templates that gets passed the request state. Is that right? If so, then this should be doable once we allow template helper functions (#63). Will that resolve this issue?

@SergioBenitez SergioBenitez added the request Request for new functionality label Mar 9, 2017
@LaylBongers
Copy link
Author

You understood it right, there's however an important difference between child handlers and template functions. A child handler would be able to receive the same parameters a normal handler can, it needs to access cookies and state without the template needing to pass it anything. This is important because the child handler essentially acts like a nested controller-view combination in MVC terms. If you in my example had to pass it the signin data every time through the template then the problem hasn't been solved yet.

@SergioBenitez
Copy link
Member

I've been thinking about this over the last month or so. My initial reaction was that this feature is not in line with Rocket's philosophy, and this continues to be the case. This feature requires Rocket to implicitly call a request handler when a function is invoked from a template. Further, it requires Rocket to make certain request handlers global to all templates. The former directly violates Rocket's philosophy on being explicit, while the latter violates Rocket's philosophy on global state.

Because request handlers are just functions in Rocket, you will be able to register them as helpers trivially once #63 lands. While this doesn't directly provide the same functionality, it allows you to reach the same goal while being more explicit. I believe this is the right compromise.

For these reasons, I am declining this request and closing this issue.

@SergioBenitez SergioBenitez added the declined A declined request or suggestion label Apr 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
declined A declined request or suggestion request Request for new functionality
Projects
None yet
Development

No branches or pull requests

2 participants