 So, I'm Adam Keyes, I'm an expert typist at Guwala, and I'm also an internet astronaut. And today I'm going to talk about what I consider the most intriguing part of the re-imagination of Rails that is Rails 3. So namely I want to explore how Active Record was extracted from itself into two new libraries called Active Model and Active Relation, and how that can make it easier for us to write really nice looking and easy to maintain data layer code. So today I'm going to talk about four great looks for your application that can make things that are kind of difficult before Rails 3 to do, that require a lot of boilerplate coding, make those things, those kinds of tasks look much easier, much more appealing to take on, and much more fun to do. So these extractions of Active Model and Active Relation reduced the friction in building little languages on top of data stores. So increasingly in the applications I come across, there's more than just a relational database. There's some sort of caching layer, there's usually some other data store used for analytics, for growth statistics, internal measurements, various data structures that are awkward to store in a database, et cetera. And also increasingly the use of web APIs, whether it's Twitter or Gawalla or some internal API that you use within your company, or maybe it's not even something even as interesting as all these, maybe it's just a PeopleSoft database or some lame oracle database sitting around somewhere. But nonetheless our applications talk to more things increasingly and it would be nice if it was easier to integrate with those things and have the niceness of Active Record when we're using things that aren't a relational database. But doing so requires a lot of boilerplate code in bringing up a data layer. If you want to make something as nice as Active Record there's a whole bunch of other concerns you have to go through before you can even start adding things like validations and associations and all the other parts of the Active Record language per se that make it very pleasant to work with. So Active Model and Active Relation reduce that amount of boilerplate that you need to write to bring up a data layer and makes it easier to get to the point where you can start adding things to your data layer library that make it pleasant to use and interesting to other people. And it also allows developers to focus on building better APIs for data. So instead of having to worry about validations you can worry about how you would like associations to work for your data layer or how you want to provide a nice looking API that looks like a hash or maybe it looks like Active Record or maybe it's an entirely new thing. All these things are made easier with Active Model and Active Relation. So I want to start a layer below though. I want to start with Active Support and using that to clean up your domain objects. Active Support is the often maligned cake on top of which Active Record and Rails are built. In Rails 3 it's smaller and less cumbersome. So in Rails 2 or in Active Support from Rails 2 if you wanted to use something from Active Support or if you wanted to use Active Record in your application the instant you require Active Support your Ruby process would immediately grow by 20 or 30 megabytes of resident memory and weird things would start happening with class loading and it could be an unpleasant experience or inefficient, inefficient experience. In Rails 3 you can cherry pick functionality out of Active Support which is exactly what we're going to do in a minute. So if you just want the core extensions to class or the fancy methods on hash you can pull those in by themselves. Or if you just want its code for generating secure random numbers you can use that in isolation. So the even better part, the really great thing about it being cherry pickable is that now you can actually use just the part of Active Support you need and you're not faced with two unappealing choices which is what you had to do with Active Support 2. I see a lot of people have either re-implemented their own versions of say 2.years.fromnow so they went and did that on their own or even worse they went and just copied that code out of Active Support and dropped it into their application or library which can make it a little ugly when you want to upgrade to a newer version of Rails 3 but a library still uses an old copy of an Active Support method. The thing that I'm really excited about in Active Support is the ability to tighten up your classes and your domain logic by pulling sort of boilerplate logic out of your class and putting it into a module. So let's look at how that starts off. So here's a user class, it's not too different from the user model and probably any of our applications, there's nothing really Rails specific to this. This is using the Rails 3 Active Support. So you can see up at the top we require the Active Support Inflacter because that's a lot of the cache class depends on that and then I require the Active Support Cache Class. So this is sort of an abstraction over a lot of things that might behave like NIMCache whether it be Mongo or a file system, wherever you need to or wherever you can cache data this provides an abstraction on that. And then we have our user class sort of stuff, every user has a name and then I have this friends method which is kind of a very low ceremony association at this point. But I'm always going to be pulling this data out of NIMCache. So I have this cache.fetch, it looks up some key in NIMCache. If there's no data, if NIMCache doesn't have that data then it will execute that block and populate from there. So as I grow this application that would probably get larger and there would be more of these friends guys. And the simplest way that I thought I could get this working was just to have an instance method called cache and it returns a new connection to NIMCache. So a quick easy way to clean this up is to use Active Support's attribute accessors that work for modules and classes. So adder accessors that probably everyone has used, they are one of the really neat things to me about Ruby, one of the first things that intrigued me, it's way better than writing those methods yourself. But they're only available on instances. So Active Support gives you a module and class compatible versions and it also gives you class inheritable versions in case you're writing a framework where you're going to have a class hierarchy and you want to assign something to the parent class of everything and have it propagate down to all the child classes. So here I've got a class attribute accessor and now when I call cache.fetch that's going to be the connection that is shared amongst all instances of user. So this is how that code would actually be used. Now I'm going to do somewhere in the startup logic for my application, I'm going to say user.cache equals memcache.store.new and then every user object, like I said, shares the connections to the cache. Now I want to clean this up a little bit because in my imaginary domain world I'm going to have a lot of these pseudo associations and if I'm going to have a lot of them then writing these same five lines of code every time is going to get really lame. There's a lot of boilerplate here and I want to try and get rid of that. And so I'm looking at this and I'm thinking well the things that can vary here are the name of the association, how the key for the cache is formatted and the logic to use to generate values if there's no data in the cache already. So I cooked up a little language for myself, you can see it extracted here. I've got this cache key method that takes a symbol that tells it what association to create. So it's going to create a friends method that does some stuff and it's going to use the friends key method, that second symbol to generate cache keys and then the logic is just basically the same and it's in the block for this cache key method. So I've got a little language that I think looks nice, I think this might work. The way I developed this sort of thing is I just sort of open up a text editor window, start typing in what I think needs to be in this little language I'm creating and then I go and try and make Ruby to execute that and maybe I come back and revise this so that it's valid Ruby or it's a little easier to implement. But that's the basic shape of how this sort of refactoring comes about and I learned this from Rich Kilmer, so hat tip to him. So here's the implementation of that little language. I'm going to use a Cater Accessor again, I'm going to be saving the cache lookups that I need to do and the cache key methods to format the keys. And you see this block form of Cater Accessor, that block is used to initialize those class variables. So they're going to end up as empty hashes to start off with. And then I've got the actual cache key method. So it's a class method, it takes the name of the association and the key to use in memcache and then it's going to define, it's going to throw some code into my class. It's going to, when this is called, it's going to assign the method, the logic for the method that I'm using into the cache lookups. It's going to assign the cache key formatting method and then it's going to define the method that I had before. So it's going to define, if for friends, this is going to define a friends method and it does a little tricky memoization. So the first thing it does is look for the instance variable of the same name and if that's there, then we'll just use that. So this will hit the cache once per process and then every other time it'll just read it out of an instance variable. And then it's going to, if it wasn't already in the instance variable, it's going to generate the cache key method by converting, it's going to look up the cache key and then turn that into a method and call that so that gives us the cache key and then you see the same basic logic as before except it's assigning to the instance variable. So the exercise to the reader is that this all executes, this actual method here executes in the class scope and not the instance scope. So you have to do some tricky things in those blocks. If you're looking for a challenge, make this execute on instances instead of classes. So this is what my user class looks like now. It's got all of my fanciness in it. But the downside is that now it doesn't really fit too well on one slide. If you're sitting in the back, you probably have to squint a little bit. And I think that's kind of a code smell. So the cool thing is that active support enables a nice little refactoring. I've started calling extract concern. And that makes it really easy to clean this code up. So Tyra's a little weirded out by this code. She thinks it can kiss her fat rear end. And so we're going to improve it. So active support concern is just a module that you extend into another module. And then it's basically syntactic sugar for the old Rails style plugin hack where you've got some module. You include it into your class. It has an included hook. You extend some module. You include another module to get instance and class methods. And I always get it wrong, but this is way, way easier. You've got some class. You give it whatever name you want. You extend active support concern and then you've got this included block. And all you have to do is take the code, is cut the code out of your class and paste it into here and you're done. You don't have to remember which hooks to call or anything else. So like I said, this is way easier and nicer than the old Rails 2, Rails 1 style plugin method hackery. This is how we use it. You just include cacheability and all the code is the same. But now the code, my user object fits on one slide again. And it's easy to see where the cache behavior comes from. If I've just handed you this application and you're thinking, what is this cache key method? Where did it come from? You would probably have already scanned past it and you could go find that cacheability module and figure out what's going on. So the crux of the biscuit is that accessors plus concerns can have a nice slimming effect on your code. You can have more concise domain logic and only a few more lines of code. And can help remove tedious code from your application. So the really cool thing about concern is that where previously I would have had classes that have some comment block that says authentication methods and then another one that's like connection management. I can just take all the code below that comment banner and throw it into some module and then include that wherever I need it. And I think that's a little clearer, a little nicer. Like Glenn was saying before, the code is the document, the code is the model. So I'm pretty excited about that and I've been using it a lot. So there's other cool stuff in active support. There's a message verifier in encrypted classes, which is what Rails uses for implementing signed keys. So if you have some application where you need to send secure data over an unsecure channel, give that a look. There's a class for generating secure random numbers that end up looking like API tokens. So I use that in any application where I need to generate tokens to identify things, to pass around, especially for, like I said, APIs. And in general, active support is less stab you in the face these days. So if you've been burned by it before, give it a fresh look, it's really great. So now I want to talk about active model. And especially making your own models that look good and talk good too. So active models are the result of extracting much of the goodness from active record, the things that you come to expect like validations, callbacks, dirty tracking, serialization. If you've ever wanted to put those into your own Ruby objects, just plain old Ruby objects, this is going to be your jam. And better still, active models carry pickable just like active support. So if you just need validations and you don't care about dirty tracking, it's fine, you just include what you need and go about your business. So validations are really easy to do now. All we have to do is include this active model validations module. And then we can use pretty much all the validations from active record that we've come to know and love. You don't need any extra methods to get this functionality, as long as there's some method called name that returns whatever you consider the name attribute for your domain, you're good. And you just go on your way. This is new to me. You can also have classes that you've extracted validation logic into. If you say you need to share some validation logic across projects or classes, you can use a class that just has a validate method. It takes a record and you do some validation logic. And then if there's an error, you append it to the record's errors attribute. And this works pretty much just like it did when you're implementing validations and rails one and two. Except now it's a hash instead of some weird class that I always forget the interface to. So now you just say error sub base or error sub name or whatever. This should actually probably be error sub name but what's a few things between friends. So that's all you do to use this in your class. You just say validates with Ghostbusters validator and you're done. There's no step two. So this is what my domain class looks like now that it has validations in it. And that's pretty straightforward, still fits on one slide. And it looks good. This is how we'd use it. I'm gonna create a new user object. It's not valid yet and I can look at the errors and I get back this ordered hash. And the really awesome thing is that ActionView, if you use rails, is compatible with this. So because active model validation is the same thing that ActiveRecord uses. If you have your own custom model objects that you include active model validation into, all of the error for and other form helpers and rails that show pretty error messages in your forms, those all work. So that's a huge win in my opinion. So here I'm gonna set an attribute. I'm gonna set the name of this guy to Ron. But Ron Evans is a cool dude but he is no Ghostbuster. So it still returns false. And you can see we have slightly fewer errors here. And then if I set the name to Ray and call valid again, then that's true because Ray is a bona fide Ghostbuster. So another cool thing that I like in active model is serializations. So what if I want to encode my object as JSON or XML? Tyra here is excited about that kind of functionality. It's really handy when you're doing APIs, whether it's a client or service or whatever. But if you think about it, writing that kind of code could get potentially nasty, especially if you have deeply nested models. So she's not quite so sure she wants to write this code herself. But luckily, she doesn't have to. I'm gonna make this a little more interesting, just add a couple of methods to my model, add a couple attributes. And then this is all I need to add in the way of infrastructure for serializations. I need an attributes method that is gonna return a hash, which is what will get serialized. So I just create this hash and pull out the attributes that I want to send over the wire, or send exchange in my integration. And I went ahead and memoized it just because I love memoization. And the really cool thing is that if I implement attributes equal and have it accept a hash, then later on I can take XML and JSON that I've received from someone else and populate an object with it. So all you have to do is just, you take the hash and then you're just responsible for taking data out of the hash and putting it in the attributes where it belongs. So to get the serialization, I include these two modules, Serializer's JSON and Serialize XML, and this is how I would use it. Once I include those two modules, I get a serializable hash method that returns basically the hash returned from attributes. So that's a good way to debug to make sure that what's going into the JSON and XML processes is correct. And then I can just call two JSON or two XML on my models and get back the correct data. We can even use from JSON and from XML. So here you see I'm gonna dump the JSON to a string. I'm gonna create a new blank user object. And then when I call from JSON and pass it the JSON string, it populates my new object from the JSON. So this is really, really handy when you're building APIs, integrations, serializing data to disk or whatever. So now we wanna do persistence and queries like a boss. And I just made you think of George Michael, hopefully. In Rails 2, ActiveRecord contains a bunch of logic for banging strings together to form queries. And it also contains a bunch of logic for talking to various relational databases. In Rails 3, a lot of that's been abstracted out into a library that models the relational algebra that SQL is built on top of that all relational databases use and that we have come to sort of accept in our lives. But the cool thing is that in the process of extracting that, ActiveRecord or, I'm sorry, ActiveRelation or A-Rail makes it possible to use the same API to query all your data sources. So if you've looked into ActiveRecord in Rails 3, then you've seen that they're moving away from using find and passing a conditions hash to calling these chainable methods like where and order and limit to build up your queries. So ActiveRelation is what sits underneath ActiveRecord to implement all that and to actually generate SQL queries. And so you can use that as a duck type to set your own data stores on top of something that kind of acts like ActiveRecord, which is really handy and really neat. So if I want to add that sort of functionality to my user model, I'm going to include ActiveRelation relation. And so if you read about the relational model, the relational algebra, basically everything is a relation. And a relation is just anything that looks vaguely tabular. You know, with some rows and some columns and some data in there and columns have names, etc, etc. So I need to include that and that's going to give me all of the ActiveRecord 3 query methods like where, limit, which is actually called take and skip. So it's a little more low level, but it's closer to the relational algebra. And you don't have to implement all of it. And then I also need an engine. And an engine is the thing that knows how to talk to the database. So this is the connection to whatever your database is, whether it's Twitter or Cassandra or Mongo or whatever. So my goal for this user model is to be somewhat like ActiveRecord. So I'm going to add some sugar on top of ActiveRelation. So I'm going to add a save method and it's not quite as clever as ActiveRecord. It doesn't do dirty tracking yet. But it's good enough to just create a new record in my database, whatever that is. And it's going to call insert, which is a method that comes from A-RailRelation. And it's going to pass itself. And we'll see how that's implemented in a minute. Same thing here with find. It generates a key into the cache. And then it calls, it creates a new where query, a where clause in a query, and then calls that query object. So this is the same thing where ActiveRecord queries are now lazy. This is, A-Rail works in the same way. But you notice that it doesn't take a hash like you would do in ActiveRecord. Because I'm going to be building this on top of memcache, which has no query language at all. I'm just going to say the semantics for my where are, you just pass it some memcache key. This is just for those playing along at home. When I was doing these examples with Rails 3, Beta 3, there was a weirdness between ActiveModel serialization and how A-Rail's each method works, which broke JSON, which I would prefer to use, but Marshall ends up working. So I have a Marshall dump and Marshall load methods, which end up looking familiar anyway. And this is the user engine. So A-Rail implements the query mechanism for us and helps us, gives us some higher level methods that we use when we're generating a query, whether it's for memcache or Mongo or whatever. But we still need to write an engine to handle translating to the right query language and doing the reading and writing from the actual database. And these seem to be called engines by convention, but really they're just a duck type that you need to know which methods to implement on. And those methods are basically our good old crud friends, create, read, update, and delete. So here's create, it takes an insert object, which is created by that insert when I wrote the save method on my user class. So I'm gonna call save on user. That's gonna get basically translated into this insert object. Like I said, everything in ActiveRelation is one of these relation classes. And unfortunately that means the insides of ActiveRelation is like a maze of a thousand doors all similar. So the way to figure out what's going on with ActiveRelation is to basically just put a debug statement or a print statement here and print out whatever parameters you got and start spelunking through those objects and figure out where the data you want is. So what I did was I did that and I found that on the insert object there's a relation attribute and that's basically the object that I passed from insert and so that insert.relation ends up being my user model. So I call cache key on that. The value is I just wanna insert the whole object and then I call cache.write key value and that cache is just my memcache connection. There's nothing ActiveRelation-y or fancy in there. So to read data back out, I had that where clause that I called in my find method, that's gonna be the argument to select. And I'll talk about the raise in a second. All it's gonna do is there's a predicates object on that, which is usually something like usually your predicates, if you're doing SQL, if you have a real query language, it would be like A equals 4A is greater than yesterday or whatever. But in this case, since I have no real query language, I just need that first object out of the predicates and grab its value. And that's the key that I want. And then I read that key out and I get my user object back. So like I said, I created a where clause earlier, but I could have created a take, a skip, an order clause, anything you can think of in SQL, there's classes for those query clauses. Because my database is more limited than a relational database, I'm just gonna throw an exception if I get anything but a where, because I don't implement those things. And say I just don't support that in my query language. So like I said, I spent lots of time poking around on the insides of these various objects. I have all this code online. If you decide that you want to build an A-rail engine over your data store, then give this stuff a look and use it as a starting point, so that you don't have to figure out the interfaces, which is not entirely clear. Updates, if I want to override an object that's already been stored, they contain an assignment attribute. I pull the value out of that and then it's the same sort of get the key, get the value, write those to the cache, and then delete has a relation. I pull the cache key off of that and then delete the key out of the cache. So this is the whole user engine, all the create, read, update, and delete. You can use this as a starting point, like I said. There's also, if this is interesting to you, there's an in-memory engine that's included as active relation. So you can take some object graph, some collection of objects you have in your application, and they don't have to be persistent in any way. They don't have to be like part of your data model or whatever, but if you want to query them with something that's like SQL, with like ware clauses and skips and takes and orders, if you can tell A-rail how your data is shaped, then you can use that to query, and that's kind of really rad. And it's also rad that you can, and it has test cases for this, but I haven't seen any examples. You can take in-memory objects and active record objects or whatever implements A-rail, and you can do queries across those two things that join on each other. So if you've got Twitter data and your own applications data and you want to join on them based on user or status or text or whatever, that's entirely possible, which is really freaking cool. There's also an A-rail Mongo engine on GitHub, which is really handy to look into as it's like a Mongo. When you get down to it, it's a lot like MySQL and semantics, so it's kind of easy to figure out what's going on and what they're actually trying to do when it's not all couched in a relational algebra theory. So here's how we set up the engine. We create a cache, and then we assign the engine attribute and pass it the memcache. Here's how we use it. You just create a user object just like before. We can save it. We can create a blank object. We can find what we just saved, can update it, can delete it. It's all like, it's a lot like active record, and at this point we are coking with gasoline. So through all these different looks and approaches to using active model and active relation, we popped a lot of collars, 15 collars on this dude, but we got a lot of functionality too. This is our domain model and all the support code and the active relation engine. And this obviously doesn't fit on a slide anymore, but it's about 100 or 200 lines of code, but we got a lot out of it. From this, in this user model, we have declarative, lazy caching, validations, serializations, persistence, and querying, which is pretty good for a day's work. If you're trying to bootstrap a database, it's a lot better than spending a week or two weeks trying to get all that sort of stuff in place. So keys to success using active model and active relation. Give active support another try, even if it's hurt you in the past. It loves you more now. Fancy up your classes with active model even if they don't have to be persistent. If you just need validations or dirty tracking or whatever, give active model a try. If you're really ambitious or if it's your thing, build a data layer with active relation, and all these things will help you make better codes. So that's all I have. Thanks for coming out. I'll post these slides that are online and on GitHub. My site is therealatom.com and I'm also therealatom on GitHub so you can find that stuff there. I have a couple minutes for questions. The question is, how easy is it to write your own serialization methods? I haven't tried. So you're thinking like if you wanted to serialize to like Bison or something else. I think you would just, you would take that data from the attributes method and do whatever you need to it. So it seems like it would be just as easy or hard as converting a hash to whatever you're talking about. I don't know, to make it work like active model, I don't know if you'd have to do anything above and beyond that. Anyone else? All right, thanks.