Join Kevin Skoglund for an in-depth discussion in this video Query data selection, part of Ruby on Rails 6 Essential Training: Models and Associations.
- [Instructor] Most of the time when we make active record queries, Ruby on Rails returns active record objects back to us, that means it goes to the database and it gets the rows of data that match our query. And then it instantiates objects where the attributes are the values of each row, but we don't have to do it that way. There are some ways that we can select the data that gets returned. And I want us to look at count, select, pluck and ids. They're useful tools to have in your toolbox. The first one is the simplest and probably the most useful, and that is count. Count simply tells the database to return the count of records that would match our query. Not to actually return the records themselves. You can contrast that with the second example, which looks very similar, but is much less efficient. The second example goes to the database, gets all the rows of data, brings them back into active record, active record converts them all into Ruby objects that take up memory. And then after they're in an array, it goes through and counts the items in the array. The first one just tells the database to do the work for us and tells the database to give us back a number of records, not the records themselves. We also have a select method, that allows us to choose the columns of data that get returned. It's very similar to SQL Select where we're able to specify the columns. Here though, active records still creates Ruby objects for us, but they aren't fully populated with all the attributes. They're only populated with the attributes we select. It's kind of a partial object. You can see that when I call product.id and product.name, it returns a result to me. When I try produc.description, I get an error. Personally, I find this of limited utility. There are some small cases where it's useful to have these partial objects around, but most of the time I'd rather have the full object and not run into errors. What I find more useful is pluck, pluck is very similar to select. You also provided a list of the columns that you want to select from the query. The difference is that pluck doesn't try to create active record objects out of them, instead it just returns an array of data. So here instead of getting an active record object back, that has an id of one and a name that's Coffee Mug I just get back in array where the first value is one and the second one is Coffee Mug. It's very similar to if I called product where, and then mapped the results and created an array using those results. But again, it's more efficient because in the second example, it's going to the database, getting back all of those rows, converting them into active record objects, and then creating the array from it. Pluck just goes to the database and says give me the values and skips the in between steps. And last we have ids, which does what you would expect. It takes the query and it returns an array of the ids. It's very similar to using pluck with the ids, but because the ids are something we want often, it's nice to have an easy way to get them. Let's try these out. Let's go into our Rails console for our project. And we only have a couple of subjects but let's find out first of all how many subjects we have, let's do subject.count. And it tells me I have two subjects in the database. Let's just create a new subject. Let's do subject equals subject.new, and then we'll make this one subject.name equals another subject and subject.position, will make three since that's probably the right answer since there are two of them and subject.visible, be equal to true. And then we'll do subject.save. Okay. So now we have at least a third subject in our database. Now let's try subject.count again, we'll see there are three. Let's do subjects.where visible true and do count. And you can see that returns two, but notice the SQL that it's creating right? It's just doing a count in the SQL. So it's not returning back records to us, It's just returning back a number. Let's try using select, let's do subject where visible true and then let's just select the name. Now you can see, I got back an object right here and that object only has a name It doesn't even have an ID, the ID is nil. If we were to call subjects equal subjet.select id and name. Now you see we get back id and name, but nothing else. And if I call subject.first.name, I missed typed out. Let's do subjects.first.name. You see I get back initial subject. But if I try and ask for the position, it comes back and says attribute missing. Now let's try instead let's hit the Up Arrow a couple of times. And instead of select use pluck, you see pluck just returns back the array of the values themselves doesn't try to create active record objects And then for our last one, let's just do subject.ids and you'll see we get back on array of ids for the subjects that match our query. These four methods can help you to write more efficient code and make your application faster.