I have an application with several controllers dedicated each to its own part, say, "news", "articles" and "shop". They are not connected to each other, but they should be, as I need to insert data from them, like news related to current shop category. I have not found a clean way to access controllers other than the current one that is handling the request.
The structure of the modules is:
Site.pm is the main project file.
Articles.pm handles articles.
News.pm handles news.
Shop.pm handles shop.
Site.pm loads each of the above dynamically from an array of module names and calls its register function to set routes up and other things at startup. Articles, news, etc all take content from database, and it is rendered as inline template, thus, I can't just take related news and slam them into the stash, as not all entries in shop might even need that information.
This is a theoretical answer without code.
You probably have the database stuff decoupled from the actual controllers as models. That's good.
So let's assume we're in the shop and we want to show news related to the current product. There are at least two ways to do that.
You call your models directly. Your model for news provides a way to get the news for a product. You do that in the shop controller that displays the product page. This controller needs to put the stuff in the stash so the templates can access it.
You create a method in your news controller that is not accessible from the outside. You make it take a product id and find related news articles and populate them into the stash. You forward to it from your product page controller in the shop controller. Afterwards, the product page controller continues. This is the more decoupled way.
In both cases, your shop template includes another template that knows how to deal with the stuff in the stash for displaying news. You might be able to recycle a news template here.
I have not worked on Mojolicious but IMO this is the best approach -
Your Site controller should send GET requests to whatever other controllers it wants and these controllers should return JSON data which can then be rendered at the client side. Take a look Rendering JSON. Hope that helps.
Based on my experience, coding-blood, and a lot of shame for my code, I advise:
each method in a controller should only call a single function and pass the results to the template. This is somehow similar to the answer of #simbabque.
This will help you later testing the controller, writing API instead of providing html templates, even change the framework completely (as long as it is Perl).
So, I would add an optional layer between the Controller and the Models:
$t->get('/books/:id')->to('books#get')
sub Books::get{ my $self = shift; my $book = FBooks::get($self->param('id')); # plus template call }
sub FBooks::get{ # here you call your Model }
# your Model calls your DB
You provide the FBooks::get only then, when you need to make multiple calls to your model/s (maybe this is not a perfect example, but I hope you get my point). I prefer this instead of an army of helpers. If there is any other better way, I am happy to learn it.
Related
The backend developer has designed the RESTful API in such a way that when going into a section of the site I call one large request for all the data in all the sub sections. These sub sections data can be modified and saved. If that happens I would need to create a new model based on the model from the large request, populate it, and save it to a different service (PUT). This service can only PUT and not GET. I would probably create this model as soon as the user navigated to this section, and display the view based on this new model. Now if i navigated to another sub section, that large request model would be out of date and I'd have to fetch it from the backend again instead of making a smaller request for that section.
I propose to him to just create separate services for each sub section that i can easily fetch and save to (I'm using Backbone). Otherwise I'm creating sub models off a main model and they are dependent on each other and I'd have to write the code to wire them together instead of leveraging the power of the built in methods on the model like save, sync, fetch.
Does this not also create an issue in creating modular components if models are depending on other models?
Has anyone seen it done this way?
I'm in a similar situation. Our API was designed under the philosophy that a single request should give everything needed to render a page. So there's one major API endpoint that returns a main data type, and all nested objects are returned in a partial state. So if I'm requesting "employees", the API won't give a "department id" it will return a partial department object like:
department: { "id": "1", "name": "Department A }
There are great benefits to this approach! Making multiple requests is expensive, and you don't want dozens of API hits for every page load. The problem you'll find is that Backbone was designed for one to one mappings between models and API endpoints. They don't give you anything like a Data Access Layer, if they did both our problems may be solved.
My team generally would make "department" an attribute for the Employee model. This has a big problem. The way that Backbone Models register changedAttributes doesn't play nice with complex objects in attributes, which complicates forms based on data structured this way. It's somewhat frowned upon by Backbone developers too. The general consensus is to store complex objects in a property of the Model class, rather than an attribute.
In any event your parse and toJSON methods will get a lot more complicated than what you'll typically find in examples.
I would recommend you to use BreezeJS, which is built only for data rich application. Check out this link
http://www.codeproject.com/Articles/730450/Creating-Single-Page-Application-using-Hot-Towel-T
I'm looking for some help wrapping my head around a good approach/architecture to handle images in my ASP.NET MVC 2 application. The application is a client for a middle-tier web service application that encapsulates our domain logic and rules. The images are stored in a back-end database that is only accessible through the web service.
For the sake of this discussion, we'll use the classic case of a Product which has an associated image. Whenever I display information about the Product, I also show the image. So, for instance, when viewing a list of Products to an admin for editing, I will show the image and the name of the product as a hyperlink. when editing, the user can see the existing image and upload a replacement. I also show the image when users browse lists of Products or look at what items are in their 'shopping cart'.
Needless to say, I have to obtain the image data a lot. (And, yes, caching will be a part of the solution but not part of my question.)
My first task was to create the controller and views used to edit Product data which includes the ability to upload the image. I followed the approach described in Pro ASP.NET MVC 2 Framework where I set the image element's src to a controller action which returns the image data. The controller receives a reference to the ProductManagementServiceAgent in its constructor and delegates to the agent which handles the call to the web service. This works great but, of course, it means two calls back to the service to display the information.
Next I have to display the list of Products, with images, to the admin. In this case it's not a problem because I'm using the same controller with the same action, so I can use the same approach. Unfortunately, now I'm making 'n+1' calls to the service.
My quandry comes when figuring out how best to handle all of the other use cases where I need to display the image. Inside the 'shopping cart', for instance. Should my ShoppingCartController also reference ProductManagementServiceAgent and use the same method to retrieve the product image? This would mean any controller that displays a product image would have to reference the agent, yes?
The first thing that bothers me about this is that I don't like injecting multiple dependencies into a class if I really don't need to and see long parameter lists in constructors as smelly code (tells me the object is trying to do too much). Plus, the ProductManagementServiceAgent is really intended for the admin UI, so maybe a different agent would be better? Or a different approach all together?
I have to think that others have already charted this territory, so I appreciate any wisdom to set me in the right direction.
Have a dedicated controller for images.
It will have one dependency - the ProductManagementServiceAgent.
Cache it both server side and client side to minimise requests.
I actually went with a suggestion not posted to this site so I can't give proper credit. In a nutshell, we expose additional actions on our controller when an image is required. So, for instance, our ProductController has a ProductImage action method that accepts the product id and returns the image. It seems to satisfy our needs.
I have a situation with my MVC2 app where I have multiple pages that need to submit different information, but all need to end up at the same page. In my old Web Forms app, I'd have just accomplished this in my btnSave_Click delegate with a Redirect.
There are three different types of products, each of which need to be saved to the cart in a completely different manner from their completely different product pages. I'm not going to get into why or how they're different, just suffice to say, they're totally different. After they're saved to the cart, I need to "redirect" to the Checkout view. But it should be noted, that you can also just browse straight to the Checkout view without having to submit any products to add to the cart.
Here's a diagram of what I'm trying to accomplish, and how I think I need to handle it:
Is this correct? It seems like a common scenario, but I haven't seen any examples of how I should handle this.
Thank you all in advance.
Yes, this is certainly one way to handle it. If your widgets, whatzits, and whozits views are really that different, than it's probably not worth it to try any sort of inheritance scheme or smart view that is capable of displaying any of them depending on what's passed in as the view model.
If you're asking for how to handle the redirect, you should probably use RedirectToAction("Action", "Checkout") when handling the save actions on your widget, whatzit, and whozit controllers.
It would be good if you had a base Model class for each of these XYZIt items and could pass them as a collection of CheckOutItems to the checkout controller directly instead of having these intermediate controllers in there. Not really sure why you need to have these extra controllers.
You can use RedirectToAction
I'm developing an ASP.NET MVC application where the content for any page can be pulled from the database, if it exists, and displayed on the page.
This is to make it possible for non-technical persons to edit the content without having to go into the source code (e.g. views) and change things.
The way I'm doing this is, each controller derives from a base controller. The base controller overloads 'OnActionExecuted' and takes this opportunity to pull any content assigned to the current Action/Controller.
If the action returns a ViewModel that derives from 'ContentViewModel', it populates the 'Text' property of the ViewModel with the text from the database.
And then the text gets rendered by the View.
Can you see any weakness to this design?
Would it be better if, rather than having a base controller, I had HtmlHelper extensions for pulling content, which I call from the View?
One reason I'm asking this is, having my own base controller seems to interfere with calling 'Html.RenderAction', which seems to expect the specified controller to directly inherit from 'System.Web.Mvc.Controller'.
ActionFilters should not be used to pull the content.
Controllers should not be used to pull the content but only to dispatch the incoming requests by applying simple logic.
HTML helpers should not be used to pull any content. They are meant to render UI elements prefilled with the supplied data.
application where the content for any page can be pulled from the database
That's basically how most applications operate.
This is to make it possible for non-technical persons to edit the content without having to go into the source code (e.g. views) and change things.
For non-technical persons to edit content there should be an appropriate UI. Independently of the project underlying technology, non-technical personal is never supposed to edit the code.
I suggest you don't make anything weird but keep things clear. Implement your business layer that will supply the data to models which the view will render. Create a UI for other people to edit the content.
I am writing a Catalyst web application that presents some data that does not change in between requests. I want to load this data when the application starts and stick them somewhere so that the relevant controllers can use them. Where should I load this data and where should I store it? At first I tried to load it in the main App.pm file and put them into the application config. This works, but it’s ugly, since the App.pm file gets littered by a lot of loading subs that don’t really belong together:
__PACKAGE__->config(this => load_this());
__PACKAGE__->config(that => load_that());
# et cetera
Then I figured I could load some of the data in the controller that uses them and store them in the controller’s config hash. This is not perfect either, because some of the data is needed in more than one controller.
I also thought I could localize the data to the controller instead of sharing them. This feels nice, because I would have all the code that works with the data more or less on one place. The problem is that the controller would also have to render parts of the resulting page for other controllers – for example if the title page controller wanted to display a list of recent news, it would have to ask the news controller to render the list. This does not seem to be the preferred way of doing things in Catalyst.
How would you solve this?
(The nature of the data: This is a website of a music festival. There is a line-up, a list of sponsors and other simple data pulled from YAML files, because database would be overkill and hard to edit.)
Fundamentally, the data should belong to the Model, which is to say your YAML files should be represented by modules in your application's Model. That's one reason you separate the model from the controllers in the first place: All of your controllers can talk to the same models, without having to replicate their information within themselves.
There's no reason you can't cache the data persistently in these modules, using plain perl data structures or whatever caching technique you like.