I'm new to MVC pattern and Sails. From my understanding, it seems like I should create a controller for each model. A controller is like one page.
So, if I want create a page containing product category, product list and user authentication, there are 3 models in my page. How should I structure the controllers?
You don't have create separate controllers for each model.
Controllers handle the request from the client and return views, JSON, etc.
You may be being influenced by how sails documentation explains things due to their blueprints.
Mvc does not require a 1 to 1 of controller to model. Your controller should take care of massing the data and rules needed to show your view or a group of different views. A controller may have a link to a group of your functionality e.g. user management where you handle registrations, login, forgotten credentials etc. This may require a few different models and not just your user model. It may also display a number of different views too.
Sails.js comes with blueprints enabled which means a user model will have create,update,find,findone etc against a user model. Infact sails doesnt need a controller in this instance but you could make one to over ride logic or add additional logic. There is however nothing stopping you calling a user.find method in the user controller as well as a pets.find. Just think of the controller as the conductor telling and calling everything to fire and bringing this information together to push into a view or number of views.
Related
In a "classical" web MVC - please correct me if I'm wrong:
the controller passes the request data received from the "user" (be it browser, console, etc) to the model layer (consisting of domain objects, mappers, repositories, services, etc),
the model layer processes it and returns some result data,
the view - as specialized class(es) - processes the result data and sends/displays it to the "user".
I would like to ask:
Does the controller create the view?
Or does the controller receive the view as a dependency?
Or are the controller and the view created completely separately, on the front controller level (let's say in index.php)?
Thank you.
Your definitions of MVC in generally is right, here is answer for your ask:
Controllers are not responsible for rendering the interface, nor for
presentation logic. Controllers do not display anything. Instead, each
controller's method deals with different user's request. It extracts
the data from said request and passes it to model layer and the
associated view.
Decisions about what and how to display are in purview of views. Views
contain the presentation logic in MVC pattern. In the context of web
applications, views create the response. They can compose a from from
multiple templates or just send a single HTTP header.
Controllers can signal the associated view by passing some specific
values of the request to that view, but most of the decisions in the
view are based on information that the view requested from different
services in the model layer.
A Controller's methods are based on what type of requests a user can
send. For example in a authentication form it might be: GET /login
and/or POST /login.
Source: Controllers, tereško
Classic correct MVC class structure:
Easy definition:
Model. The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller).
View. The view manages the display of information.
Controller. The controller interprets the mouse and keyboard inputs from the user, informing the model and/or the view to change as appropriate.
Source: Microsoft Docs
Additional resourses: (only useful ones)
External
MVC Explanatory [computer science design patterns]
Creating a Custom Controller and View in CodeIgniter [a visual example]
Codeproject's definitions MVC: easy | extended
Internal
The relationship between Model, View and Controller
MVS in a conversation form
The controllers are entry point of MVC, controllers call to model , and model check wich view display , example, magento (mvc)
Based on my current understanding, if I had to describe how the various components of a rails app work together to respond to requests, I would say the following:
1) Routes determine which request URLs map to which controller methods.
2) Controller methods obtain information from the models and pass that information (in the form of global variables) to corresponding view templates.
3) View templates use the data stored in the global variables to construct the final response.
In the above explanation, the relationships between several components are clear and undeniable; namely:
1) routes and controller methods
2) controller methods and view templates
In fact, the above relationships are 1-to-1.
However, the relationship of the model classes to their adjacent component type (i.e. controllers) is not as clear. Yes, the controllers retrieve information from the models, but consider the following:
1) A controller does not necessarily need to retrieve information from a model, as would be the case for a static website.
2) A controller could retrieve information from multiple model classes.
Therefore, would it be accurate to say that models exist slightly more separately from the other components? Would it be accurate to say that, taken together, the model classes make up the back-end of the back-end of your application, whereas the other components (i.e. routes, controller methods, and view templates) compose a tightly-coupled, linear mechanism wherein the controllers dip into the model classes as necessary? And more specifically, would it be accurate to say that, at least in the context of how the rails components actually fit together, there is no natural relationship between any given controller and any given model (e.g. UserController and User)?
Yes, I know rails comes with the "resources" keyword for use in the routes file to generates RESTful routes and that things are often done in a RESTful way in rails. You could say that rails lends itself to the development of RESTful web applications. And in the context of a RESTful application, the model and controller are implicitly related to each other. But that's a description of the REST architectural style. I'm asking about rails. It seems to me that in rails itself, models are only related to controllers to the extent that the model is used in the implementation of the controller's methods - and because code organization in software is arbitrary, those relationships are arbitrary.
I'm thinking about these things because I want to add a way for users to view their own profiles. I already have a User model and a controller and views for displaying information about users. The profile page would display information from the User model, but I don't want to use the same controller or views for the user's own profile as I do for displaying information about other users. So, I plan to create a new controller and views for the profile, but use the User model to retrieve the information that gets displayed. It's an arbitrary decision, much like other arbitrary decisions made when building an app. But it wouldn't be a valid decision if for some reason models and controllers were supposed to remain tightly coupled (e.g. 1-to-1) in rails.
Can anyone confirm or refute what I'm saying?
For a great explanation of MVC, check out Jeff Atwood's post: http://blog.codinghorror.com/understanding-model-view-controller/
Now as for your app, one controller is just fine for displaying User's profile pages. What you should do to ensure security is that for the UsersController#show action (profile page) you should validate that it is the current user, otherwise redirect, or show error message, or show the editable page, etc.
#user = User.find(params[:id])
if current_user != #user
render :show
else
render :self_profile
end
Another method you could use is:
#user = User.find(params[:id])
if current_user != #user
#authenticated_user = true
end
render :show
Then in your view template, you can have a conditional:
<% if #authenticated_user %>
#Edit button here, takes you to the settings page
<% else %>
#Follow button here
<% end %>
current_user should be a helper_method defined in the application controller.
Creating independent controllers is fine. You could also create a route that points to your UsersController#show action and handle the case when the user is viewing his or her own profile there.
In a non-trivial app you will end up with controllers that do not match resources and models that do not have a controller and that's ok.
In your case, maybe all you want is a different route (ex: www.example.com/me), that doesn't mean the action logic can't be in the UsersController. In the end, it's all about keeping similar logic in one place so that it's easier to maintain.
I've learned that you should set up the controller-class in a MVC-OOD as a use case, from top to bottom in only one method that run the MVC-classes.
Is it OK to use different methods in one controller to get more control and better overview?
Let's say you wanna run a controller that will display a login form (getting the html etc from the View). And the same controller will also display a log-out button IF the user is NOT logged in.
This could be done with a single method in the controller, but using two methods seems better. One method to call if you want the login form, and one to call if you want to log-out button.
(just an example)
So, what does the pros say. Should each controller contain one "use case" method only, or could it be several?
TL;DR -- you have misunderstood the MVC design pattern and are doing it wrong.
Controllers are not responsible for rendering the interface, nor for presentation logic. Controllers do not display anything. Instead, each controller's method deals with different user's request. It extracts the data from said request and passes it to model layer and the associated view.
Decisions about what and how to display are in purview of views. Views contain the presentation logic in MVC pattern. In the context of web applications, views create the response. They can compose a from from multiple templates or just send a single HTTP header.
Controllers can signal the associated view by passing some specific values of the request to that view, but most of the decisions in the view are based on information that the view requested from different services in the model layer.
A Controller's methods are based on what type of requests a user can send. For example in a authentication form it might be: GET /login and/or POST /login.
Its important to remember two things with MVC, firstly, its an Object-Oriented Architecture, and secondly, It should be used for separating concerns.
Separation of Concerns is related to Abstraction, It is to aid us in understanding the section of code at hand. The Model and View are both collections/domains of related objects. Each object is fully complete and relevant to its domain.
You will find objects with types such as Buttons, Images, Text Inputs etc inside your View, and you will find business related objects (User, Account, Profile etc) within your Model.
The collection of objects inside your Model don't tend to do much, They require logic to wire the objects together. (Or simply delegate simple single object requests to the correct object)
The Controller provides the interface into your Model, and contains the business logic related to the Model and the interactions between the Model objects. You will have a single Controller for your Model, and the Controller will have multiple methods which will align with your use-cases.
This is more of a non-code related question. I want your experience here and suggestion. I am designing this simple web application where I could just insert data, and then making sure the website will view that data based on categories.
In my controller, I have functions, each loading based on which category is selected from my main page.
Now I am wondering, is it better to create multiple controllers (like I used to have separate classes when using OO Php) for say CRUD operations, Listing the records, Search functionality, etc. Or just keep it all centralized in one controller (the current approach)? If multiple controllers, any recommendations?
You should have a controller for each separate functionality your websites provides.
For example:
controller for handling "regular" content (articles) (displaying articles, searching, rating, etc)
controller for handling user management (login, logout, registering, etc...)
controller for "static" pages like about, help, tos, etc...
And you should also handle all database operations in model classes, each for different entity (model for articles, model for users...)
I hope you got the point
Codeigniter uses an MVC structure, so you should actually use models for database operations, and separate them in a way that each model is used for a specific functionality.
If all the categories are handled the same way, you should add all the retrieving from db code in a single model, that way you simplify your code making it a lot easier to maintain.
In MVC, where is the correct place to put authorization code?
The controller?
The Model?
In the view?
All over the place?
I vote for putting it where it makes sense. Most of my authorization stuff is handled via decorating controller actions (or even some controllers) with the AuthorizeAttribute -- or an attribute derived from it. In a few cases -- like my menus -- I've resorted to putting the authorization check in the view code itself, rather than calculating it in each controller and passing flags down in ViewData. There are a few instances where certain aspects of the model are only available to particular roles and in those cases I've resorted to extending the model with methods that can take the current user and roles and do the check there.
I think authorization is a cross-cutting concern. Should be in one place - an aspect that can be declaratively applied where it's needed.
The Controller!
Your View should only handle user interface and display
Your Model should represent the data in your system.
Your Controller should handle the logic of how the system works.
Authorising a user involves taking the credentials provided from the View, checking them against some sort of authorisation list in the model and then performing a check.
This is done in the controller:
Get user credentials from View
if(compare with user list in model returns match)
authorise users
else
refuse access
If you have to choose between M, V or c, the C is the correct place. But, I recommend an architecture where your app is all contained in libraries and the UI is just a thin veneer. You end up calling down the stack from the Controller, but the code is not in the controller.
In MVC, the Model is just a model, or a "dumb data object", if you will. It is designed to hold state, and should not dictate behavior. The View is for the user to interact with and is also "dumb"; the view handles UI. The controller is where behavior sits, or is the entry point into behavior in the case where the app logic is in libraries. Make sense?
Model.
Controller is just for switching through different ways. View is just for... viewing.
So you should make all authorization codes in the Model layer. Ideally, everything will work just fine. If not, then the controller will take the user to the proper login box.