While writing Rails code we prefer convention over configuration and we follow the conventions adopted by Rails. Because of this we are not required to write a lot of configuration code.
The idea is that if you configure your applications in the same way most of the time then this can be treated as the default way of setting up a Rails application.
Rails has adopted a default way of doing things and laid down some conventions that should be followed while working with Rails. Naming conventions being one of the few conventions.
In this chapter we will be summarizing Rails naming conventions which we have used in our Granite application.
General naming conventions in Ruby
Class names and module names use
CamelCase. For example,
Method and variable names use
snake_case. For example,
Naming conventions in a Rails application are more or less based on the general naming conventions in Ruby language.
We will take a look at the naming conventions used in models, views and controllers of a Rails application as Rails is based on an MVC pattern and these three components serve as the core of any Rails application.
Naming conventions in ActiveRecord model
Active Record uses some naming conventions to map models with database tables.
Rails pluralizes the class names to find the respective database tables. For
example, in our Granite application, for
User class, we have the
Rails is capable of pluralizing (and singularizing) both regular and irregular
words. Model class names must use the
CamelCase form when composed of two or
more words, while the database table names must use the
For example, the
UserNotification model class has the first letter of each
word capitalized and its corresponding table name,
plural with underscores separating the two words.
You can also override the naming convention using the
ActiveRecord::Base.table_name= method to specify the table name that should be
used instead of the table name Rails expects due to the naming conventions.
ApplicationRecord inherits from
table_name= method is available to all models which inherit from
For example, for the
UserNotification class, we could have set the table name
notifications, like so:
1class UserNotification < ApplicationRecord 2 self.table_name = "notifications" 3end
Naming model associations
Let's also understand how to name associations inside a model.
While declaring an association using methods like
the association name must match with the singular form of associated model name
because the aforementioned methods create an association between each instance
of the declaring model with a single instance of the other model.
1class Task < ApplicationRecord 2 belongs_to :user 3end
Had we used the pluralized form of
user model in the above example and tried
to create the instance using
Task.create(users: @user), Rails would have
thrown an exception for uninitialized constant
This is because Rails automatically infers the class name from the association
name. If the association name is wrongly pluralized, then the inferred class
will be wrongly pluralized too. In this case the inferred class is
For declaring an association between one instance of the declaring model and multiple instances of the other model, the association name must match with the plural form of the other model's name. For example:
1class User < ApplicationRecord 2 has_many :tasks 3end
Naming conventions for databases
As we discussed in the previous section, table names in a database should be
plural and use the
snake_case form. Same goes for the column names.
Foreign keys should be named following the pattern
These are the fields that Active Record will look for when you create
associations between your models.
For example, inside the
tasks table we had created a foreign key by the name
Task model shares a
belongs_to association with the
Naming conventions for Controllers
Since a Controller is a Ruby class, it follows the general convention of naming
a Ruby class. It uses
CamelCase and has the
Controller keyword as a suffix.
There are two key details to note here:
The name of the controller is usually plural. For example, notice how tasks is plural in
Controllerkeyword suffix is always singular. Meaning we don't use
Controller actions are methods and use
snake_case. Their names usually match
the route names defined in the routes config file.
In case of RESTful routes, controller actions are usually named after the standard CRUD operations performed by RESTful routes namely index, show, new, create, edit, update and delete. For example:
1resources :users, only: %i[create index]
All requests for creating a user on the
users route will instantiate the
UsersController model and call it's
Naming conventions for routes
Route names use the
snake_case form, and usually match the corresponding
controller's name without the controller suffix.
Route names can be singular or plural depending upon the resource type. In Rails we have both singular as well as plural resources. We have already discussed the difference between them in one of the [early chapters](/learn-rubyonrails-book/restful-routes-in-ruby-on-rails#difference-between-singular resource-and resources-in-rails-routes) in the book.
However, both singular as well as plural resources map to a plural controller by default. For example:
1resources :users 2resource :comment
In the above example, requests on
comment route will be routed to
CommentsController respectively. Note that even though
comment is a singular resource, it is mapped to the
comments is plural.
Naming conventions for Views
All of our view files need to reside in the appropriate view folders, which we must first create and name properly.
In our application, we have a view folder for each of the controllers. We use the following naming convention for our view folders.
The name of the folder within
app/views should be the same as the associated
controller name. And also folder names should be
View files should match the corresponding action names and use
followed by the appropriate response type and file extension in this particular
order separated by a dot(.).
This is the format of the view file with the associated controllers view folder:
For example, in our Granite application we have stored all view files related to
And view file corresponding to the
show action of
show is the action name and
json.jbuilder are response type and file extension respectively.
Naming conventions in services, workers and carriers
All services, workers and carriers should reside within
app/carriers directories respectively. Their file names
snake_case and should be suffixed with
_carrier to clearly define their responsibilities.
Since services, workers and carriers are all classes, they should follow the
general naming conventions of naming a class in Ruby i.e. their names should use
CamelCase and match with their
camelized file names.
For example, in the Granite application,
TodoNotificationWorker class is
Naming conventions and folder structure for tests
In Rails, the tests that you write along with fixtures and other test-related
files such as factories and test_helper, all goes inside the
It is suggested that the
tests directory structure should mirror the
directory's structure. This makes it easy to locate corresponding code and its
Another important point to note is that the name of a test file should contain
_test suffixed to the name of the corresponding file which is being tested.
For example, if
TasksController in the Granite application was present inside
app/controllers/api/v1/tasks_controller.rb, then its corresponding test
file should have been present inside
tests/controllers/api/v1/tasks_controller_test.rb, which in turn mirrors the
folder structure of the app directory.
tests folder also contains a subfolder for
factories. Factory names and
model names should have a one to one correspondence. For example, in Granite,
task model and task factory are both named
Let's also talk about naming test cases in Rails. Test cases are Ruby methods in
a unit test class hence they should use
Like all method names in Rails, test cases should have a descriptive and meaningful name for better readability. A good rule of thumb is to mention what is being tested and the constraints under which the test is being performed.
Let's look at this with the help of an example. Consider the
test_not_found_error_rendered_for_invalid_task_slug test case in
TasksControllerTest. It is pretty clear from the name itself that we are
testing if a
not_found error will be thrown if an invalid task slug is given.
In this case, response is the entity that is being tested and invalid task slug
is the constraint.
A test case name should always start with
test_ in order for it to be executed
while running the tests as discussed before in the
Testing User model chapter
There is nothing to commit in this chapter as it's an in-depth chapter that doesn't have anything to do with our granite application.