Follow this Order:
- Create an ERD
- Create a Migration
- Create the Model
- Manage Permissions to the Model
- Specify the Routes
- Create the Controller
- Create the Views
If you're just joining a team of developers for the first time, it can be daunting trying to figure out where to start when adding functionality or new models. There are hundreds of files of code and so many moving parts that you may or may not have any idea what they do. While there is a lot of talk about TDD (Test Driven Development) and writing specs before writing any bit of code, I've found it helpful to create a basic prototype or skeleton of what I'd like before getting too deep into tests. And the good thing is, adding models to an already large codebase is easy!
There are many ways to develop, but I've found following a series of logical steps helps me. So here is my general thought process and steps toward adding functionality to an already large codebase. I won't go into major details for syntax(like how exactly to set up a migration), as you can google that information easily and I'm assuming the reader has a base knowledge of Rails. Moreover, every codebase and team is different. Instead, I'm focusing creating an overall guide to influence your decision process when you stand back and go 'what next?' This post is aimed towards beginner developers who understand the basics about Rails but may not have enough experience yet to feel fully comfortable and to get to them to the point where they don't have to worry about setting things up and to get right into the 'real coding'.
It should be noted that much of this work can be done using Rails
generate scaffold command from the command line. However, if you're not 100% sure what exactly Rails will create and do, or if you're not yet comfortable creating basic scaffolding on your own, I suggest following these steps.
Before you write any code at all, you need to plan out what exactly you're going to be creating. You should take some time to figure out what type of model you will need, what attributes it will have, and how it will be related to other models within your codebase.
Built at www.draw.io
Creating a solid ERD is argueably the most important step in the creation process, so take your time! As the old adage goes, "Measure twice, cut once."
The first step for creating a new model is to prepare the database to store it's information. If you're coming into a code base and have already gotten it working locally, then the databases (usually defined in your
config/database.yml file) have likely already been created. So, you'll only need to create a migration.
General syntax for Migration:
$ rails generate migration name_here
This will create a migration file for you, using the name you used in
name_here and adding a timestamp to it. Open that file, and create the table you need with the fields you need. Note that the name of the table will be plural. For example, if you wanted to create an
Article model, the name of the table in the database will be
See: Active Record Migrations — Ruby on Rails Guides
When your migration file is finished, run:
$: rails db:migrate
If for some reason you notice a mistake, or want to undo the changes, you can rollback with:
$: rails db:rollback
After the migration runs successfully, you now have a table in your database to store the data for your new model!
Next, we will need to write the Rails code for the actual model. Depending on your project, you may have various domains for models, but you can often find all the models you'll need in the
app/models directory. Some things to note: the filename should begin with a lowercase letter and be singular. The name of the class within the file should be uppercase and singular as well. So, create a new file in your models directory with the name of your model.
Let's look at an example. Let's say you just created a new table
articles through a migration.
app/models/article.rb file(notice lowercase and singular)
class Article < ApplicationRecord end
That's it! You now have a model. Jump into the rails console (
$ rails c) to check that it's working as expected. Don't worry about validations or relationships just yet. Let's get everything working correctly first, then we can worry about wiring it all up.
Who will be able to use your Model? By that I mean, will every user to your site be able to read information the model contains? Will they be able to create new ones? Or will you reserve the right to create new models only to admins? If you're coming into a large codebase, likely there will already be some sort of User Authentication service (like Devise(GitHub - plataformatec/devise: Flexible authentication solution for Rails with Warden.)) and Resource Permission Management Service(like CanCan(GitHub - plataformatec/devise: Flexible authentication solution for Rails with Warden.))
Whatever library you use, you should look into how to add (or restrict) permissions to your Model. In the case of CanCan, you will have an ability file in your
app/models directory. Within that ability file, you can add permissions based on the type of user.
For example, your ability file may look something like this:
class UserAbility include CanCan::Ability def initialize(user) can :read, Instruction can :manage, Gadget if user.admin? can [:show, :map], Restaurant end end
It's not imperative to understand everything that's going on here, but you should look into how whatever library you use works when you can. In CanCan's case, within an initialize method you specify what actions(in the Controller) a user can perform on a Model.
:read is shorthand for
:show, :index, while
:manage allows for all normal CRUD actions. If you have other actions you will need to perform, you can add them as well by using an array of symbols.
If you're not sure, for the time being you can just add your model and allow the user to
:manage and change it later, but you should think about who exactly will be using the model and what they will be doing with it.
This step is must be completed now because if you do not give permission to access the Model, you won't be able to test your controllers or views later. Each request to use the resource will be stopped by the Application controller and you'll get an error.
After you've given permission to access the model, you'll need to define the route a user will take to reach that resource. It's easy to forget setting up routes, so I find doing this before creating controllers and views to be a logical next step in the process.
config/routes.rb file, you'll need to specify the routes that will access your controller(which we will make next). If your application uses many namespaces, you should take care that you specify routes within the correct namespace or nested within the proper related resource. Also, you'll need to specify any actions that fall outside the realm of the normal CRUD actions. If you nested the routes within another resource, take note of it, as you'll need that information for the next step.
Finally we can create the Controller for our Model. You may already be worried about all the functionality or data parsing or logic you know you'll need to add, but don't worry about all that yet! All we should worry about right now is making sure that when we put in a URL, our application reacts as expected and routes our request to our Controller.
First, we must create the Controller file, and this can be a little tricky. If your Controller is not nested within a namespace or other resource, you can just create a new file in your
app/controllers directory. However if your Controller IS nested within another resource, you'll need to either create directory for your new Controller, or be sure to create your Controller within the proper directory if it already exists.
In the proper directory, create a new file to serve as the controller. This file will need to follow the basic naming structure of the plural of your model + underscore + controller. For example,
In your Controller, define all the actions the Controller will have. You don't need to add any logic to them; just define them. This example is for a non nested resource. Note the Model name is in uppercase, plural, and there is no underscore:
class ArticlesController < ApplicationController def show; end end
If your controller is nested, you'll have something like this:
class AdminDomain::ArticlesController < AdminDomain::ApplicationController def show; end end
A couple things to note: Remember that the
AdminDomain::ArticlesController is NOT inhereiting from something called AdminDomain. The
:: is a scope resolution operator, and is serving to tell the compiler that this ArticlesController is located within the AdminDomain, not that it inherits anything. The inheritance is shown after the
<, which states the
AdminDomain::ArticlesController inherits from
AdminDomain::ApplicationController, but you could just as easily have it inhereit from
ApplicationController (thought this would likely lead to unexpected behavior.) Also, it's technically unnecessary to define blank methods as Rails is kind enough to do default actions without an explicit method declaration. But for clarity sake (and for you to double check what methods you'll have), I suggest declaring them.
The default behavior for an action in a controller is to render the view that shares the same name. So, with our blank actions declared in the controller, we should go about making our Views. Like with the controller, you will need to remember if your resource is nested or not. If not, you can simply create a folder in your
app/views directory that is the plural of your model name. For example, you would create a
app/views/articles directory for all Article views assuming the ArticleController is not nested inside another resource.
Inside your new directory, create a blank file for your view, and give it the file name that reflects the action in the controller. Rails uses ERB out of the box, but check what templating language your team uses and create a file that ends with that extension.
For now, just add a single line in the file to make sure it's working properly. Something like,
Now you should be able to put in the URL for the show action of the Topics Controller (check your routes if you're not sure how to access it), and recieve a large "Hello World!" response.
You're all done! That is to say, you've just started. But you've done all the basic work required to add a Model, Controller, Routes, and Permissions to the codebase. Now you can start worrying about more practical matters, like how you want the page to look, or what data you want to query from the database, or what data you want the Model to validate, the tests you'll need to create, or any of the other concerns that come with creating new functionality.
Good luck and happy coding!