How to represent cross-model information in MVC? - ruby-on-rails

I have an application, built using MVC, that produces a view which delivers summary information across a number of models. Further to that, some calculations are performed across the different sets of data.
There's no clear single model (that maps to a table at least) that seems to make sense as the starting point for this, so the various summaries are pulled from the contributing models in the controller, passed into the view and the calculations are performed there.
But that seems, well, dirty. But controllers are supposed to be lightweight, aren't they? And business logic shouldn't be in views, as I have it as present.
So where should this information be assembled? A new model, that doesn't map to a table? A library function/module? Or something else?
(Although I see this as mostly of an architectural/pattern question, I'm working in Rails, FWIW.)
Edit: Good answers all round, and a lot of consensus, which is reassuring. I "accepted" the answer I did to keep the link to Railscasts at the top. I'm behind in my Railscast viewing - something I shall make strenuous attempts to rectify!

As Brian said, you can create another model that marshals out the work that needs doing. There is a great Railscast on how to do this type of thing.
HTH

Controllers don't have to map to specific models or views. Your model doesn't have to map one-to-one to a database table. That's sort of the idea of the framework. Separation of concerns that can all be tested in isolation.

Why not create a model that doesn't inherit ActiveRecord::Base and execute the logic there (think the Cart class in Agile...With Rails).

Controllers don't have to be that lightweight.
However if you have some calculations that only rely on the model/s then you probably just need some sort of model wrapper for the models to perform the calculation. You can then place that into the API for the view so the view gets the end result.

You don't want the logic to be in the view. However you are free to create a database view. Except, rather than create it on the database side, create it as a new model. This will enable you to perform your calculations and your actual logic there, in one place. The pain of trying to keep your views in sync vs. the one time "pain" of creating the new model... I vote for a new model.

Related

Rails 3 project structure for UI Models and Data Models

This may be a really stupid question, but I do not have it clear in my mind as to how it is best to manage this so want to put it down here and see what is common practice.
Coming from .net my web applications are never 1 project which is everything, I tend to at least have a data layer project which deals with persisting entities to the database and making these models represent said entity in a DB friendly manner. Then I have my UI project which has its own models which are a representation of the entity for the UI, which may have validation based information and will most likely be a more cut down model only exposing what is needed.
So the main point I am trying to get out here is that although we may have a User entity, the models to represent that may be slightly different in the UI and Data layers...
Now fast forwarding to rails, you create your project and it comes with database connectivity (which I believe can be swapped out to any flavour you want), and validation and a whole manner of other frameworks and functionality. This then seems to imply that I no longer need 2 projects, just 1 as its all included within here and all done for me, so all I need to worry about are making my models.
This is the part where I am a little confused, as lets say I am using ActiveRecord I will need to make my model and inherit from ActiveRecord::Base, then I will need to setup how this model connects to other models etc, so I have my model's data concerns sorted, now I need to setup my UI concerns, about validation and string lengths etc... now where do these go... I am assuming on the same model, but then a model isnt just a simple representation of data, its a blob of stuff containing concerns for databases and views and who knows what else.
It just seems a little odd to put everything within this one place. I know in .net there are plenty of examples where with large object graph representations in the DB the data models are VERY different to UI models, so is it wise to couple them into one model this way, or is Ruby and its frameworks so flexible in this area that you do not have these same problems? If so is there some example or article which can solidify in my mind how you sidestep the normal problems that cause you to separate your concerns to have maintainable code...
=== Edit ===
Just to try and clear up any confusion, in my post when I say my view models and view concerns, I do not mean presentation concerns. I am sorry if it came across that way. What I mean is that I may have (in a normal .net example) a UserStorage model, which has concerns about persisting a User entity. I then in the ui layer have a view which displays many users and one that displays single users in more detail. You may have 2 differing models here a UserSummary model and a UserDetails model, both partially represent a User entity, but are customised for the actual view in question, as you may get to a situation where UserDetails also becomes a composition of a User and a Company entity, which would mean there are 2 storage based classes feeding into 1 view based class.
Within the examples and guides it makes out like you should have 1 view model which deals with these concerns, as well as storage concerns, and in this case it just seems like if I were in the situation where I had a view model that was a composition of a User and Company it would seem odd for this view layer class to worry about its storage, as its never stored as itself, it is stored as 2 separate models in the database/datastore.
This is the REAL problem I am trying to get at here, it seems to be tightly coupling your view to your storage concerns which I am used to being 2 different things which should never be mixed... like putting your main course and pudding on the same plate...
In vanilla Rails, there is no such thing as a "view model".
The models handle all business logic, including query and persistence, association, and validation. You seem to be dismissing validation as a concern of the view, but this is actually a core concern for the integrity of your models: it does belong there.
That's not to say that validation shouldn't happen in the view (client-side) too, but the model has your core business rules and is the place where the validation rules are ultimately checked.
You will want your models to hold most of the logic of your application. This means things like checking if a user is valid or active, finding related records, etc. Pretty much anything that isn't presentational belongs in the model.
In the view, Rails provides helper methods for formatting. These come from modules that are included in the view instance. Helper methods have access to the instance variables of the view (your models) and are used to present them.
In some situations, passing naked models into the view makes it hard to keep things modular and organized. Some people prefer using Presenters to wrap the models before passing them to the view. It can help to organize your code, but it's also an extra layer. Presenters are not standard in Rails, but it's trivial to add this pattern using plain ruby objects or a library like draper if it makes sense for your application.
EDIT: Oh look, a most excellent blog post on just this very topic came up today, from the most excellent Thoughtbot.
In a nutshell:
if it's about the data (storage, integrity, etc.) it goes in the model
if it's about processing/calculating the data (e.g. finding all pending orders) it goes in the model
if it's about presenting the data (pending orders should have a red cancel button) it goes in the view
Since you seem to be an experienced developer, you'd probably benefit from this book http://www.manning.com/katz/ Its geared towards developers that are new to Rails (but not to web programming).
Alternatively, there is a free online tutorial also http://ruby.railstutorial.org/
And of course, the Rails guides are always a good source of information: http://guides.rubyonrails.org/
Not one mention of MVC in your question, you should look into the Model View Controller pattern.
You should also look into how migrations work.

Rails - Method in Model or Controller or somewhere else?

I'm practicing my Rails development skills by building an app that will have different types of exercises for users. Most probably things like multiple choice questions for different subject matters.
One way to check to see if the questions are answered correctly is to use validations on the model. However, I don't really need to save the results, and it might end up in me creating a lot of different models, as each question will have its own validation to check each answer.
Is an alternative to create a new Controller action for each subject area? Is
How else might I organize this?
http://www.enode.com/x/markup/tutorial/mvc.html
With the MVC pattern, Controllers are usually in control of manipulating data kept by Models.
It's good form to keep most of your logic in your Controller. I'm not sure what you mean about a new Controller action, but what you'll probably want to do is set up some sort of form in your View, (see form_for) and fire that off to the Controller. The Controller does validations or whatever you need it to do.
This should be helpful:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
So for example, you might have a form in your View (a quiz for example), calculate a user's score in the Controller, and save that as a field for a user in your database.
The debate on where to put logic is as old as the involved patterns themselves. For MVC, I decided to ask myself:
Is the logic involved essential for the model?
Would the model (in itself) function well without the logic?
Is the model free of any requirements towards the controller?
If I'd re-use the model, would I want to take the involved business logic along or would it be in the way?
My general advice: Put business logic as "low" (bottom: db, then model, then controller, then view) as possible without violating any of the following constraints:
Authentication and authorization does not belong to view. It's either a property of the controller (handle things like sessions and general api access rules, etc) or of the model (authorization: who may access which content?)
UI/display/input-method related things do not get into model or db. Don't let your model/db decide if and how to render html, xml or json.
Data consistency and integrity not in controller/view. Ideally, your data model only accepts valid data, uses transaction safety and reports back failure or success to the controller. Ideally, consistency is handled at db level.
A model shall be reusable with other controller/views in new project (think of switching to another web api). Too heavy constraints may render it unusable in new situations.
there might be more...
And generally: If in doubt, put in into the controller. ;)

In MVC (Asp.Net MVC specifically), should a model be represented by a single view?

To me, this seems to make little sense, but after reading the information in the following:
http://weblogs.asp.net/scottgu/archive/2010/02/05/asp-net-mvc-2-release-candidate-2-now-available.aspx
http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html
http://blog.stevensanderson.com/2010/02/19/partial-validation-in-aspnet-mvc-2/#comment-35397( specifically some of the comments)
It appears that the idea behind Asp.Net MVC is that you have a one-to-one relationship between models and views. This seems to go against the DRY principle and several other standard programming practices.
For example, lets say you have a user account model and there are two views available to edit it - one for the user himself to edit it and one for the site admin to edit it. The admin has access to an additional field for something internal, required but the user cannot view/edit it. Per the model binding functionality and the beliefs described in the posts referenced above, I would need to create two separate user models, one for each page, and the only difference would be that additional field. This is just a simple example as well, I've got a few that I've seen where it would potentially mean 5 or 6 different models for the exact same object, just a few fields different between each view. That really doesn't make any sense to me.
I did not read the posts you mentioned, but there is nothing wrong with having one Model for a couple of views.
I would just have this one UserModel and use it in all Views, even if there are some fields that are not used.
If things get a bit more complicated but Users still have a lot in common you can either use aggregation for the usermodel (User.Address) or use Interfaces (User has fields street , and city and implements IAddress).
Both methods have their pros and cons - with aggregation used in the majority of situations.
EDIT
After reading the posts I saw that they deal with validation. This is a different story.
If you want to use DataAnotations you have to have different classes if validation varies. I dont use DataAnnotations - so I guess your class design might be different.
If you're using annotations, I'd strongly consider one "model" and multiple "viewmodels." We went with a viewmodel approach on our current app and have been reaping the benefits, because our basic model needs to be shown in a couple different views.
There is no official requirement to have only one view per model in ASP.NET MVC. In many cases that would lead to duplication of code.
I personally like to split model-view dependencies, that is, one view per model. It comes down to the fact that you never know how, say, a couple of very similar model-view pairs are going to evolve in the future. If they're separate, you just introduce changes in one and you don't have to "fix" the other views that were dependent on this model, or worse, to take extra work to create own models for them all at once.
TL;DR: Make many view models. They are cheap and flexible.
"This seems to go against the DRY principle and several other standard programming practices."
[Citation Needed]?
MVC doesn't change the fact that in any language or pattern you need to make a view model definition for each separate screen. Whether via attributes, via XML, via toggling web form controls, whatever.
The DRY principal usually pertains to repeating business logic. Repeating a FirstName property across a CRUD screen section really isn't a big deal. Even 5-6 times, whats that? 40 seconds?
If you mistake your view models for object oriented classes and not homoiconisticish screen representations you run the risk of filling them up will all sorts of inheritance and or business logic.
Your not really programming when you make dumb view definitions. This work could easily be done in an Access GUI or defined in XML. The fact that your screen-view-models are in C# just makes it easier to fill them up with data and ship them around and work with tools like WCF and Automapper.

MVC - Separation of Concerns

I'm a newbie. I want to ask about the MVC model for separation of concerns. I have read up a few MVC tutorials but I don't yet have a full understanding of the roles of each of the Model, View and Controller.
For instance say I am writing an application for a user to monitor a portfolio. I would like the landing page to display lists of investments based of different criteria, for instance one may list investments based on amount invested, another may order it based on investment performance.
My question is, in accordance with the design pattern where should I write logic for generating the lists; in the Model, View or Controller?
Also any asp.net MVC examples demonstrating seperation of concerns is much appreciated.
Thanks in advance guys.
At the risk of repeating myself, I'll point you to the answer I gave in this thread. The entire thread is probably worth your time, as are dozens of others on Stack Overflow.
To break it down simply:
Controllers - control application flow and makes decisions about data.
Models - perform business logic.
Views - produce output.
For your particular situation, you will want to produce your lists in the View layer. Use templates to create your list structure, and fill them with data fetched from the Model layer.
I'm not an asp.net programmer, so I can't give you a reliable example, but have a hunt around for other SO threads.
Nice question, this is subjective and there are many solutions, it comes down to the context I think and the preferences of the individual.
With ASP.Net implementation of MVC alot of people talk about the Model being more of a ViewModel than a Model as in some other frameworks (somewhat of a DTO). This in mind and looking at the Controller as just a coordinator of the flow of the application, it would not be wrong to generate the lists in an additional layer accessed via a service of some type. You would make a request to that service for a set of ViewModels which meet a specified set of criteria and let that extra layer worry about the way in which those lists are generated from that set of criteria. This way all the controller needs to know about is passing some criteria to the service and providing the view with a set of models (viewmodels) to display, the view is free of making any decisions about what to do with the data it has been provided, and the models are nice and lightweight.
Hope this explanation makes sense, and I'm open to criticism if people don't agree...
MVC pattern "requires" you to insert all your "business logic" in the Models. Models are used to access database and fetch data and mold it in a way that you just have to use a Controller to assign it into a View.
An graphical example : http://www.bhartisoftland.com/technologies-skill-sets/gifs/mvc-php.png
Needless to say perhaps, that you can bypass the use of models and write all your logic in the Controllers, but that would result in a very extensive and probably redundant amount of code. Controllers are used so you can call Models and Views, and exchange information from one to another with just a few lines of code.

ASP.Net MVC View Structure

I just finished Scott Gu's Nerd Diner tutorial. I found it very helpful because it not only taught the basics of ASP.Net MVC, but also how to use with Repositories, Validation, Unit testing, Ajax, etc.. Very thourough, but still manageable.
However, I am curious about his site structure:
Specifically, he used this view strucuture for every object:
/ModelObject/Edit/
/ModelObject/Create/
Then extracted the common elements between the two views and put them into a partial.
I understand the logic, but it seems like it would lead to "view explosion" if you have even a moderate number of tables in your database.
Scott's really good, so I am assuming his structure is right. But I would like to know why.
Thanks!
[Edit for clarification]
I realize that many times it is necessary for there to be multiple actions (and views) to handle differences in creates and edits. It is the case of the very simple edit and create, where the only difference between the two actions is in one case the model has an ID and needs to be updated, and in the other case the model does not, so it needs to be inserted.
In this case, is the violation of the "Dumb View" rule by using the same view to handle both cases going to cause major problems?
The view structure is based on the controllers, not the model directly. In the Mvc methodology, you should have a view for each action (each public method, essentially) in a controller. The controller actions don't have to match up directly to each table in database but there is likely some sort of direct relationship between the number of tables in the database and the number of controllers and views. Controllers are higher level
It is standard to have CRUD type actions on the controller, when they are applicable:
Index: list the items
Details: view a specific item
Edit: edit an item
Create: new item
Delete: delete an item
Each of these actions will require a view (and sometimes more than one).
So, yes, you can collect a large number of views if it is a large application. The way to minimize the code is:
Extract shared functionality to partial views, as to keep the action views as small and simple as possible
Keep the views and controllers simple so that they are easy to maintain
Use AJAX to implement more functionality in one view
It's important to point out that any large application is going to have lots of forms. Whether it's Mvc or Web Forms, if there is a lot of data to work with, there are going to be a lot of forms necessary to do it.
It is true that this can indeed lend itself to a lot of views. However, I've found that in my real life applications, I'll have a number of tables that I don't have a 1:1 correlation to CRUD operations. While I certainly have data that goes into those tables, I've found that most times a view presents data from at least two if not three or more tables. Just like every other application, you've got to know what you're after so that you can plan things out. Any large size application is going to require quite a bit of planning up front (which would include analyzing the number of views/controllers for MVC).
It's only the small apps that you can sling together based on you hunches and past experience.
if you have a background as asp.net webforms developer, your answer is natural.
There are several questions, it depends on the point of view. At first, with asp.net-mvc we do not have fully-equiped server controls making many things for us, without a real awareness what they do. Now you have to type more code and have eyes like a surgeon on html.This way I can find a reasonable question for "view explosion"
Other projects follow more or less that structure, see the project by Rob Conery:
Mvc Storefront
PS: "Skinny controllers, Fat Model and… Dumb view"
[Update response to clarification]
Mhh.. I think there's no violation of "dumb view". The important thing is that the all the views has nothing to do with the code in the business logic layer or in your model. You can a have a button "Save", it is the controller has to know which action must be executed, insert or update.
On more reflection, this is what I am thinking:
Combining the edit/create views would be easy on simple models because
- Same properties displayed
- Same validations
BUT doing this would force you to either
- handle both the update and insert in the same action
- use a control statement in the view to determine which view action is used to update
Both options seem ugly and unnecessary when it is so easy to use separate actions and separate views with common code extracted into a partial.

Resources