<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Julien Fitzpatrick</title>
    <description>The latest articles on DEV Community by Julien Fitzpatrick (@julienfitz).</description>
    <link>https://dev.to/julienfitz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F456929%2Fcc65d351-eb79-4fe7-814c-ca36e7ee6428.png</url>
      <title>DEV Community: Julien Fitzpatrick</title>
      <link>https://dev.to/julienfitz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/julienfitz"/>
    <language>en</language>
    <item>
      <title>Don't have a CLUE how to get the most out of your Active Record queries?</title>
      <dc:creator>Julien Fitzpatrick</dc:creator>
      <pubDate>Thu, 10 Sep 2020 05:19:36 +0000</pubDate>
      <link>https://dev.to/julienfitz/don-t-have-a-clue-how-to-get-the-most-out-of-your-active-record-queries-2502</link>
      <guid>https://dev.to/julienfitz/don-t-have-a-clue-how-to-get-the-most-out-of-your-active-record-queries-2502</guid>
      <description>&lt;p&gt;Improve your Active Record querying skills by playing a game of Clue: it's you against the database! Just want to play and don't want to read this whole thing? Go straight to the &lt;a href="https://github.com/julienfitz/rails_clue" rel="noopener noreferrer"&gt;repo&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part One: What is Active Record?
&lt;/h2&gt;

&lt;p&gt;If you've spent any amount of time working in Rails, even as a beginner, you've likely encountered some SQL. It's that not-so-pretty, sometimes quite verbose language you often need to use in order to query your database. Active Record's job is to heroically swoop in and provide a much more human-readable and human-understandable way of interacting with your Rails database. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Active Record&lt;/strong&gt; refers to the layer of Rails that’s responsible for representing business data and logic, which is basically all the stuff in the database that’s like, for a blog it would be the users, the posts, the comments, etc. The data associated with running the business. It’s called “Active Record” because it’s an implementation of a pattern called “Active Record” that was described by Martin Fowler in his book, Patterns of Enterprise Application Architecture. (It’s also available here: &lt;a href="https://www.martinfowler.com/eaaCatalog/activeRecord.html" rel="noopener noreferrer"&gt;https://www.martinfowler.com/eaaCatalog/activeRecord.html&lt;/a&gt;)  In Active Record, objects carry both persistent data and behavior which operates on that data. So a User object in our database has both the data that we see in the database, as well as any behavior we’ve defined in its model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0f9d02c4b54hwp5zedh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0f9d02c4b54hwp5zedh6.png" alt="Screen Shot 2020-09-09 at 10.11.30 PM"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The Active Record pattern, in turn, is actually a description of an &lt;strong&gt;Object Relational Mapping&lt;/strong&gt; system (ORM), which is just a way of connecting the application objects (the users, the posts, the comments, etc) to their associated tables in the database. By using an ORM, we avoid the hassle of having to use SQL to access records in our database. The ORM is like a friendly file clerk, so instead of having to find things the hard way, you can just be like “hey, I want this user named Frank” and they’ll go and get it for you.&lt;/p&gt;

&lt;p&gt;As you can see here, Drake is demonstrating his distaste for this SQL statement as compared to his obvious love of its equivalent Active Record query. Look how much simpler it is!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fscc6eyvfyf6u9xmm7xep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fscc6eyvfyf6u9xmm7xep.png" alt="Drake meme: SQL vs. Active Record"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy Loading
&lt;/h3&gt;

&lt;p&gt;Active Record makes use of &lt;strong&gt;Active Record Relations&lt;/strong&gt;. You may have noticed that any Active Record query that returns a collection (like &lt;code&gt;where&lt;/code&gt;), as opposed to an individual object (&lt;code&gt;find&lt;/code&gt;, &lt;code&gt;find_by&lt;/code&gt;, &lt;code&gt;first&lt;/code&gt;, and &lt;code&gt;last&lt;/code&gt;), is not actually returning the array of database objects that it looks like it’s returning: it’s actually returning an Active Record Relation! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Character.where(name: "Mr. Boddy").class vs. Character.find_by_name("Mr. Boddy").class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For performance reasons, Active Record doesn’t want to tell the database to execute any queries until it absolutely has to, so most of the Active Record queries you run will return a relation rather than the actual database object(s). This allows us to chain a bunch of query methods together without taking a performance hit by executing the actual SQL query behind each one, and when it’s finally time to execute the query, Active Record and SQL will work together to figure out the best way to structure the query.&lt;/p&gt;

&lt;p&gt;Of course, while we’re trying this out and running query methods in our Rails console, we’ll notice that queries ARE being executed, because the Rails console implicitly runs something like the &lt;code&gt;.inspect&lt;/code&gt; method on relations, which requires queries to be run. So it’s a little misleading if we’re only running these methods in our Rails console. &lt;/p&gt;

&lt;h3&gt;
  
  
  Eager Loading
&lt;/h3&gt;

&lt;p&gt;Since Active Record is set up to work this way, we can easily get into a situation where we unwittingly create an N+1 problem and absolutely hammer our database with unnecessary queries. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.all.each { |char| puts char.weapon.name if char.weapon }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not only going to make a query to get all the characters, but because an association exists between characters and weapons, it’s also going to make a query for every single character’s weapon, which is a lot of queries! A common way to avoid this problem is by loading the weapons along with the characters ("side-loading") by using the &lt;code&gt;includes&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.all.includes(:weapon).each { |char| puts char.weapon.name if char.weapon }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that’s Active Record, lazy loading, eager loading and an intro to a couple of Active Record query methods.&lt;/p&gt;

&lt;p&gt;Now, on to the fun part! &lt;/p&gt;

&lt;h2&gt;
  
  
  Part Two: Rails::Clue
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbm692a9qs84fcj334mh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbm692a9qs84fcj334mh5.png" alt="rails_clue_characters"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Before we get started, I invite you to fork or just clone my repo here so you can follow along (and try some queries of your own): &lt;a href="https://github.com/julienfitz/rails_clue" rel="noopener noreferrer"&gt;https://github.com/julienfitz/rails_clue&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you never played Clue as a kid, I’ll give you a quick primer. The premise is that a person has been murdered and it’s up to us, the players, to figure out who the murderer is, where it took place, and which weapon was used. We’ll be doing this by using the Active Record query interface! &lt;/p&gt;

&lt;p&gt;In the board game, you start by putting a character card, a weapon card, and a room card in an envelope, and those represent the murderer, the weapon, and the location. Players deduce what’s in the envelope by taking turns moving around the game board, suggesting a variety of combinations of murderers, weapons, and locations, and taking notes along the way. &lt;/p&gt;

&lt;p&gt;Similarly, our database has one Envelope object that contains the murderer, the weapon, and the location. Much like the board game, we could just cheat and look at the envelope directly, but that spoils all the fun, so let’s not do that!&lt;/p&gt;

&lt;p&gt;Let’s start by exploring what we have in our database right now. Just like the board game, we have Characters, Weapons, and Rooms. Let’s start by talking about &lt;code&gt;pluck()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pluck&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So first, let’s list all the Characters’ names. You might be tempted to run &lt;code&gt;Character.all.map(&amp;amp;:name)&lt;/code&gt; and that would in fact list all the Character names for you! This is true. But first of all, &lt;code&gt;map&lt;/code&gt; is a method on Enumerable. So it’s not part of the Active Record query interface. Instead let’s use &lt;code&gt;pluck&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.pluck(:name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;What’s the difference? Why would we choose pluck over map in this instance?

&lt;ul&gt;
&lt;li&gt;When we use &lt;code&gt;.all.map&lt;/code&gt;, Rails fetches the data from the database &lt;code&gt;SELECT "characters".* FROM "characters"&lt;/code&gt;, and creates a collection of ActiveRecord objects using that data. Ruby then goes over the whole collection, takes the name property from each object, stores it in a new collection (the array), then returns the array.&lt;/li&gt;
&lt;li&gt;When we use &lt;code&gt;pluck&lt;/code&gt;, we move the responsibility of fetching those names from Ruby straight to the database. This executes this query: &lt;code&gt;SELECT "customers"."name" FROM "customers"&lt;/code&gt;. &lt;code&gt;pluck&lt;/code&gt; is much faster because it directly converts a database result into a Ruby &lt;code&gt;Array&lt;/code&gt;, without constructing ActiveRecord objects in between. It’s not as noticeable on a small database like the one I'm working with, but very noticeable on larger ones. When I did this locally on my work machine, which is similarly small, there was a difference between 1.7ms and 0.8ms. So almost a full millisecond difference.&lt;/li&gt;
&lt;li&gt;Something else interesting about &lt;code&gt;pluck&lt;/code&gt; is that because, unlike most of the methods that operate on relations, it triggers an immediate query and returns an actual array (rather than a relation), so you can’t chain additional query methods on top of it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Anyway, so let’s get the names of all the Characters, all the Weapons, and all the Rooms using &lt;code&gt;pluck&lt;/code&gt;. Cool. Another fun fact about &lt;code&gt;pluck&lt;/code&gt; is you can query for more than one attribute at a time! So if I wanted to see all the Characters’ names AND their ids, we can run &lt;code&gt;Character.pluck(:id, :name)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;count&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.count&lt;/code&gt; is also an Active Record query method. Let’s see how many GuestbookEntries we have with &lt;code&gt;GuestbookEntry.count&lt;/code&gt;. Wow, that’s a lot of GuestbookEntries.&lt;/p&gt;

&lt;p&gt;We can also use &lt;code&gt;.count&lt;/code&gt; in combination with an attribute to see how many of that given class of objects have that attribute. This doesn’t really help us right now, since all the database objects have only one or two attributes, and they all have all of them. So if we look at &lt;code&gt;Character.count&lt;/code&gt;  and &lt;code&gt;Character.count(:name)&lt;/code&gt; we’re gonna see the same number. But it’s cool to know you can do that!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;find / find_by&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the most basic query methods that most of us know of the top of our heads is &lt;code&gt;.find()&lt;/code&gt;. Both &lt;code&gt;.find()&lt;/code&gt; and &lt;code&gt;.find_by()&lt;/code&gt; will each return only one result, so &lt;code&gt;find_by&lt;/code&gt; will return the first matching result. Let’s pick a character at random. Since we have 10 Characters, each having an ID between 1 and 10, let’s use &lt;code&gt;Character.find(rand(1..10))&lt;/code&gt; to get a “random” character, and we’ll assign this character to a variable to make our lives easier.&lt;/p&gt;

&lt;p&gt;How many guestbook entries does this character have?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char = Character.find(rand(1..10))
char.guestbook_entries.count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GuestbookEntries have a &lt;code&gt;time_entered&lt;/code&gt; and &lt;code&gt;time_exited&lt;/code&gt;, and the two attributes on our Envelope that are actually okay for us to access are &lt;code&gt;murder_start_time&lt;/code&gt; and &lt;code&gt;murder_end_time&lt;/code&gt;. We can use those attributes to see if our Character was in any particular room during that time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;where&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can use &lt;code&gt;.where&lt;/code&gt; to see if any of our Character’s GuestbookEntries are from the time range of the murder! Let’s make our lives easier by assigning the murder start and end times to variables. Then we’ll run a basic &lt;code&gt;where&lt;/code&gt;  query to see if this character has any GuestbookEntries during the murder times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;murder_start = Envelope.murder_start_time
murder_end = Envelope.murder_end_time

char.guestbook_entries.where(time_entered: murder_start..murder_end, time_exited: murder_start..murder_end)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the &lt;code&gt;where&lt;/code&gt; method is super flexible, and there are many ways we can use it. You can pass it a string, an array, or a hash. You can also use &lt;code&gt;where.not&lt;/code&gt; to find records that &lt;em&gt;aren’t&lt;/em&gt; what you’re searching for. There’s lots of examples in the Active Record documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;joins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You know what might also be helpful? Every Weapon belongs to a character, BUT… not every Character has a weapon. What if we narrow down our characters to just those that have weapons? We can use an &lt;code&gt;INNER JOIN&lt;/code&gt;, or in Active Record, the &lt;code&gt;joins&lt;/code&gt; method! We can do this with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can chain &lt;code&gt;pluck&lt;/code&gt; on there and get a list of just the names of the Characters who have weapons!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon).pluck(:name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How about we add &lt;code&gt;rooms&lt;/code&gt; to that query so we can make sure we’re looking at characters who have both a weapon and at least one room?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).pluck(:name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;distinct&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oof, what a mess! So many results! The thing about &lt;code&gt;joins&lt;/code&gt; is that we’ll see duplicates if more than one room has the same character. So let’s use &lt;code&gt;distinct&lt;/code&gt; to only grab a single record per unique value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).distinct.pluck(:name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;group&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Out of curiosity, it won’t help us solve the mystery but just for fun so we can learn about another query method, let’s use &lt;code&gt;group&lt;/code&gt; to see how many of these Characters who have weapons and rooms have been in each room, by room name. Group is generally more useful in combination with a math operation like “count” so that’s how we’re gonna use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).distinct.group('rooms.name').count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;having&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can chain &lt;code&gt;having&lt;/code&gt; onto &lt;code&gt;group&lt;/code&gt; to specify additional conditions on the query, so let’s see if we can add some conditions around the characters’ GuestbookEntries to help us narrow down who might have done it! Let’s narrow this down to characters who have guestbook entries with &lt;code&gt;time_entered&lt;/code&gt; that’s equal to or after the &lt;code&gt;murder_start_time&lt;/code&gt; and &lt;code&gt;time_exited&lt;/code&gt; that’s equal to or earlier than the &lt;code&gt;murder_end_time&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).distinct.group('rooms.name').having('guestbook_entries.time_entered &amp;gt;= ? AND guestbook_entries.time_exited &amp;lt;= ?', murder_start, murder_end)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OMG! I think we have the murderer! Or at least, the version of this database that I'm currently working with has happened to work out this way (your results will likely vary, since the murderer is generated randomly). Now, this query could have returned more than one character, but it just happens that I currently only have one result, so this has got to be them! Let’s see which room we’re talking about here by tacking on a &lt;code&gt;count&lt;/code&gt; real quick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).distinct.group('rooms.name').having('guestbook_entries.time_entered &amp;gt;= ? AND guestbook_entries.time_exited &amp;lt;= ?', murder_start, murder_end).count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s see if Mrs Peacock is indeed the murderer (I’ve added an &lt;code&gt;is_murderer?&lt;/code&gt; method to Characters). Since this query returns an array, and we already know there’s only one result, we can use &lt;code&gt;take&lt;/code&gt; similarly to how we might otherwise use &lt;code&gt;first&lt;/code&gt; , it’s just that &lt;code&gt;take&lt;/code&gt; grabs a single record without any implicit ordering, so it might be a teeny bit faster than &lt;code&gt;first&lt;/code&gt; sometimes, because it’s just doing a teeny bit less work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.joins(:weapon, :rooms).distinct.group('rooms.name').having('guestbook_entries.time_entered &amp;gt;= ? AND guestbook_entries.time_exited &amp;lt;= ?', murder_start, murder_end).take.is_murderer?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sweet! Let’s see if this room is the murder location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Room.find_by_name("Lounge").is_scene_of_the_crime?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amazing! All that’s left now is to figure out the murder weapon. If we want to do it the easy way, we can just look up which weapon Mrs. Peacock has, since there’s a relationship there. But! If you want to try your hand at some Active Record query method combos of your own, I invite you to do so to figure this one out!&lt;/p&gt;

&lt;p&gt;What’s Mrs. Peacock’s weapon?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.find_by_name("Mrs. Peacock").weapon.name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is it the murder weapon?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Character.find_by_name("Mrs. Peacock").weapon.is_murder_weapon?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sweet! So we think it was Mrs. Peacock in the Lounge with the rope! Let’s see if we’re correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Envelope.take.whodunnit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there we have it! Mystery solved! If you'd like to try your hand at this, feel free to fork my repo (or just clone it) and play around! &lt;a href="https://github.com/julienfitz/rails_clue" rel="noopener noreferrer"&gt;https://github.com/julienfitz/rails_clue&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>database</category>
    </item>
    <item>
      <title>Pop, Lock, (Drag) and Drop</title>
      <dc:creator>Julien Fitzpatrick</dc:creator>
      <pubDate>Sun, 23 Aug 2020 03:44:41 +0000</pubDate>
      <link>https://dev.to/julienfitz/pop-lock-drag-and-drop-4459</link>
      <guid>https://dev.to/julienfitz/pop-lock-drag-and-drop-4459</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmhxgrl5ci21ennjzgr89.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmhxgrl5ci21ennjzgr89.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I decided I wanted to learn how to create components that I could drag and drop, I assumed it was going to be some totally complicated rigamarole that would almost certainly require a third-party library to implement. I was pleasantly surprised to find that the whole “drag and drop” concept has its own HTML API, and it’s really not hard to use at all! So how does it work and how can you use it in your own application?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API" rel="noopener noreferrer"&gt;HTML Drag and Drop API documentation&lt;/a&gt; - if you’re the type that just wants to dig into the docs on their own, you can hit ‘em up here!&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you want to drag? Make it draggable!
&lt;/h2&gt;

&lt;p&gt;In our case, we have a list of drag queens and we want to make a new list by dragging and dropping our favorites. By default, HTML elements are, as you might expect, not draggable. It would be kind of strange if you could just click and drag any old thing on the internet into any other old place on the internet, right? &lt;/p&gt;

&lt;p&gt;What do you want to drag? In our case, we want to be able to drag the list items in this unordered list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const QueensList = () =&amp;gt; {
    const queens = [
      'Divine',
      'Lady Bunny',
      'Sasha Velour',
      'Vaginal Creme Davis',
      'The Fabulous Wonder Twins'
    ]

    return (
      &amp;lt;ul&amp;gt;
        {
          queens.map((queenName) =&amp;gt; (
            &amp;lt;Queen name={queenName} /&amp;gt;
          ))
        }
      &amp;lt;/ul&amp;gt;
    )
  }

  const Queen = ({ name }) =&amp;gt; (
    &amp;lt;li&amp;gt;
      {name}
    &amp;lt;/li&amp;gt;
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to make these items draggable, we have to mark them as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const Queen = ({ name }) =&amp;gt; (
      &amp;lt;li draggable='true'&amp;gt;{name}&amp;lt;/li&amp;gt;
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want the text of the list item to make it to the other element, we also have to add the item to the drag event’s drag data. We can do this with the &lt;code&gt;setData()&lt;/code&gt; method on the drag event’s &lt;code&gt;dataTransfer&lt;/code&gt; property, and we do this in the &lt;code&gt;onDragStart&lt;/code&gt; method (which, as you may have guessed, is what gets triggered when a drag event starts):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const onDragStart = (dragEvent) =&amp;gt; {
    // I added a border at this point so I can 
    // clearly see what's being dragged
    dragEvent.currentTarget.style.border = '1px solid pink'
    dragEvent.dataTransfer.setData('text/plain', dragEvent.target.id)
  }

  const Queen = ({ name }) =&amp;gt; (
    &amp;lt;li
      draggable='true'
      // also added a unique id so the list item can be "found"
      id={`source-${name.split(' ').join('-')}`}
      onDragStart={onDragStart}
    &amp;gt;
      {name}
    &amp;lt;/li&amp;gt;
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Where do you want to drag it?
&lt;/h1&gt;

&lt;p&gt;Next, we make another component to act as the drop target, because we gotta drop these queens somewhere, right? How about a new unordered list of &lt;code&gt;FavoriteQueens&lt;/code&gt; with a very conveniently-named list item called “Drop Target” so that we can visually see where we’re dragging things?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const FavoriteQueens = () =&amp;gt; (
    &amp;lt;ul
      id='target'
      onDragEnter={onDragEnter}
      onDragOver={onDragOver}
      onDrop={onDrop}
    &amp;gt;
      &amp;lt;li&amp;gt;Drop Target&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the element where we want to drop items, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identify it with an &lt;code&gt;id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;define three methods:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onDragEnter&lt;/code&gt; to define what happens when we enter with a draggable item&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onDragOver&lt;/code&gt; to define what happens when, you guessed it, we are dragging an item over&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onDrop&lt;/code&gt; to define what happens when… yes, you guessed it again… we drop it!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For &lt;code&gt;onDragEnter&lt;/code&gt;, all we need to do is call &lt;code&gt;dragEvent.preventDefault()&lt;/code&gt;. This is because all we want to do is prevent the default behavior, which is to not allow a drag event to happen. We definitely want a drag event to happen!!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      const onDragEnter = (dragEvent) =&amp;gt; {
        dragEvent.preventDefault();
      }  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;onDragOver&lt;/code&gt;, we want to do the same thing, and prevent the default behavior. Just for funsies, we’re also going to add a solid green border, so we can get some visual feedback and know when we’re over the draggable area.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const onDragOver = (dragEvent) =&amp;gt; {
        dragEvent.preventDefault();
        dragEvent.target.style.border = '1px solid green'
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, for the &lt;code&gt;onDrop&lt;/code&gt; event, we start by (again) preventing the default behavior.  Then, we use the &lt;code&gt;getData&lt;/code&gt; method on the drag event’s &lt;code&gt;dataTransfer&lt;/code&gt; property to retrieve the element we were just dragging. We use that data to create a new element and append it to the target. At this point, we also remove the border styles on both ends, since we’re done clicking and dragging and don’t need that visual feedback anymore. Finally, we call the &lt;code&gt;clearData&lt;/code&gt; method on the drag event’s &lt;code&gt;dataTransfer&lt;/code&gt; property to clear… the data… yes, you might have guessed as much by the name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      const onDrop = (dragEvent) =&amp;gt; {
        dragEvent.preventDefault();
        const data = dragEvent.dataTransfer.getData('text');
        const newElement = document.getElementById(data)
        dragEvent.target.appendChild(newElement);
        dragEvent.target.style.border = 'none'
        newElement.style.border = 'none'
        dragEvent.dataTransfer.clearData();
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s put it all together! May I present to you, the drag-and-droppable contents of &lt;code&gt;App.js&lt;/code&gt; in a cute lil &lt;code&gt;create-react-app&lt;/code&gt; application! You can view the complete code at &lt;a href="https://github.com/julienfitz/drag-and-drop-queens" rel="noopener noreferrer"&gt;https://github.com/julienfitz/drag-and-drop-queens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2FvfPjzIhsgLNNm%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2FvfPjzIhsgLNNm%2Fgiphy.gif" alt="a gif of Divine"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'

const App = () =&amp;gt; {
  const onDragStart = (dragEvent) =&amp;gt; {
    // I added a border at this point so I can 
    // clearly see what's being dragged
    dragEvent.currentTarget.style.border = '1px solid pink'
    dragEvent.dataTransfer.setData('text/plain', dragEvent.target.id)
  }

  const onDragEnter = (dragEvent) =&amp;gt; {
    dragEvent.preventDefault()
  }  

  const onDragOver = (dragEvent) =&amp;gt; {
    dragEvent.preventDefault()
    dragEvent.target.style.border = '1px solid green'
  }

  const onDrop = (dragEvent) =&amp;gt; {
    dragEvent.preventDefault()
    const data = dragEvent.dataTransfer.getData('text')
    const newElement = document.getElementById(data)
    dragEvent.target.appendChild(newElement)
    dragEvent.target.style.border = 'none'
    newElement.style.border = 'none'
    dragEvent.dataTransfer.clearData()
  }

  const Queen = ({ name }) =&amp;gt; (
    &amp;lt;li
      draggable='true'
      // also added a unique id so the list item can be "found"
      id={`source-${name.split(' ').join('-')}`}
      onDragStart={onDragStart}
    &amp;gt;
      {name}
    &amp;lt;/li&amp;gt;
  )

  const QueensList = () =&amp;gt; {
    const queens = [
      'Divine',
      'Lady Bunny',
      'Sasha Velour',
      'Vaginal Creme Davis',
      'The Fabulous Wonder Twins'
    ]

    return (
      &amp;lt;ul&amp;gt;
        {
          queens.map((queenName) =&amp;gt; (
            &amp;lt;Queen name={queenName} /&amp;gt;
          ))
        }
      &amp;lt;/ul&amp;gt;
    )
  }

  const FavoriteQueens = () =&amp;gt; (
    &amp;lt;ul
      id='target'
      onDragEnter={onDragEnter}
      onDragOver={onDragOver}
      onDrop={onDrop}
    &amp;gt;
      &amp;lt;li&amp;gt;Drop Target&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  )

  return (
    &amp;lt;&amp;gt;
      &amp;lt;QueensList /&amp;gt;
      &amp;lt;FavoriteQueens /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}

export default App    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>html</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
