How to prevent business logic in Rails controllers - ruby-on-rails

If I understand MVC correctly Controllers should only contain logic that glue the model together with the view. It contains the application logic such as authentication, session and other things for the application. The model on the other hand should do the business logic of the application and the views should update in response to changes on the model. However, how do you this in Rails?
My controllers contain logic that finds model objects etc and then update the views in response.
Have I misunderstood application logic and business logic. I would apprciate if somebody could help me understand MVC.

Rails is a good implementation of MVC and allows good abstractions. Finding model objects is not business logic.
To make sure you get this right, keep your controllers short; move any significant logic to models by creating new methods; use the built-in rails helpers and methods; follow RESTful architecture where possible (not perfect, but helps) and get someone else to discuss your code with you.

Part of the problem is that the Rails architecture makes it look like model = ActiveRecord, and that's not necessarily true. A Model class or module can be anything you like.
When the models -are- ActiveRecord (which does make sense in the majority of cases), you can add methods to those classes that can be invoked by the controllers and that contain the business logic.

Related

Implementing application logic on model layer (MVC)

I keep reading that the biggest layer in the MVC pattern should be the model. I've also heard that we should avoid putting logic on the controller layer. However, as my ASP.Net MVC 5 application is getting larger, I see that I'm getting heavy views, heavy controllers, and... extremely tiny models (they're not more than references to my SQL tables).
Yes, I admit, I could never manage to put any logic on my model.
I like the MVC pattern, and my website is working good, but I keep on thinking that I'm surely not doing things right...
Can you show me some useful links about how to write MVC code properly? Rick Anderson's (Microsoft) MVC 5 tutorial is fine, but once again, his models are indeed very tiny...
In my applications I put as much logic as possible in the domain models. On top of that there is an application layer which interacts with the database and domain models to perform application specific operations. The controller actions have as little code as possible and just call methods in the application layer.
In addition I usually have a view model for each view. Any logic that you have making your views "heavy" would go there.
One of the main reasons I try to put as much logic as possible in the domain models is to make unit testing easier. Logic in the application layer usually involves the database, which you will need to mock in order to test. Moving logic to the domain models makes testing easier and makes you code more reusable.
This is a pretty complex issue. I have an in depth blog post on the question if you're interested.
This answer is also pretty close to what I would suggest.
You're missing a service/business layer which should be injected in your controllers though "Dependency Injection". These services do all the heavy lifting.
Having Models without any methods or operations in them is a good thing. You're only storing this info anyway. They basically just get; set; data.
Use extra layer between models and controllers (for example repositories as data access layer).
I strongly recommend using ViewModels-they make code much more organized.
You should Create Some Classes that purely doing business logic and emit ViewModels for MVC view. Controller should respond to actions and the action method delegate the responsibility of getting the model to this business classes.
After some research on this issue, and taking into account some of these answers and comments, I realized that a medium sized MVC project can't rely exclusively on the 3 layered model. As the controller actions become bigger, the developer starts feeling the need of creating a 4th layer: the service layer. Like Gunnar Peipman correctly suggests in the following blog post, "Controller communicates with service layer and gets information about how access code claiming succeeded": http://weblogs.asp.net/gunnarpeipman/archive/2011/06/20/asp-net-mvc-moving-code-from-controller-action-to-service-layer.aspx

Confused on MVC in rails

I am a bit confused on what to write where in Rails.
Ideally, I will be having a view, a controller, a model. Model should be having all the business logic. But in most of the Rails applications I've seen, I've seen most of the business logic written in the Controller files.
Should we call them as controller? And what about View-models. I am talking about the datamodels that are associated for a view. I am having JSF and Swing in my mind when I say this. There every view has a datamodel associated with it, usually a bean. But here, we don't have anything like that or I am ignorant? And what about service layers, How do I implement them in my Rails code.
To summarize my questions
Why are business logic being
written in Controllers in most of
Rails code? Is this a good practice?
How to incorporate the view-model in
rails, ie, data-models for view?
Where to put service layers in a Rails app?
Thanks
To summarize my answers:
The new standard for Ruby on Rails is to place business logic in the model. This is also known as fat model skinny controller.
Rails doesn't enforce this approach of one data model but you can implement it if you choose. The basic scaffolding does something similar.
The service layers will most likely be stored within rack middleware. This allows for general filtering of requests and responses.

Why should I use view models?

I'm new to developing web apps using ASP.NET MVC. In fact, I'm rather new to developing web apps, regardless of technology.
Currently, I'm working on a project just to get to know the ASP.NET MVC framework better. When reading on SO and elsewhere on the internet, the consensus seems to be that the views should never deal directly with the business objects (i.e. objects implementing business logic and containing associated attributes). Instead, view models should be used. However, this introduces a couple of issues:
Where do I put my validation code?
I need to add code to map between business objects and view models.
In fact, it seems rather cumbersome and I haven't really seen anyone explaining properly why it's a bad idea passing business objects to the views. Could someone please try to explain this (or point to a good explanation)?
Just a clarification; I'm not looking for examples on how to handle the two issues with view models above but simply an explanation on why I should use view models at all.
Where do I put my validation code?
On the view models you should validate everything that's specific to the application like for example the date should be in en-US format culture, ....
I need to add code to map between business objects and view models.
That's why there are tools such as AutoMapper.
Different problems arise when you use directly your domain models in the views:
The views have specific requirements for displaying the data (localization/globalization) so you either end up with spaghetti code in your views or you put this code on your models so that they become less reusable in other applications because you have polluted them with specific presentation stuff
You have different validation requirements based on the view. Let's take for example the case of Add and Update views. In the Add view the Id property won't be needed and it won't be required because you will be inserting a new item. In the Update view the Id property would be required because you would be updating an existing item. It would be difficult to handle those specific validation rules without view models.
The models might contain properties such as IsAdmin and then I am leaving to your imagination the implication of a controller action with the following signature:
[HttpPost]
public ActionResult CreateUser(BusinessObjectUser user) { ... }
assuming that you have hidden this property from the underlying form by not including it.
The business models don't change often whereas the UI could change more often. What if your customer asks you to split your screen in two? The way you present the information changes and the way it is formatted also change. If you use your models directly into the views the spaghetiness of your views becomes worse and worse with every change.
About 60% of the question I am answering on StackOverflow in the asp.net-mvc tag wouldn't have been asked if the OP have used a view model.
Three reasons to why you should use View Models:
Reason 1: Remove logic from your Views
Reason two: Security
Reason three: Loose coupling
Below link may useful:
http://www.codeproject.com/Articles/223547/Three-reasons-to-why-you-should-use-view-models
First off, allowing the Views to have direct access to the Business Objects in ASP.NET MVC introduces some extra security concerns. ASP.NET MVC does a lot of Model binding for you when a user posts a value back to your controller. This can open you up to various kinds of attacks. By introducing a View Model in between, you can be sure that only the fields you are interesting are bound (because the ViewModel will only contain the fields you care about).
As for the other questions:
Where do I put my validation code?
I use DataAnnotations on my ViewModels directly. That allows me to use the Model validation architecture built in to ASP.NET MVC. If there's any validation beyond that I handle it in my controller.
I need to add code to map between
business objects and view models.
True. But using something like AutoMapper can greatly reduce the amount of boilerplate code that you have to write by hand.
MVC is easy to understand and has very little overhead. But those that have used the Model-View-Controller pattern for some time know that it isn't perfect. Not even close. The Model-View-ViewModel pattern offers an interesting alternative.
It is important to understand that the Model-View-ViewModel pattern extends the Model-View-Controller pattern. It isn't a dramatic paradigm shift if you are used to MVC. Even though the advantages of MVVM are subtle, they are profound.
What are some of the advantages MVVM has over MVC?
Better Separation of Concerns
Improved Testability
Transparent Communication

How should my MVC Model work with my Business logic classes?

So I have a MVC app and in another project I have a normal collection of classes which handle the Business and Data logic for the application. I also have some logic in the Model of the MVC project itself. This logic handles ViewModels and the like, things which could not have been done in the n-tier project as they relate to the MVC project itself and need to be in the same project.
My questions are:
Should my model classes have knowledge of the n-tier business logic? Or should only the controller have this knowledge and send data back and forth between the n-tier application and the MVC model as needed?
If it's ok for my model to reference the n-tier application, then should my controller access n-tier via the model class?
Hope this makes sense, found it difficult to word correctly to get my point across.
Generally speaking here - Your model classes should not have business logic knowledge. They should have only the information required to display the view to the user (use DTOs as suggested by mxmissile).
Your business logic would either be in your controller, or (better) in a separate service layer called by your controller. Having methods on a model that, for instance, bypass the controller and make calls directly to the database is almost always a bad practice.
The idea here is to make the views as dumb as possible. You send them a model, they pull out the data they need, format it appropriately, and display it. This makes it much easier to create new views of the same data later if you decide you want to change the presentation.
Think of your models as only containers for data between your controllers and your views. Essentially DTOs.
Your ViewData/ViewModel classes in your MVC application may contain instances of your Model classes (mine do). My controllers call my business services and are responsible for any translation between ViewData and Models.
If it's ok for my model to reference
the n-tier application, then should my
controller access n-tier via the model
class?
I wouldn't go through the model to get to the application tiers, I would have the controller be that interfacing component. The controller calls to your application tiers which return instances of your Model from your data access components. You can then translate those instances into more consumable objects by using a ViewData/ViewModel object. You can do this in a controller, or use a separate assembler class.

MVC Models & Controllers where what to write

We have started using MVC framework and now we are bit confused where to write business-logic, in controllers or models?
For the project we are going to use WCF layer as DAL.
People have different views on Model & Controller, and think differently of writing business logic either in 'M' or 'C'.
What is the best practice?
I believe we will be accessing WCF (DAL) service in Model and applying all the business logic or filtering and then Controller accessing the data from Model.
These are my rules:
Controller
Mainly Pageflow . Determines what View is displayed next.
Has access to Services ( ie productService.GetProduct(Model.ProductID) )
Model
I have 2 of them.
POCO-Classes - used by all layers (BLL,DAL)
ViewModel - used by View and Controller for stronly typed views.
View
Hopefully mainly easy HTML
I try to have the layout in a way, that it is possible to have different kind of people work at the project: The frontend guy and the backend guy.
The backend guy will do the Service and Repository.
The Frontend guy will do Controller and Views. He also does ajax.
Try to keep -Business- logic and -Application flow- logic separate. Most people tend to mix those together as -business logic-
Most people keep their business logic in the model and this is considered best practice. Steve Sanderson who has written xVal endorses this method.
As I’ve discussed before, validation rules should go in your domain model, because the role of your model is to represent the workings of your business. It ensures that the rules will be enforced consistently, regardless of whether the UI coder remembers them or not.
Check out his post about xVal that talks about the problem you are discussing.
Do not think that model is supposed to be build from data access logic (wcf service in your case) only. I would recommend you to check out Domain Driven Design, it goes well with MVC. Controllers shouldn't contain any business logic. Controller action method should be ~20 or less lines. But that's just my opinion (made up from countless sources).

Resources