How to Integrate a Position Attribute and Custom Scope in Rails
Before we can build out the drag and drop interface, we first need to prepare the database so that it contains a concept of 'position'. This means that our model needs to have a way to store what position each portfolio item is in order to render them properly on the page in the order defined. In this guide we'll walk through how to add a position attribute to the database and how to build a custom scope so that portfolio items are sorted by position.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

In the last section, we got a ton done and our portfolio now is looking much better. In fact, we did so much that I forgot at the end to actually close off our set of tasks. So in the last section, we covered custom styles integrated bootstrap organized our SCSS files. Everything like that. So we can close deliver and accept it.

In this section like I mentioned in the intro, we are going to start with Javascript. Now if I pop this open and click start we can take a look at the tasks that we're going to perform. So we're going to integrate our basic Javascript type of systems and a lot of that's already done for us so we're going to walk through exactly what Rails does and in the deep dive we also saw some of the ways that Rails packages up our Javascript's. We are still going to kind of review how that works. At the end, we're going to go through a Coffee Script deep dive to see exactly what Coffee Script is because Javascript is a programming language and Coffee Script is a little bit of a cleaner way to work with it. In fact, Rails by default ships with Coffee Script and that's what we're going to be building this feature out in. And the main thing we're going to be doing in this section is this third task right here which is to integrate a Jquery drag and drop interface for our portfolio items. This is a very cool feature, and I can tell you from experience that being able to build out a comprehensive drag and drop component is going to put you much further ahead than a number of other Rails developers. This is not a traditional feature that a back-end server side kind of developer usually knows how to build out. And it's the exact reason why I wanted to cover it because I get asked to build this feature so often and simultaneously when I look at the Rails courses out there it is very rare that I see this all see a bunch of Jquery and Javascript courses that do it. There's a pretty significant break between implementing this and the front end and having it register and having it communicate with the backend so would be easy to create a drag and drop interface that simply doesn't maintain its state. So in other words, if what we're going to do is build out the ability and ill show you right here we're going to build out the ability to click on an item and then drag it anywhere else in the portfolio and then have it stick there. Now if we just did that on the front end where we could click and drag it someplace and have it stick there for a moment that's relatively easy. But in order to have that component communicate with the Rails via the Rails API so that it actually updates the position permanently. That is a little bit more challenging. That's what we're going to be building out now.

One other item that I want to mention is I found a great resource here from a developer named Joseph Ndungu and it seems to be a very talented developer and I was able to learn quite a bit about when I was originally seen how to build out a drag and drop interface when I've been asked to do this in the past. And I want to mention it one because I think it's a good resource and also because I am a huge believer in when I find a good resource to share with others and to give credit when I learn something from somebody else but I will give a caveat. This is a few years old and this will not work with HTML 5 so I'm going to share it with you so you can research. But if you try to follow along line by line with what his guide says it won't work just because there are a number of kind of outdated items in it. This is something that I did reference when I was putting together the curriculum so I wanted to include that because I don't like when other developers take something that I've taught or something I've built and treat it like it's their own. I'm a big believer in sharing credit when it's due. So I put that in the show notes that I would once again add that it does not work with Rails 5 and for a number of various reasons that I'll mention ok before we get into what we're going to build out and before we get into Javascript we first have to do a few prep work items on the Rails side. So right now you can see that we have our portfolio items but the way that our portfolio items are being sorted isn't exactly what we're going to need. So, for example, let's open up the code. So if I open up sublime and come into me go to the portfolio controller.

large

You can see that right here we're calling portfolio items and portfolio all. And that may be fine if you don't care about the order but with the way that Rails works what this is going to do is it's going to sort items based on when they were last updated and that is definitely not what we want. We want to actually have an ability to set the sort order so we could implement all the cool Javascript and Jquery in the world. But if we do not have a clearly defined scope and a sort order then every time we hit a page refresh then it's going to wipe them all out and go back to the old sort. So that is going to be the first thing we do is add that as a parameter. So stopping the real server you know say oh before I do that I'd better check out. So we work on another branch so git checked out -b and we'll call this Javascript. This will be our javascript branch and now I can say Rail's G migration add the position to portfolios. So and help if I spelled it right. So the way that this is going to work is if you think about it logically in order for our system to know what order to put the items in we need a frame of reference we need some attribute in the database that we can store and we can update and say you see this position right here. This number is the order that I want you to base the sort on. So in other words and to give a little bit of a visual for this if we set the sort or the position number here to 5 for this portfolio title 1 then we would expect this to be at position 1, 2, 3, 4, 5. We'd expect it to be right here. So the way our system is going to work is when we click and drag one of these items and move it to a different position what we want is for our system to then go and dynamically change that position integer value. But before we can do that we need to actually create an element in the database for the position. So I'm going to run that that's going to create our migration.

rails g migration add_position_to_portfolios position:integer

large

Now I can say

rails db:migrate

This is going to do everything that we need here so now that we have what we need we also need to go and create a scope. So I'm going to say rail's s. Opening up sublime text here I'm going to first build out a scope and put it right in the index action and then after that, we're going to refactor it and create a custom scope. So I'm gonna say portfolio dot order. And then what we're going to put in here is position and ASC. So this is going to do is it's going to look for the position attribute in the portfolio database table and it's going to say I want you to order the elements starting at the lowest ingoing to the highest.

medium

So if I come back here and hit refresh. Nothing changes because all of these values should be nil. We didn't update any values so we can test to see how this would work by opening up a terminal session. So opening up a new tab here I can say rails c. And let's go and update a few of these items. So if I go

Portfolio.last

you can see the position is nil. So I can say

Portfolio.last.update!(position: 1)

And now let's do another one

Portfolio.first.update!(position: 2)

And both of those should work. So now if we hit refresh you can see that the items that we selected right here the first one is going to be this one asdf one. So if I scroll all the way down you can see it's going to be looks like one of these ones here. So if I hit refresh now you can see that this is now shown first and then updated portfolio which is the first one I grabbed this one is now second. So eventually we will give positions to all of the ones that we want and then, however, you want to order them then you're going to be able just to click and drag and then they will be able to be updated automatically and that will update this little example that we gave right here in being able to perform an update. This is essentially what's going to be happening with our drag and drop interface. So that is that part of it.

large

So now I'm gonna close that out coming back here. Let's remove this so that we don't have our scopes inside of our controller. I'm going to cut this and simply add a new method and we're going to call it by position.

medium

Now if I open up the portfolio rb file we can create another scope here so I can say def self dot by position and simply paste in order position ascending hit save

large

and make sure that the controller is saved. And now we should be able to refresh and have the exact same behavior. And yes that is working perfectly ok. So this is the first step. This is what we needed to do before we could start building in our drag and drop interface because this is going to give us our foundation where we can now have positions and where also they can be ordered the way that we need them to be. So I'm going to clear git status to see everything we changed. We updated our schema added a new position updated the controller and the model. So I'm going to say git commit updated portfolio to include attr which is short for attribute for position. Git push origin Javascript. And that is what we need. So with that in place in the next guide we're going to be able to start walking through how to implement our Javascript library.

Resources