Model-view-controller: what goes where
May. 18th, 2009 08:44 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
![[community profile]](https://www.dreamwidth.org/img/silk/identity/community.png)
In a Rails application, most of your code is divided into three main sections: the models, the controllers, and the views. Which code goes where is one of those things that can be a little confusing when you're getting started with Rails.
Let's say I'm writing a blog application - I want to create posts that other people can read. If I generate a scaffold for that, I'll wind up with a file named post.rb in the models folder (in the app folder). The first line will say:
Ignore the "< ActiveRecord::Base" part for now - all that means is that your class inherits from a class that Rails gives you which has a bunch of useful methods. What you should focus on is that this is *the* post class - this is where you'd put any code that has to do with what a post is, what a post does, what should happen to a post before it gets saved or deleted, which posts to get from the database, what sort of relationships a post has with other objects (users, comments, etc.). The models are the real heart of your application, and any code that can be moved out of the controller or the view and into the model probably should be.
Note: one thing "< ActiveRecord::Base" does is draw a connection between your Ruby class and a database table so that an instance of the Post class is a record from the posts table. (This is called Object-relational mapping or ORM.) Model classes don't have to inherit from ActiveRecord::Base, though, and they don't have to be connected to database tables - you can put any sort of Ruby class in there if you need to. It doesn't come up as often, but you can do it.
Continuing with the blog theme, at the top of your posts controller, it would say:
This is a different kind of class that inherits a different set of methods. The controller is a sort of gatekeeper - it gets information from the model and sends it to the view, and it gets information back from the view and sends it to the model. Generally speaking, the less code you have in your controller, the better off you are. I've seen tutorials that say something like "models should be smart, controllers should be dumb" but I think it's more like the controller should be concise because it's where things actually happen - it's where you create new records, update them, delete them, display them, and the less clutter there is, the easier it is to keep track of what's actually going on. Also, things like complex database finds (get all public posts by a certain user, tagged with a certain tag, in a certain order, etc.) tend to be easier to maintain and less likely to be duplicated if the bulk of the code is in the model.
What should go in the controller? Most basically:
1. Assignments of instance variables that get passed to the view (@post = Post.new, @post = Post.find(params[:id]), @posts = Post.all)
2. Calls to methods that make changes to the database in response to user input (@post.save, @post.destroy)
3. Code that controls who can see which pages
4. Flash messages and redirects
Views are probably the easiest to grasp when you're starting out because they're the most like regular webpages. They are html once the Ruby code in
When you find yourself using if/else or multiple lines of Ruby in your view, that's where a helper method is generally useful. If you've created any scaffolds in your application, you'll notice that the app folder contains four other folders: controllers, helpers, models and views, and yet the system is called Model-View-Controller, not Model-View-Helper-Controller. Helpers are just an extension of the views - they're a way to simplify code and make it easier to reuse. For example, let's say there's a spot on my page where I want to have a login link if you're not logged in and a log out link if you are - instead of having five lines of Ruby cluttering up my page - and repeated wherever I want that link - I can make a helper method called login_logout_link (or something). I'd define it in a helper file and just put
When you're just starting out, the most important thing to know about helpers is that they exist, and if you see a mystery method in the middle of your view and you don't know what the heck it is, it's probably a helper. :)
Models
Let's say I'm writing a blog application - I want to create posts that other people can read. If I generate a scaffold for that, I'll wind up with a file named post.rb in the models folder (in the app folder). The first line will say:
class Post < ActiveRecord::Base
Ignore the "< ActiveRecord::Base" part for now - all that means is that your class inherits from a class that Rails gives you which has a bunch of useful methods. What you should focus on is that this is *the* post class - this is where you'd put any code that has to do with what a post is, what a post does, what should happen to a post before it gets saved or deleted, which posts to get from the database, what sort of relationships a post has with other objects (users, comments, etc.). The models are the real heart of your application, and any code that can be moved out of the controller or the view and into the model probably should be.
Note: one thing "< ActiveRecord::Base" does is draw a connection between your Ruby class and a database table so that an instance of the Post class is a record from the posts table. (This is called Object-relational mapping or ORM.) Model classes don't have to inherit from ActiveRecord::Base, though, and they don't have to be connected to database tables - you can put any sort of Ruby class in there if you need to. It doesn't come up as often, but you can do it.
Controllers
Continuing with the blog theme, at the top of your posts controller, it would say:
class PostsController < ApplicationController
This is a different kind of class that inherits a different set of methods. The controller is a sort of gatekeeper - it gets information from the model and sends it to the view, and it gets information back from the view and sends it to the model. Generally speaking, the less code you have in your controller, the better off you are. I've seen tutorials that say something like "models should be smart, controllers should be dumb" but I think it's more like the controller should be concise because it's where things actually happen - it's where you create new records, update them, delete them, display them, and the less clutter there is, the easier it is to keep track of what's actually going on. Also, things like complex database finds (get all public posts by a certain user, tagged with a certain tag, in a certain order, etc.) tend to be easier to maintain and less likely to be duplicated if the bulk of the code is in the model.
What should go in the controller? Most basically:
1. Assignments of instance variables that get passed to the view (@post = Post.new, @post = Post.find(params[:id]), @posts = Post.all)
2. Calls to methods that make changes to the database in response to user input (@post.save, @post.destroy)
3. Code that controls who can see which pages
4. Flash messages and redirects
Views
Views are probably the easiest to grasp when you're starting out because they're the most like regular webpages. They are html once the Ruby code in
<%= %>
brackets is evaluated, and the goal is generally to include as little Ruby as possible so that you can see and focus on how the page is structured and displayed. Any information you need from the database should generally be assigned to an instance variable in the controller and not accessed directly from the view. When you find yourself using if/else or multiple lines of Ruby in your view, that's where a helper method is generally useful. If you've created any scaffolds in your application, you'll notice that the app folder contains four other folders: controllers, helpers, models and views, and yet the system is called Model-View-Controller, not Model-View-Helper-Controller. Helpers are just an extension of the views - they're a way to simplify code and make it easier to reuse. For example, let's say there's a spot on my page where I want to have a login link if you're not logged in and a log out link if you are - instead of having five lines of Ruby cluttering up my page - and repeated wherever I want that link - I can make a helper method called login_logout_link (or something). I'd define it in a helper file and just put
<%= login_logout_link %>
in my view. When you're just starting out, the most important thing to know about helpers is that they exist, and if you see a mystery method in the middle of your view and you don't know what the heck it is, it's probably a helper. :)
(no subject)
Date: 2009-05-20 12:22 am (UTC)(no subject)
Date: 2009-05-20 02:12 am (UTC)kTIDPJLmYe
Date: 2013-05-26 09:47 am (UTC)loBNaDyczltqMXAFgW
Date: 2013-05-26 05:29 am (UTC)vKBmbtiTowrWWPMcg
Date: 2013-05-26 02:29 pm (UTC)KJAZZQFrPUpiPzBxzmM
Date: 2013-05-26 07:57 pm (UTC)MEPiLUjlYrmQkm
Date: 2013-06-11 11:30 am (UTC)