Hey <@U0BVACZHB>, not to get mixed up in that very...
# cfwheels
d
Hey @mike42780, not to get mixed up in that very opiniated thread about MVC perfection, I too have done both in several projects. When it comes down to sending out an email, I see that as a View (just like when I return PDFs or Excel) that gets called from the Controller. Naturally, the email never gets returned directly to the user but you can fire it off just the same from the Controller and still return them to a success screen. Personally, I like the Active Record model approach to things because it keeps things simple and centered around the data. Because of that, I usually only use afterSave if it affects another model. But that's just me, that doesn't mean you need to do it that way.
a
That's interesting. So in a platform-agnostic way, you'd have this sort of thing:
Copy code
myControllerMethod(requestBitsAndPieces) {
    someData = myModel.doStuff(requestBitsAndPieces)
    
    renderEmailView("theSpecificEmailView", someData)
    return renderResponseView("responseView", someData)
}
And here
renderEmailView
handles both the the actual composition of the email content, and the transmission of same? Initially I thought that seemed like a good solution, but it's a bit tight-couply around the "render" and "transmit" pieces. I think where the idea separates from a sound approach is this bit:
sending out an email, I see that as a View (just like when I return PDFs or Excel)
For this analogy to hold, then just the rendering of the email document would be the parallel to the PDFs / Excel. The views that render the binary data for the PDF or Excel don't also send the response to the client. I agree the email content should be handled by a view, but there's still the matter of the transmission. This is why I was wondering about offloading the emailing to a sub-controller... and then evolved to it being the job of an email service that has some sort of templating / view handling itself (as per Sean's approach). And also that it's business logic that an email is even a "thing" for the given business processing being served, so - again - not for the controller.
I like the Active Record model approach to things because it keeps things simple and centered around the data. Because of that, I usually only use afterSave if it affects another model.
That is very good thinking, I like that. Kinda like a trigger.
m
That's interesting. So many different ways to do the same thing. Why I thought it might be interesting to see what others do as I pondered to do the email trigger in the controller or model based on my wanting to cfinclude the body of the email and not clutter up the component. I tend to lean more toward the model with an aftersave because I like the confirmation email close to where the data is saved, so I don't miss it when reviewing code and just seems to fit better. But doing it your way works works well too.
You could even write the emailconfirmation() function in the model and call it in the controller. Not sure you'd want to, but the option is there. emailResult=model("comment").sendConfirmationEmail();
a
Yeah the implementation def belongs in the model. I'd probably try to call it from the model too. Given CFWheels's notion of "model" is more closely related to like a repository in the Repository Pattern (https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design), it'd be nice if there was also a
services
directory which were similar to
models
, but free of all the DB / ORM baggage (and a lot of the rest of the kitchen-sink stuff that are included into model objects and don't really belong there). That'd go a long way towards solving situations like this.
And would make one's code a lot clearer.