I've been learning Rails and seems like concerns are a way to dry up fat models and make methods sharable by models. I'm confused though as to why views/partials have access to these methods. Shouldn't the MVC model make all the model related things go through the controller and then be given to the view. It feels like giving views access directly to model concerns skips the controller. Also why do I not have access to these methods in Rails console?
A model concern can be seen as a way to split up a model with many methods. It is possible to share common methods between models, but also possible to just thin out the model code.
Once you include the concern, all concern methods are mixed into the model, and therefore are available anywhere the 'base' model methods are.
Related
What is the Rails Presenters folder for?
What goes in this folder?
Why is this folder needed?
presenters is a design pattern commonly reffered to as Model View Presenter(MVP)
This is a derivation of the Model View Controller pattern and is used for creating user interfaces.
It's useful for the Separation of Concerns for making code more DRY.
Here's how Wikipedia describes it
model - interface defining the data to be displayed or otherwise acted upon in the user interface.
presenter - acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
view - a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
Presenters in Ruby on Rails
Presenters are simple classes that sit between the model and the view and provide a nice, DRY object oriented way of working with complex display logic.
In Rails, the convention is for them to be located in the app/presenters folder
Here is a userful article that explains the pattern and its use in Ruby on Rails.
https://kpumuk.info/ruby-on-rails/simplifying-your-ruby-on-rails-code/
The Presenters folder is where your Presenter code would go. I know, obvious, I'll explain.
The way I think of Presenters and Decorators is as an abstraction of a Model in order to massage the data attributes before they are given to view.
If you are familiar with helpers, well, Presenters are kind of like helpers in the sense that they are getting some data ready for the view, except helpers usually serve as utility methods for said views, while presenters are more about presenting the actual attributes.
This link explains the difference very well: https://awead.github.io/2016/03/08/presenters/
hope that helps.
Presenters de-clutter your views
When people mention presenters in a rails context (as opposed to discussions of Model-View-Presenter, MVC, MVVM discussions etc) they are referring to a situation where things look really complex in your views: there are plenty of if statements everywhere, and it's difficult to read through it all.
Or to adopt an everyday analogy: imagine you have a really messy house, with stuff piled up everywhere - so that it's difficult to walk through. You can think of a presenter as a large garage where you can neatly organise everything. This makes it much easier to walk through your house, and you still have all the utensils that you need.
Getting back to the rails context: Presenters allow you to remove all that complex logic somewhere else: into the Presenter's folder, so that when you read your views, it will be a lot easier to understand from a higher level. The clutter isn't there, the complexity isn't there: that has been transferred somewhere else. If you want more detail, you will have to go to the relevant folder. The logic need not be contained in a folder called "Presenters" but it can be put there by convention.
Would concerns help me share logic for partials? I see Rails 4 has the "concerns" folder for controllers, but it's empty on app generation.
DHH wrote a blog on concerns (but I think they are for the model): http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns
I would appreciate a concise example.
Simply put:
Helpers contain methods to be used in views.
Concerns are modules to be included in controllers/models(depending which concern is it) etc.
It's just a folder with code that you could otherwise put in another place if you wanted. We use fancy terms like concerns to get paid more.
Concerns are modules that get mixed into controller or model classes for instance. DHH's post focused on models, but the same applies to controllers. It helps slim down the model or controller classes, and makes it easier to reuse common code across multiple classes.
Helpers are for short presentation-oriented methods that you want to call from your views, or very occasionally from your controllers, maybe.
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.
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.
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.