My Grails domain model consists of something like the following:
Competition - with name String property
Club - with name String property
Team - with club and competition properties
Game - with teamOne and teamTwo properties
I'm looking to create a Game form that contains the following:
a competition drop-down
a team one drop-down
a team two drop-down
For my team drop-downs though I wish to just have a list of Club names e.g. ${Club.all}
However, I then wish to have some interceptor that will use the Competition and Club name to construct the appropriate Team before the Game entity is constructed
I do not wish to introduce any Ajax/Javascript to my application, I want to keep the UI work as minimal as possible.
How can I achieve this?
You could use the beforeInterceptor available in controllers. I'm not exactly sure if this is what you are looking for, but it sounds like you can do what you describe.
Related
I am creating an events class for an application, the event has different categories for which a participant can sign up for e.g if they are a veteran cyclist or a master cyclist. In addition, an event can be seeded or not as well, would it be advisable to have two enums one for the categories and one for the event being seeded or not, or is there a better way to do it?
I have the following two Doctrine (ORM) entities:
Product
Category
Category contains one or more segment (level):
category
category/sub-category
Product contains a name and possibly a color. A Product either has a color or not.
product
product/red
I'd like to have both Category pages and Product pages.
The Category URL should be made up as {locale}/{category_path}, e.g.
/en_US/category
/en_US/category/sub-category
The Product URL should be made up as {locale}/{category_path}/{product_path}, e.g.
/en_US/category/product
/en_US/category/product/red
/en_US/category/sub-category/product
/en_US/category/sub-category/product/red
The problem with using Symfony's routing is that there maybe matching confusion between the following routes since they have the same number of segments:
/en_US/category/sub-category
/en_US/category/product
Is this something I can use the CMF DynamicRouter for? If so, at a high level, what pieces do I need to build? Do I need to use a RouteProvider for each Entity?
to use the dynamic router out of the box, your entities need to be able to implement the RouteReferrersReadInterface. That is, they need to return route objects. And you will need to implement the RouteProviderInterface so that you can find the documents in the database.
With the Doctrine ORM, you probably want separate route entities (one per language) that contain the manifested path and link to the products / categories. Afaik the ORM can only link between known entities - one way to use the same route object would be to make category and product share a common base class that is a Mapped Super Class. The product color variants could be done as a variable part of the URL, so you end up with a pattern saying .../{color}
With the CMF route enhancer, you can configure different controllers for category and product pages.
A limited example of ORM routes is provided with the RoutingBundle. You might extend the base entity, or do your own starting with that. The documentation on symfony.com is often first mentioning how to work with the default storage of the CMF, the Doctrine PHPCR-ODM, but things should work with the ORM as well. Open issues on the cmf github project if something does not work.
Is there a general rule of thumb to how controllers should be organised?
Should Controllers only be created if they are linked to a domain model?
For instance if I have a 'Product' model, I would have a ProductController, which would have actions such as 'GetProductDetails' etc...
But what about things that don't have an actual model, such as searching for products, and returning multiple products on a page?
Since the Product model is the underlying model for all these interactions, should this functionality be included into the ProductController and have actions for searching and displaying multiple products, or should another be created for Search?
If you follow the pattern used by the scaffolding used in visual studio then yes you end up with one controller per entity so a product controller would have a actions that returned a list, a single product and an action for posting update to. In addition you might have additional search actions and any other product related actions. Which is just state and reinforce infer-on's answer.
However the reason why you would do this is that it means your code is easier to maintain - if you're looking for code to do with products you have one controller class to look in. You're also adhering to the principle of separation of concerns each controller is only concerned with one type of entity.
Further to this if your app grows much larger and you use an IoC / dependency injection pattern then you only need to inject one repository or business service per controller that is a search controller that offers methods to search for products and customers would need services or repositories for customer and products but a request might only be a customer search so the creation of the products repository was pointless hence you get inefficient and overly complex code. There are patterns to solve this issue but they involve even more code so to avoid this and to keep it simple stick to one root entity one controller.
You should manage every action which involve same resource with same controller, and you should implement that solution in accord with Richardson Maturity Model
A model (developed by Leonard Richardson) that breaks down the
principal elements of a REST approach into three steps. These
introduce resources, http verbs, and hypermedia controls.
so your API will be something like this:
/api/products GET Gets full list of all categories
/api/products/123 GET Gets the details for a single category
/api/products PUT Replaces the entire list of categories with
the one given
/api/products/123 PUT Update the specified category
/api/products POST Creates a new category
/api/products DELETE Deletes all categories
/api/products/123 DELETE Deletes the specified category
So I have been using data annotations for my validation in an MVC project and they seem to work in most scenarios.
Here are two examples in my current project where they don't seem to fit and I am unsure of the best place to put the validation.
1) I have a Join League page that contains a form where the logged in user enters their team name and clicks to join the league. When they submit the form i need to make sure that the current user doesn't already have a team in the league. So it basically needs to query the db for that user id and league id to make sure no team exists for the user. My ViewModel does not contain user id, since it is not relevant to the view.
2) On this same page, I also need to make sure the team name is unique. This is easy if you are just looking to see if it exists in a table. You create a custom validation attribute that query's a table for the value of the field. However i need to see if it exists in a table for a certain league id. (the league they are joining.)
It doesn't seem like Data Annotations are an ideal solution for anything other then trivial validation. My current solution is to query the db at beginning of post action method, and add the error to the ModelState manually. (yes, terrible)
Any ideas?
I think it may help to put some thought into the difference between Input Validation and Business Logic. Ayende has some thoughts on this here
Rules like 'When they submit the form I need to make sure that the current user doesn't already have a team in the league' sounds like Business Logic, not Input Validation, and you may want to handle it in a different way. This logic could, for instance, go into a 'CanSave' method on a 'User' class or something similar - the key thing is to separate this from Input Validation if you can.
Although I agree with Steve, DataAnnotations has a base ValidationAttribute in which you can implement anything you want. To say it can only do trivial things is not accurate in fact with this extensibility point you can do almost anything you want.
Now there are some issues with service location being all over the place by having database logic inside your code but there are options to clean this up. The DataAnnotations are applied via a ModelValidatorProvider class that can easily be configured just like you would do ControllerFactories or ViewEngines.
ModelValidatorProviders.Providers.Add(new YourCustomProvider());
Now what you can do in this case is have your validator provider provide the persistence layer code into your attribute. So the code stays clean yet you can use custom data annotation attributes that touch the db.
A View accepts one Model.
But I need to draw HTML input controls for two models.
An example will illustrate:
I have a screen where I add Employees.
After adding their first name, last name and so on, I need the user to choose a number of Companies the Employees could be in.
The Companies are in one table.
The Employees are in another.
And a linking table joins them.
So it seems I need to pass the Companies to the View.
Can I pass multiple models to the view?
Or do I have to do an ugly database lookup in the View to find the Companies and manually spit out HTML for checkboxes without HTML helpers?
A Model doesn't have to consist of just one object or a single collection of one type of object. It can contain many objects and/or collections of objects. It seems that the model required for your page consists of at least collections of both employees and companies. If you have no type which fits this bill in your business object abstraction then you need to create a ViewModel for this page which can do the job.
This answer may help to explain how a ViewModel fits in MVVM ViewModel vs. MVC ViewModel
This is not entirely obvious - I'm sure it is to some guru types but for the rest of us trying to work things out its a bit more interesting.
Without going into detail I see a number of ways of solving this:
You need both sets of data so you need a view specific View Model
Your model is the Employee but you can still add other data to the ViewData - so make the Employee the model and pass the company data in as well as view data but not part of the model
(You may want to do this regardless of what model you use) Render the company selection elements as a separate view - which is where things get interesting - you obviously have to pass the existing selection, or a means to identify same, to the component view but do you have to pass the company list or could you, at this point, cheat a bit (prgamatically)? My feeling is that this is a partial view and that you need to pass it a company selection model (list of companies with selection indicated) but you could in theory do RenderAction and have an action that returns a view that goes to get the company selection for the specified employee - that way the overall view never sees the company data, that becomes a separate encapsulated problem - at least in terms of loading the data.
I think in this case where you're adding the employee either tweaking the model or adding the company list as supplementary data to the ViewData is sufficient, but for editing - assuming its required - rather than inserting you want a company selection list (all the companies with flags to indicate which are currently selected) rather than just a list of companies and at that point it all gets a bit more interesting