Using CMF DynamicRouter for Doctrine entities - symfony-cmf

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.

Related

How should MVC Controllers be organised?

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

has_many :through model names, controller and attributes best practices?

Disclaimer: I really spent time thinking about names of models and variables. If you also do, this question is for you.
I have a Rails project which contains two models: User and Project.
They are connected by the model ProjectsUser, which is a connection model in a many-to-many relationship. This model also holds the role of a user in the given project, along with other attributes such as tier and departments. So this is a has_many :through relationship.
Given this scenario, here is everything that always bothered me on all my rails projects since I started developing on it:
Should I use a ProjectsUserController or better add the relevant actions on UserController and ProjectController? At some point, I want to assign users to a project, or even changing the role of a user in a given project. Is it a better practice to leave those actions on the connection controller, or use the model controllers?
Should I write a method to get the role of a user for a given project? This is basically if I should have a method User#role_for(project) or not. Since this method basically is getting the information from the projects_user object it could make more sense to always let this explicity on the code, since most of the times I'll have the project and the user, but not the projects_user. Is this line of thinking correct, or maybe the problem is that I'm should have more project_user on my code than I really do? Are there good caveats for this?
Should I try to rename my table to a non-standard name if it is not obvious? Ok, I got that if I have the models User and NewsSite I should use has_many :subscriptions, but the thing is that naming those models in real life cases are usually harder, by my experience. When the name ends up not being that obvious (for exemple, in my case, maybe project_participation as #wonderingtomato suggested) is for the best, or in those cases it is better to fall back to the ProjectsUser approach?
One extra cookie for pointing beautiful open source Rails code, or by book indications that might help with my kind of questions.
I would use a specific controller. Even if now the interaction sounds simple, you can't know if in the future you'll need to add more advanced features.
I've been handling these kind of relationships in several projects, and using a controller for the join model has always paid off.
You can structure it this way, for example:
index should expect a params[:project_id], so that you can display only the index of users for a specific project.
create is where you add new users, that is where you create new join models.
update is to modify a value on an existing join model, for example when you want to update the role of a user in a project.
destroy is where you remove users from the project, that is where you delete the corresponding join models.
You might not need a show and edit actions, if you decide to manage everything in the index view.
Also, I'd suggest to choose a different name. Rails relies heavily on naming conventions, and projects_users is the default name for the join_table you would use with a has_and_belongs_to_many association. In theory you can use it for an independent model (and a has_many through:), but it's not immediately clear and you might break something. In addiction, it will confuse the hell out of any new programmer that could join the project in the future (personal experience).
What about calling the model something like project_participation?
If you haven't built a lot of functionality yet, and don't have yet that table in production, changing it now will save you a lot of headaches in the future.
update
1) I stand by what I said earlier: your join model is a full fledged record, it holds state, can be fetched, modified (by the user) and destroyed.
A dedicated controller is the way to go. Also, this controller should handle all the operations that modify the join model, that is that alter its properties.
2) You can define User#role_for(project), just remember that it should properly handle the situation where the user is not participating to the project.
You can also make it explicit with something like:
#user.project_participations.where(project_id: #project.id).first.try(:role)
# or...
ProjectParticipation.find_by(project_id: #project.id, user_id: #user.id).try(:role)
But I'd say that encapsulating this logic in a method (on one of the two models) would be better.
3) You are already using a non standard name for your table. What I mean is that it's the default name for a different kind of association (has_and_belongs_to_many), not the one you are using (has_many through:).
Ask yourself this: is the table backing an actual model? If yes, that model represents something in the real world, and thus should have an appropriate name. If, on the other hand, the table is not backing a model (e.g. it's a join table), then you should combine the names of the tables (models) it's joining.
In my mind, REST doesn't always have to map directly to DB records. A conceptual resource here is the association of Projects to Users. Implementation would be different depending on your persistence layer, but a RESTful API would be standard.
Convention over Configuration in Rails is a great helper, but it isn't necessarily applicable to every case 100% of the way through the stack. There doesn't need to be a 1-to-1 mapping between controllers, models, and their respective names. At the app-level, particularly, I want my routes/controllers to represent the public view of the API, not the internal implementation details of the persistence and domain layers.
You might have a UserProjectsController which you can perform CRUD on to add/remove project associations to users, and it will do the appropriate record manipulation without being overly bound to the DB implementation. Note the naming, where the route might be /user/:id/projects, so it's clear you are manipulating not Users or Projects, but their associations.
I think thinking about this sort of thing (both before and after the fact) is what leads to better designs.
I too start with the model and think about the application structurally. The next step in my oppinion is to build the user interface to make sense based on what makes it easy and useful for the user (spending more effort on things that matter more). So if it makes sense for the user to separately edit the ProjectsUser objects then the ProjectsUsersController is the way to go. More likely editing the join model objects as part of the Project (or User depending on the structure of you app) will be a better fit for the user. In that case using a nested form and editing via the controller (and model) that's the main model referenced by the form is better. The controller really lives to serve the UI, so decisions about it should be dependent on the UI.
Yes, if it makes your code simpler or more readable. If you use role more than once I suspect it will.
I would actually name that model something like Member, or ProjectMember (or Membership). It defines a relationship between a user and a project, so its name should reflect what relationship that is. In the occasions where such a name is too unwieldly or too hard to define then falling back to something like ProjectUser is reasonable (but not ProjectsUser). But I definitely like finding a more meaningful name when possible.

What is the Ruby on Rails naming convention for models/controllers that are parts of another object?

I'm not sure about the naming convention for objects that are related/parts of an object in Ruby on Rails. Heres an example of this:
I have a User object
I have a separate Image model that only stores images of the User object
I also have a separate History model that only stores the actions of the User
Would it follow Rails convention to name them to UserImage and UserHistory models? Or is this not following convention? If so, why not?
Thank you!
It generally depends on what other names are used in your application, and to some degree on personal preference.
My preference is not to add namespace prefixes unless it's really necessary because of namespace collisions, or is confusing because of similarly named structures with my application. Also it is more of a rails convention to use suffixes to prevent naming collisions with classes in different areas. For example controllers are all suffixed with Controller, mailers suffixed with Mailer, decorators with Decorator and so on.
In your case I would stick with User, Image and History. Prefixing Image and History doesn't really gain you anything, unless you have other types of Image/History models, in which case it might be better to look into polymorphic relationships instead of namespace prefixes.
It's mostly a matter of style and maintainability.
If you name your models this way then you will not be able to develop associations between models. Ex. UserImage model will be considered as a single entity not association of user and image model. If you want to develop this type of associations use HABTM relationship. Thats why rails follow "Convention over configuration".

what is the most efficient way to rename/refactor the name of my MVC

I have my MVC ready, but now, there is a requirement to rename them to a new name, from top level down(including View, Controller, ActiveRecord model names). What's the most efficent way to refactor all of them?
For example, rename from "Car" MVC to "Train" MVC without change the functionalities inside, only change the names. (the "Car" model also have some associations to other ActiveRecord models)
Unfortunately, there's no magic solution, you need manually change the class names in each of the files, and anywhere in code you reference those names. Find and Replace is your friend.
Having been through the procedure a couple of times, I think it's better to do the work of changing all the names rather then trying to mask different underlying names with routes or aliases - you'll just end up with confusing code in the long term.

Asp.net MVC Architecture

I'm coming to the end of my first MVC project, and I'm not overly happy with how I constructed my Model objects and I'm looking for some ideas on how to improve them.
I use repositories for each DB table with Get, Save, Delete etc methods.
The repositories use Linq2Sql for the DB access.
I do mapping from the Linq2Sql objects to MVC Model objects, in the main, these are very much 1 to 1 mappings.
My problem is, I don't think my MVC model objects were granular enough, and I am probably passing more data back and forth than needed.
For example, I have a User table. An admin can edit a users details as can the user themselves, so I reckon I should really have a "AdminUserModel" and "UserModel" objects, where "AdminUserModel" has a greater set of values (IsEnabled for example).
So my bigger question is really, what kind of architectures are people using out there in the wild, in order to map many similar, related Model objects down through the layers to the DB?
Any sample architecture solutions anyone can suggest beyond NerdDinner?
thanks in advance!
In the case of your user model, you should use inheritence in stead of 2 seperated models. In this way you can use the code that was created for user in the ones that inherite from it.
the type of model you use depends completely on what you want to do with it. A good thing might be to take a look at patterns and try to get the patterns working that are needed for your situation...
I usually take implement inheritance in my models.
I usually have a base class of entity, which will have id, datecreated, valid and any other fields that are shared between entities (publishStatus, locked etc).
If needs be you can create other base classes inheriting from entity: person entity, product entity etc.
this way you can have a generic repository base, constrained to Entity or IEntity, i find that most entities CRUD functions dont need much more behaviour than that provided by the generic base (perhaps you will need to add a few additional get methods for some types)
In your case, AdminUser could inherit from User

Resources