 Hello, thanks for coming. This is awesome. I see a very full room. If you guys have you have an empty seat next to you Can you raise your hand? Okay, the guy is around if you want to sit down. There's like 20 and two seats Well, thanks for coming to this talk thanks for coming to railsconf It's been amazing so far a lot of great talks and I had a lot of fun I hope you had a lot of fun as well and We are also here to celebrate that rails 5.2 was released Just a week ago If you have any Contribution to the race code base. Can you raise your hand? Can everybody else give a clap to all this? I'm not gonna go through Everything new in rails 5.2. I'm just gonna go through one thing, but it's a really exciting and you know pretty interesting thing and it's called active storage and You know because this is railsconf. I'm not just gonna tell you what it is I'm just gonna go deep inside the code without scaring you too much And so you can also learn how things work and it's a perfect segue to the previous talk So then I can invite you all to Become contributors to the race code base because you know once you go past the stage of this is just magic And you look at the code you might realize that it's ruby and it's classes and objects and you can also contribute to that As a matter of fact active storage is the newest framework. So possibly you might still miss some documentation or Maybe you can find some issues. So it's the perfect place for everybody to start in my opinion looking at the race code base My name is Claudio and English is not my first language. So You can just go and download the slides if you want. They're already available there. You might help you follow speaker.com slash Claudio B so Before I get started just want to comment that this talk is about active storage Turns out I work for a storage company, but it's not it's not cloud storage It's actually we come to your place and we you know take the stuff that you don't need We wrap it up take pictures barcode take everything to a warehouse and then you can ask for your items back with a race app Of course, and it's called clutter. You can check it out and we're busy in a day and we're hiring and that's my pitch but We're gonna talk about active storage instead Clearly I can't talk about everything, but there is a great place to start even after this talk And that is the official race guides. So at guides the ruby on race org There's a section about active storage and it goes through All of it. So it's actually Really well written. So I invite you to just go there and by the way all the URLs that you see are on my speaker deck so you don't have to write them down and This is what we're gonna talk about today First of all, what is active storage? Maybe you've heard about it. Maybe you haven't you're just curious I'm gonna give you an introduction on what it is and how to use it and You're gonna see that it's really really easy to use So then you might wonder what how does it work? What is it made of and that's gonna be the second part of the talk I'm just gonna go through the main classes of this library and Finally, how does it all work together? And I think you know one of the reasons why I'm giving this talk is because when I looked at the code of active storage It's really it's really elegant. It's really a good code base and sometimes people wonder What can I look at? What is a like a library that is a good starting point? So this is a you know my advice and you can look at that and so Enough with introduction. I think I'm gonna get started Okay, so What is active storage and how to use it active storage is a library to upload files If you have a web application and you want users to be able to upload files to the browsers This can be a good option for you It's not the only one in the past. There have been other third-party libraries like paperclip or carrier wave, but active storage ships Inside rest by default. So you already have it there. So you might want to give it a try and And so how do you use it? How do you let users upload files? I'm gonna show this in a brand new app. So there are no dependencies I'm just gonna create a scaffold brand new scaffold ways 5.2 app and then have an upload so This is how you just create a brand new app in rails you do your rails new I call this up catalog and I generate a model called cat of course because it's risk also. I haven't seen too many cats in this Conference yet. So this is my my part for that So every cat has a name and then we create the database we migrate and we run the server and If you've ever used the scaffold in rails, you know that it generates forms like this one So you have a form where you can add a new cat to your application So this is the baseline. We already have a form now. We want to add a field for people to upload an image So there are three steps. The first step is actually to just add a field to the HTML And this is pretty much HTML. We are adding a file field. I call this picture You can give it whatever name you want photo cute little picture cat cute picture and then a label that's that's Really it there's a new field called picture now in rails whenever we have a field in a form that we want to Submit to a controller. We need to tell the controller about this field We need to white list this new parameter because of the strong parameters in in rails So what that means in your controller you? Already have these programs require cat permit name These are all the programs that are accepted from the form So all we have to do is to add picture as another parameter that the controller is going to accept and then the last step in The model in the cat model. We have to add a single line of code We just have to say cat has one attached picture And that's it. That's literally all you have to do if you do all of this then you Have this form people can upload the picture the picture gets uploaded it gets attached to the cat and As a matter of fact if you have a show page You can just do image tag cats dot picture and that's going to display the picture right there Do you think it's awesome? Okay, a random applause for your active storage. I think it's pretty awesome Also for the cat So, you know, this is the basic usage and but it doesn't stop here. There's a lot more than you can do with active storage Here are some of the other things I'm not going to really talk about here But you can still do imagine you have this cat dot picture You can actually display a variant like a black and white 90 degrees flip image you and all you need a Library like mini magic in your gem file and it does this it creates another file like that black and white It's not only for pictures I mean for images you can also have like has when I touch document like a PDF file and There's a matter of fact if you have a PDF You can even display a preview like an image that renders the first page of the PDF and you can resize that 100 by 100 for instance And of course of course if you have a cat you're gonna have many videos of your cat And so it's not just has one attached you also have has many attached that works in a similar way and For each video you can extract metadata the size the angle the duration of a video So there is more about how to use active storage There's variants pre-use and analyzers and so read the guides and Also, if you just Google active storage how to use active storage Probably the first result is gonna be a blog post by Vladimir who's right here and by Alex by even Martians and they have this very Comprehensive blog post about how to set up all these features so You know if you want to start using it, it's pretty easy to start and if you want to do all these variants and previewers You know, please feel free to do this. Just try in a brand new app and then see if it works in your production app Okay, so far so good because this was the easy part Okay, cool. So now How does it work like what's inside the code, you know, like you know What we were talking about in the previous talk, you know, you use the routes, but then you want to see how they work So you open the the code base. So here we're gonna go through a similar journey and We're gonna look at the classes that are inside active storage Well to look at the source code, how do you do that rails is open source So the entire source code is on GitHub So you can just get the GitHub comm slash rails slash rails There is an active storage folder and then tire code is right there Another way to open source code if you have active storage library in your app You can just do bundle open active storage and it's gonna open the source code in your editor You can actually do this with any any library that's in your app any jam Okay, so you open the source code and there's a bunch of files. Where do you even start? So this is This is what you should remember about the important classes of active storage There are three main classes. There's active storage service active search blob and active search attachment And I'm gonna explain where they are. So next time you hear about a blob, you know What exactly we're talking about? So let's start with active storage service The service is the part that deals with Just moving bytes, you know, you have an attachment. You have a file Just moving the bytes like from memory from your browser to disk. That's all the service does So I tried to make a picture of this when you upload the cat picture From the browser. So an HTTP uploaded file There is a component that takes those bytes and stores them for instance on your local hard disk if you're in development in a certain Folder slash storage. So that's the service. That's what the service does. It moves bytes from memory to disk Active storage service is a real class and the code looks like this It has other methods has upload and load delete and so on. These are the most important ones and Funny enough, this is the implementation. So if you call active service upload it raises an error This is actually a pattern what this is is an interface This is basically saying there is not just one service There are many subclasses and you can implement whatever service you want, but they have to follow this pattern So you can't call active service directly You can call one of its subclasses and not subclasses they Implement an upload method a download method because they can be implemented in a different way So this is just a pattern you might have seen even in other Ruby code bases That there is a class that doesn't actually implement the method. It just describes what what methods are there? But now let's look at one of the subclasses This is called disk service and it's the one that's by default. So in the examples I showed before I was Running an app locally and disk service. It's the default configuration So this service the upload file the upload method It takes this IO this file and really all it does it's calling the Ruby Methods IO copy stream that just copy copies bytes because this is the one service that stores a File on your own disk So it's doing anything else that taking the bytes and taking the stream of bytes and copying to a certain location The location is this make path for key which by default is inside this slash storage folder in the same words app The download method is also using Ruby Libraries, so it's a it's reading the content of the file from the same path So this is a pretty straightforward implementation takes the bytes move them from memory to disk and the other way around So this is great for development. It's going to store the image on your computer But for production, you probably don't want to store the image locally You want to store it on a cloud solution like for instance Amazon AWS S3 And the good thing about active storage is that it already ships with a service for S3 So you don't have to build it. This is another class. It's the S3 service You see that there is still an upload method and a download method. They're just implemented differently This object for key put those are all methods that come from a gem called AWS SDK S3 gem that it's included So it's just using the methods to move bytes to and from S3 so if You want to use active storage with S3 all you have to do is You go to the configuration file. It's called storage. YAML by default. It's going to say service disk That's the default you just change that with service S3 And then make sure you have the credentials for a for a bucket on S3 and then it just works out of the box and so this is pretty convenient and Active storage actually also has support for Microsoft Azure and Google cloud storage All inside and if you have your own cloud solution and you want to build a Service for that, you know, just make sure you follow this this pattern this interface and then you can build it And maybe you can build your own gem or maybe you can do a pull request to integrate it in the code base How are we doing so far? Good. Thank you. Well, you can applaud if you want. I'm not gonna be Okay, so service moves bytes so in the case of the cat picture we have the bytes But we don't know what those bytes are. We have no idea that it's even an image It's just bytes. So we need some place to store the information Where is that thing what it is? And this is what the blob does The same example when you upload this file the blob is the part that it's actually storing the key So, you know what the file is the original file name might be useful the content type. It's the JPEG and the byte size and so this is the part that stores a reference to the file and It's actually storing it in the database active storage blobs. It is a table in the database So this is the scheme of the table and it reflects what I was just describing before he has a key a file name Content type metadata byte size and the checks out to ensure that the image is not corrupted Now the you know, you might be wondering, okay, where where the where does this table come from? We did not create any table so this is one of the you know things the rails helps you do because the first time you ever use active storage in your app and you try to upload the file You will see this page and it says could not find table active storage blobs So active storage needs that table to work Also, it tells you what to do to resolve this issue run bin rails active search install and this was actually my own small personal contribution to active storage, but this is really The only thing you have to do only once so that you need these tables the first time you try locally You might see this page then you run this command this command adds the migrations to your app You run the migrations and then the tables are there and then you don't need to do anymore when you Deploy to production the migrations are gonna be there you run them and that's it so only once you need to make sure that your app has these tables and then that's it and Just as an approach, this is a little different from other file upload libraries that Instead require you to add fields to every single model. So let's say your cat has picture They say well, you need to add a field called picture to the cat then you have a dog model It says you need to add it there Active storage is a little different because everything is is here is inside these tables So you only have to do that one. So I think that's pretty convenient So I'm just gonna show you one methods of active search blob and this is the upload one. So what it's doing as I'm saying it's as I said before it's Extracting all this information. So it calculates a checksum from from the bytes and then it extracts a content type Either from the extension or the mime type or just the first bytes and then it extracts the size It stores all this information and then it calls the service to actually store the file and then Here's the last class. So we have the bytes We have the blob that it's telling us. This is an image of this certain size But we're still missing a part. We are missing the fact that this image is the picture of this cat We're missing the association. So that's the last part. It's missing to associate the blob with what it belongs to And this is what active search attachment does So this is the you know, the last part when you upload a picture of a cat apart from the service and the blob There is gonna be a new attachment that says this is a picture. It belongs to the record Cat number four for instance, and this is the blob number two. So it's really just building disassociation so then when you call cat the picture it knows where to go and Active storage attachments is also a table and it's the other table that the migrations add to your app and this is The entire scheme also has a name a polymorphic record and then a blob and this index So what this index is saying is if you have like cat number four, it can only have, you know, one picture for this blob And that's that's Basically all there is even the code for attachment. It's really just describing you know what I just Mentioned it's backed by this table. It belongs to a record polymorphic So maybe the cat and then it belongs to the blob it creates the association and so Summing up these are the main classes you have the service that moves the bytes you have the blob that has a reference to Where the bytes were stored so then you can fetch that and then you have the attachment that connects this blob to the original model Okay, so this is like the third act where we like put everything together How does it all fit together at the beginning? I show you Active storage is pretty easy to use. You just add a few lines of code Then I mentioned the main classes, but how does it all work together? There is still some magic there that it's not pretty clear and so that's what I'm going to show you now and This code uses some techniques that are actually all over the rails code base And so I know if you learn some of these things that they might even be useful if you look at other parts of rails Or even your own code base so I Think the perfect starting point is when I said well all you need is to add this line of code So how does this single line of code add this whole behavior to your cat? It's it's pretty powerful And even before that where does this method even come from because here? We are inside an active record base active record doesn't have has one attached as a method. So How did this method end up there? well, the answer is that active storage is an engine and James Adam it yesterday had a talk called here's to the crazy ones where he talked about engines for the entire talk So it's a really good talk to watch on YouTube. We have the chance Active search is an engine so as an engine it has initializers and This is how this code works. This is inside active storage but this is saying is Whenever a race up is loaded is in is initialized Active support on load active record what that line is saying is whenever you're loading a race up when you're loading active record stop there for a second and Extend active record with active storage attached markers So it's loading active record with all the active record methods where find and so on and then once it's loaded extended with active storage attached markers Which is a module inside active storage and one of the methods is has one attached And so that's where that method comes from. That's how rails is able to extend In in this case where extended active record with active storage, but this pattern is really used all over Okay, so that's how the method ended up there now What is this method this method is actually pretty long and I didn't put the whole method here because it can be scary It just stopped at the first like five lines But even just the first line is like class eval code. What is this? Maybe you don't write this type of code normally in your application, so Let me explain what this is When you say a cat has one attached picture Suddenly your cat has a method called picture This is pretty similar to when you say in active record user has many roles and then you have user dot roles So you have this new method just because you've called something else Of course rails cannot know at the very beginning Has attached has one attached what it has to take that name that you're giving it and then Define methods with that name. So this is what's happening here This class eval is taking that name that you pass to has one attached and it's using that to define a bunch of methods with that name For instance, if name is picture This code becomes a little easier to understand because you said picture now You have a method called picture equal and then the other method called picture and so on so this is really sort of metaprogramming in rails, but and it also helps you when you debug to go to the Correct line, but this is really what it's doing. It's defining new methods based on the name that you've given Now this picture equal is the method that it's called when you Set a picture. So when you attach a picture to a cat and it's calling picture dot attach Picture itself is another method defined by has one attached. So this is the picture equal. This is the picture method picture is an instance of an internal class called attached one It's it's this is what picture is the good thing about this is, you know You can go and look at the code of attached one, but it just gives you an idea of how really object-oriented This actor sir is it's not like injecting I don't know loading modules It's really based on a bunch of classes and these classes are pretty small So if you go inside you're gonna see that they're not too hard to understand So this is an instance of this attached one and this is the class that has a method called attach And this method it's basically doing two things First it's creating a blob from your attachment and the blob then calls the service to move the bytes and Then it's creating the active server attachment So we go back to where we were before because you are attaching a picture to a cat first It's creating a blob and then it's You know storing the bytes with the key and then it's creating the attachment so it goes back together to where we were and this is you know, I hope that like with this talk I'm really like letting you know that you can just go and look at a code base and Both learn and you know possibly contribute as I was saying before this Library is is pretty new and it's open to You know suggestions, maybe there are some issues Something else you can do if you go to the github page of rails. There's the issues tab All the issues are normally tagged. So if you see the tag active storage, you might you know want to explore and see What happens in the code the code base is not really that big You know, we heard about journey before that's a little bigger as a code base But if you especially if you're new to rails I think active storage is a good place to start active support is a really good place to start active job as well They're all pretty small. So just give it a try. I Just want to give it another like round to explain again all this process of Attachments blobs and services This is another method that Active storage ads we have has one attached picture. It's this after destroy commit so think about it if you you know destroy a cat which you should never do but if you If you decide to destroy an instance of a cat from your database and that cat had a picture You probably want to delete that picture So if you had a picture on S3, it doesn't need to be there anymore and maybe it shouldn't you know a cat picture Maybe you can stay there, but if it's an attachment of a document and you delete it You don't want the attachment to stay there. So this is also something that active storage implements with this after destroy commit picture purge later after destroy commit is a callback of active record and it's saying do something after The instance was destroyed It's it's after destroy commit So it doesn't run inside the transaction of the deletion if it was just after destroy it would It might be blocking your database. So let's see what happens when you destroy an instance of a cat It's calling picture dot purge later Purge later it's saying if there is an attachment call attachment dot purge later Now attachment, I remember it was in the database. So it's destroyed, but then it's also calling blob dot purge later The blob is actually calling a job. It's saying well, I don't really need to delete this file in real time I mean I can just let an active job do this like five seconds from now When the job runs it's calling blob dot purge Love the purge. It's it's destroying the blob and it's calling delete Delete is calling the service and say can you actually delete this file and then the service for instance the disk service It's calling file dot delete and so this is really the entire flow and you know I just wanted to show this again just to you know demonstrate some some properties of active search For instance in this case really separation of concerns like the cat doesn't know that the file is even on S3 It's just going step by step. So If I haven't said yeah, I think this lever is really awesome and the code is really elegant. So check it out To conclude there is more and I didn't have time to go through that But some of the other things that you might want to explore First of all active storage is not just a Ruby Jam It's also a JavaScript library The code is is in the same place and the reason why there is a JavaScript library is Because sometimes you don't want to upload your files to the race up You just want to upload them directly from your browser to S3 for instance, especially maybe fuse Heroku, you don't want to use the storage of her off. You just want to upload them to S3 so active storage includes a JavaScript library to do that you include the JavaScript file in your in your view and it takes care of Creating a blob so you have a key then with this key the file is uploaded to S3 and then this is the key that You can then use to retrieve this image The only thing that changes is the order in which the blob is created and the image is stored Something else that I found you know useful is Every time you use active storage in your Rails log You're gonna see that information like file was uploaded and so on the way in which this is done is using a library called Active support notification that you can publish a message to and then subscribe It's used all over Rails. So, you know, if you find this and you don't know what it is. Just check it out. It's pretty good And then the last thing is Active storage has a file called routes that are be and I like that we tie back in with the previous talk about routes It has routes because imagine if you have a file then you want to display that file in the browser So it needs a URL. So this URL for a file needs to be generated the nice thing about this file is that About routes that are be is that it's using a couple of methods in the router They were just added in Rails 5.1 the methods direct and resolve. So in your router You can have you know resource get post but you can also use these two methods and maybe you have never seen these methods used in the real app. So if you want to check them out, they are in Active storage and This concludes my talk all the slides are available there and Really, I don't give it a try and let us know what you think I am a member of the Rails issues team, which means if you open an issue in Rails I can now look at it and check it and maybe merge or comment and Even if you want to mention me on GitHub, you know, I am clouded be on GitHub So you can do that if you open a PR it will make me happy and That's it. I'm gonna be here for the rest of risk comp. So if you have any question just Confine me