- Read Tutorial
- Watch Guide Video
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
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
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.