Rails does a lot of work for you. This is often beneficial, but when it makes assumptions that aren’t right for your app, it can be frustrating. In this post, I’ll discuss a few issues that can arise when you get started creating models, along with some easy solutions to them. Oh, and before I get too far, I should note that the code here assumes you are using Rails 5.
Rails handles pluralization for you in a lot of cases. For example, when you generate a model, it creates a number of additional files, some of which have the plural version of the model’s name. For example, if you generate a Computer model it will create a few files, some of which have the word “computers” in the name.
$ rails g model Computer Running via Spring preloader in process 71634 invoke active_record create db/migrate/20161005132000_create_computers.rb create app/models/computer.rb invoke test_unit create test/models/computer_test.rb create test/fixtures/computers.yml
Additionally, if you were to create another model that had a has_many relationship with Computer, you would reference the Computer model by its plural version.
This usually goes smoothly, but there are times when things just don’t work right. For example, let’s create a Superhero class:
rails g model Superhero
This produces the following output:
$ rails g model Superhero Running via Spring preloader in process 6027 invoke active_record create db/migrate/20160929235358_create_superheros.rb create app/models/superhero.rb invoke test_unit create test/models/superhero_test.rb create test/fixtures/superheros.yml
We run into a surprising problem: the pluralization is incorrect. Rails provides an easy way to fix this issue, though: inflections. Among other things, inflections allow us to transform strings between their plural and singular forms. We can define the correct pluralization of superhero in config/initializers/inflections.rb by adding the following code:
ActiveSupport::Inflector.inflections() do |inflect| inflect.irregular 'hero', 'heroes' end
Once this is in place, pluralization works correctly throughout your app.
Associations and Foreign Keys
You often want relationships between your models. For instance, if a superhero you belongs to a team, you could build the migration for your model as follows.
class CreateSuperheroes < ActiveRecord::Migration[5.0] def change create_table :superhero do |t| t.belongs_to :super_team t.timestamps end end end
This is pretty similar to what you will see in just about any intro tutorial on rails. It creates an association between SuperTeams and Superheroes. When I first saw this, I assumed it was creating a foreign key constraints in the database. However, this is not the case. If you want foreign key constraints, you'll have to explicitly tell rails. To do so, the following line of code can be added after create_table is called:
add_foreign_key :teams_memberships, :superheroes
Now the migration actually adds foreign key constraints, so the relationship is preserved, even when accessing the database outside of rails.
Associations With Custom Names
When you get started with associations in rails, a lot of the documentation you see will assume that associations have the same name as the class they link to. For instance, let's say we're creating an app to represent businesses, and that we've already created an Employee model. When we create our Business model, we'll likely want each business to have a manager.
We will want a belongs_to association to represent this relationship. In the Business model, we could might start off with the following:
This does create the association, but it will name it "employee," which is not desirable. If we want to name the association "manager," we could change the association to look like this:
belongs_to, :manager, class_name: 'Employee'
Now we have an association to the correct model with the desired name.
Hopefully this has been helpful and will save you a bit of time when developing on Rails in the future.