Building an Additional Parent/Child Relationship in Rails 5
In this guide we'll prepare for implementing complex forms in Rails by building an additional parent/child database relationship, connecting the Portfolio model with a new model called Technology.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

While planning out this course, I wanted to use nested attributes for blog tags. But after thinking about it for a little while, I decided to go in a different direction. We'll still learn about nested attributes, but there is a model that is a better fit for it than tags.

Part of the reason I am redirecting is that there is a standard to implementing tag on posts and similar types of items. It utilizes the acts-as-taggable-on gem.

This gem will do everything you'd want in terms of adding tags to posts. Also, it does it in a more elegant fashion than if we were to build it from scratch. Consequently, if there is a case where tags would work best, I would definitely recommend using this gem and integrating it for tags. We may do that later in the course if time allows.

However, for now, I'm going to edit this task to say "Nested attributes for portfolio technologies". If you're thinking that we don't have a technologies table in our database, you are right. That's exactly what we're going to build out in this guide. Then we will walk through the steps to creating a nested form in the next guide.

Creating our Technology Model

So, switch to your terminal and general a model called Technology. It will only have one attribute, which is name and it will be of data type string. That is all we need for the internal attributes. However, it will be connected to the portfolio so it needs a reference.
rails g model Technology name:string portfolio:references

large

Open the migration file. You can easily do by copying the migration file number in the terminal and doing a fuzzy search in sublime (using command + t, paste the file key in the search bar. The migration file should look like this:

class CreateTechnologies < ActiveRecord::Migration[5.0]
  def change
    create_table :technologies do |t|
      t.string :name
      t.references :portfolio, foreign_key: true

      t.timestamps
    end
  end
end

Take note, we have our name and a foreign key relationship with portfolio.

Next you can migrate the database with command rails db:migrate This will run the migration.

After that runs, we can check the schema file first, then update our models like we did in the previous guide. Looking at the schema.rb file, we now have a technologies table that is connected to the portfolio_id

create_table "technologies", force: :cascade do |t|
    t.string   "name"
    t.integer  "portfolio_id"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
    t.index ["portfolio_id"], name: "index_technologies_on_portfolio_id", using: :btree
  end

One handy thing that references does for us, when you add it at the time you are creating the model, is that it actually does a part of the work for us. For example, if you go to technology.rb, you can see that it adds the belongs_to reference for us.

class Technology < ApplicationRecord
  belongs_to :portfolio
end

However, it doesn't update our Portfolio.rb file, so we have to manually add the code
has_many :technologies at the top of the file:

class Portfolio < ApplicationRecord
  has_many :technologies
  include Placeholder

Don’t forget to save your files.

Now, using technologies gives a little hint on how cool the pluralization features are in Rails. So far, we've always had our model named in such a way that you just add an s at the end. For example, our existing model names, portfolio, skill, blog and topic, all just needed an s to make the name plural. However, Rails is pretty good at recognizing traditional words in their singular and plural forms. So, instead of adding just an s after the word technology, it actually gave us the correct plural form of technologies, which I think is really smart.

Testing the Model

With our models updated we can test this out. Open the rails console and create a technology, don’t forget the bang! Give it a name of “Rails” and reference it to a portfolio item using Portfolio.last.id.
Technology.create!(name: “Rails”, portfolio_id: Portfolio.last.id)

With our technology created we can run the query Technology.last.portfolio and the associated portfolio is displayed. Likewise, if you use Portfolio.last.technologies, it will return the technology for the last portfolio [#<Technology id:1, name: “Rails”, portfolio_ic: 14,…]. Now we can add those items to a portfolio.

Updating the Seeds File

In order to see some data in our application, we need to update our seeds file to include our technology item. Once again we will use .times and do

3.times do |technology|
end

Inside of that we want to create! some technology items. We will use our standard convention where we put the name in a string and use interpolation to number them. We also want to connect it to a portfolio so we will indicate that.

3.times do |technology|
  Technology.create!(
    name: "Technology #{technology}”,
    portfolio_id: Portfolio.last.id
 )
end

Since we are in the data management section of the course, I want to show you another way of writing this code. It will also be a preview to what we'll talk about in the next guide.

First we need to add our puts statement puts "3 technologies created". As I said, all this code would work as it is. However, there is another kind of syntax that we can become more familiar with.

Open your rails console, so can run a query to find the last portfolio item. We will store the value in a variable. p = Portfolio.last. Now we can bring back the associated technology using p.technologies

large

Here is another way to use the variable to create a new item.
p.technologies.create!(name: “Ruby")

This will create another technology for the portfolio. Now if we run p.technologies again, the return will show that there are two technologies associated with p; Ruby and Rails.

This is really effective, as Rails allows you to take advantage of ActiveRecord. ActiveRecord allows you to start with the parent element, which in this case is Portfolio (remember, Portfolio owns multiple technologies), and then create child relationships without referencing the id.

In this way, you can call one portfolio item and create as many technologies for it as you want. When you create technologies like that, it will, by default, be associated with that particular portfolio. Notice, how I passed only the name and not the portfolio_id while creating the above technology. This is because Rails will do that work for us, which I think is pretty outstanding.

New Syntax for Seeds

Let's go to our seeds file, and make an update to take advantage of the syntax we just learned. First, we will remove portfolio_id: Portfolio.last.id, since we won’t need that anymore. Next we need update our create syntax using something very similar to our call in the console. Note that we need to to add .last

- Technology.create!(
+ Portfolio.last.technologies.create!(

So now your technology loop should look like this:

3.times do |technology|
  Portfolio.last.technologies.create!(
    name: "Technology #{technology}"
  )
end

This will work just the same as the previous syntax. Go to your terminal and type rails db:setup so we can create a new database that includes technologies. If we look in the terminal we see those puts statements:
3 Topics created
10 blog posts created
5 skills created
9 portfolio items created
3 technologies created

Those statement indicates our seeds file is working correctly. Open the rails console and type the query

Portfolio.last.technologies.count, and you'll see that our last portfolio item has =>3 technologies associated with it. So everything is working nicely.

Finally, let's add files to our GitHub branch.

Let’s run a git status just to see what we accomplished. We updated our portfolio model, our schema, and our seeds file. We also created a technology model.

Let’s include all of that with git add .

We will commit with a message using git commit -m ‘Integrated technologies model’

And finish off with git push origin data feature

In the next guide, I'll show you we can connect the code we just built with our forms.

Resources