AARON:
Avdi?
AVDI:
Yes.
AARON:
How come your sound is so good?
JAMES:
[chuckles] It’s his voice.
JOSH:
Genetics. [laughter]
JAMES:
That's awesome.
[Hosting and bandwidth provided by the Blue Box Group. Check them out at bluebox.net]
[This episode is sponsored by JetBrains, makers of RubyMine. If you like having an IDE that provides great inline debugging tools, built in version control, and intelligent code insight and refactorings, check out RubyMine by going to jetbrains.com/ruby]
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to rubyrogues.com/newrelic]
CHUCK:
Hey everybody and welcome to episode 81 of the Ruby Rogues podcast! This week on our panel, we have Avdi Grimm.
AVDI:
Hello, hello.
CHUCK:
James Edward Gray.
JAMES:
So excited to be on the [inaudible] episode.
CHUCK:
Josh Susser.
JOSH:
No comment.
CHUCK:
I'm Charles Max Wood from devchat.tv and this week, we have a special guest – Aaron Patterson.
AARON:
Hi this is Avdi Grimm. [laughter]
CHUCK:
So it’s been a while since you've been in the show Aaron, do you wanna just quickly introduce yourself for the handful of folks that haven’t seen you speak at the myriad conference you’d been to?
AARON:
Sure. My name is Aaron Paterson. I work on the Rails Core Team and the Ruby Core Team and I tweet as “tenderlove”. I don’t know what else to say about myself. How's that?
CHUCK:
Ruby Core Team? Do you speak Japanese?
AARON:
I do. Yes. It’s true.
CHUCK:
[laughs]
AARON:
[laughs] And I only participate in Japanese too.
CHUCK:
[laughs]
AARON:
…intentionally so that nobody can understand what I'm saying.
CHUCK:
And by “nobody”, you mean neither the Japanese speakers nor the English speakers, right?
AARON:
Exactly, yes. Because my Japanese is only good enough that… it’s good enough to get myself in to trouble, but not good enough for everybody to understand me. [laughs]
JAMES:
But the truth is Aaron only learned Japanese because of the noise-- [laughter]
AARON:
The reason I learned Japanese was in order to read a Ruby documentation.
JAMES:
[laughs] That's kinda sad.
AARON:
Well, I just thought all these crap online… like all these blog posts, all these documentations, I'm like, “What are they saying? What are they saying? I must know!” And so I'm like, “I may as well learn this,” and then I decided to. But now, I just continue to learn it because… I have been studying it for like 6 years and I'm still not good enough to read the documentation.
CHUCK:
Wow.
AARON:
[laughs]
JAMES:
That was great experience.
CHUCK:
Yeah. So anyway we brought you on to talk about Rails 4.
JAMES:
Can we do Best of Parley first?
CHUCK:
Yeah we could do that.
AVDI:
Best of Parley this past week – in my opinion anyway – was a thread about method ordering. I liked it because it’s a topic that for some reason I didn’t really have an opinion on yet. And it was basically about how you order the methods inside your classes. Do you put then in alphabetically or do you sort them by like put the outermost methods top level API methods first and the implementation of the method after and various permutations on that the people brought up. So it’s an interesting read. It’s an interesting reading about the thought process that goes into different choices even in little things like that. And so if you want to enjoy other fine discussions of programming minutia like that, you should check out the Parley mailing list -- which can be found right on our home page. Right Chuck?
CHUCK:
Yeah. You just got to rubyrogues.com and sign up. All right. Well, let’s go ahead and jump in to the episode. So, Rails 4 – not to be confused with Rails 2.3.5, right?
JOSH:
Oh, little Rails is growing up so fast. I remember when it was just 0.13.
AARON:
That's Rails 4 – for you and me – is the subtitle. [laughter]
JOSH:
I have that album with Marlo Thomas.
CHUCK:
[laughs] So I am kind of curious as to what everyone’s first version of Rails was.
JOSH:
I'm pretty sure mine was like 0.8 or 0.7 or 0.13 – I don't know. It was way back when – 2005.
JAMES:
Aaron, what was the first version of Rails you played with?
AARON:
0.something around 2005 as well -- 2005 or 2006 -- yes. I can’t remember the origin.
AVDI:
I don’t know. I mean I was kind of at the time that it came, it was being… first coming out, I was sort of watching from afar because I wasn’t being paid to write Ruby at the time. But I think when I first started getting paid to write Ruby, I worked on some apps that were still like pointing on or something – I'm not certain.
CHUCK:
So I got involved in 2006 (so you guys are old) and I think it was 1.1 or 1.0 that I was first exposed to. What about you James?
JAMES:
I played with the early versions just kind of on the side but I definitely didn’t use if for anything real until about 1.2 or so.
AARON:
Yeah I think… I never actually wrote production code until 1.2 or so as well. Like I was only playing with it. In fact, I actually got it working with oracle in the 0.whatever days. It was pretty ridiculous.
JAMES:
It is ridiculous. So you work on it almost all the time. You get to play with all the versions.
AARON:
Yes I do work on it almost all the time when I'm not doing Ruby Core stuff. Yes, pretty much.
JAMES:
So in Rails 4 (since we are about to go another big version) what are the major changes that you guys have been working on?
AARON:
The major…? I don’t know like I guess it depends on what you mean by “major”. Like as far as stuff like major coaching is, I don’t think there is too much under the hood -- at least nothing that should cause backwards incompatibility. Like, if you have trouble upgrading your app, it’s most likely just a bug and you should probably report it, right? But I guess some things you can think of… or I'm trying to think of stuff of the top of my head. We’ve moved tests around. So the directory structure changed. You are going to have--
JOSH:
Can you say more about that you restructured it to be more like RSpec, where it’s focused on models and controllers rather than functional and unit?
AARON:
Yes exactly.
JOSH:
Oh cool. I've been waiting for that for years.
AARON:
Yes. That is what is happening and like--
CHUCK:
Are you still going to a place for proper integration and acceptance test though?
AARON:
I can’t remember if we have acceptance directory, but we are going to have integration. It’s going to be like models, controllers and integration if -- I remember. A helper’s directory too.
JOSH:
Was there a features one?
AARON:
I don’t think so.
JOSH:
OK. Maybe that's just from Capybara.
AVDI:
Yeah. It does kind of coordinate nicely with the new Capybara release -- which finally moves from spec requests to spec features -- which makes more sense.
JOSH:
OK. So Aaron, the thing that I really wanna know is what got taken out?
AARON:
What got taken out?
JOSH:
Give me some stuff that got pulled out in the gems.
AARON:
Damn. I should have been more prepared for this. Yes.
JOSH:
Sprockets?
AARON:
No. It was already a gem. Sprockets Rails is gone, but I think it’s just because some of those Sprockets stuff or the Sprockets Rails integration stuff just got pushed up to the Sprockets gem.
JOSH:
I read something that the asset pipeline stuff got pulled out into a separate gem, so that it can be maintained on an independent release cycle.
AARON:
Yeah well, I don’t think that's… I mean I guess it’s technically true because the Sprockets Rails stuff is gone, but its I don’t know… I don’t think it’s any more… it’s not anymore removed than it was before. Sprocket Rails was super tiny. It was just like a little bit of integration between Sprockets and Rails and now that stuff is just moved in to Sprockets.
JOSH:
OK so it’s just being managed in a different code base or a different project?
AARON:
Yes. Exactly.
JOSH:
OK. Your gemfile will look the same.
AARON:
Yes, pretty much.
JOSH:
OK.
AARON:
Sprockets.
JAMES:
OK. So they renamed some test directories or removed some integration code -- that took about a year.
AARON:
Yes. [laughs]
JOSH:
I read something about there being a new policy around deprecations.
AARON:
A new policy around deprecations.
JAMES:
Yes! The good news is they are going halfway to send var? [laughter]
CHUCK:
What do you mean by halfway to send ver? Or to send var or whatever?
AARON:
Oh! Half way to send ver. I see what you are saying. Oh, I guess… I don’t actually think there's a policy change. I think the problem is like most people… there was never a policy change, it’s just that we didn’t have a consistent… The people who have commit bit didn’t have a consistent idea of what the application meant -- if that makes any sense. Like now, it’s just completely stated so that everybody with commit bit knows exactly how we have to deprecate stuff -- which is supposed to be closer to send ver.
JAMES:
Yes it is.
AARON:
So it’s supposed to be that way. And we are just explicitly stating it so that it’s clear among the Core Team -- like well, among the committers I mean.
JOSH:
[unintelligible]
AARON:
Yeah, we actually had some… I don’t know if people know this in general but we actually have a lot more committers than are on the Core Team. So I think there is (I'm totally guessing here) like, maybe 12 or 13 committers. And to be honest, I don’t actually know the difference between a Committer and a Core Team member is. One person has a --- on the website. I'm not sure. [chuckles]
JOSH:
[chuckles]
JAMES:
I'm sure it’s more important than that.
AARON:
Is it? As far as I know there’s no difference. I didn’t get a ---- or anything.
JAMES:
[laughs]
AARON:
[laughs]
JOSH:
My impression is that committers can’t do anything without a chaperon.
AVDI:
[laughs]
AARON:
[inaudible] …committer for quite a while before I was a Core Team member and I just did stuff. It doesn’t matter. I think— [laughter] I have no idea what the difference is. I guess maybe it’s… is there larger decisions to be made about a framework supposedly the Core Team members are more important. I don’t… but I don’t even know if that's true because like… I don’t know, I try to listen to all of the people. So, nobody’s opinion is more important -- as far as I know -- except for [inaudible]. [laughter]
AARON:
[laughs]
JOSH:
By the way, speaking of releases, I hear that there was a DHH 2.0 release in the last day.
AARON:
What?
JOSH:
Yeah, David had a kid!
AARON:
Really?
JOSH:
Yeah, Colt Heinemeier Hansson. He just twitted it. So mazal tov, David.
AARON:
Good for him.
CHUCK:
Rails *and* David are growing up.
JOSH:
Yeah, talk about an unannounced release. [laughter]
AARON:
I had no idea. I mean--
JOSH:
I got to say it’s kind of daring of him to do this release without a beta beforehand but— [laughter]
AARON:
That's weird.
JOSH:
Speaking of betas, how was the… has the release process for Rails, is that going to be changing for Rails 4.0 where you can follow pretty much what’s happened in the last couple releases.
AARON:
I think it’s going to be pretty much the same. We were just going to ship betas and then ship at some point. I don’t know, I think we are going to keep it about the same. I like us to have more regular release cycles, but we don’t have like a dedicated release manager -- I think kind of sucks.
I tried to be the dedicated release manager -- it’s extremely stressful.
JAMES:
[chuckles] This is not surprising.
AARON:
It’s super stressful. Like you put out a realise and it’s like… you put out some betas or you put out some release candidates and you are like, “Please test, please test, please test” and very few people actually test it.
JAMES:
There is always that one guy who sends that word correction in like the release note.
AARON:
The thing is like, people do test it, but I think it’s hard because… so you can’t say like… we usually put a deadline on like, “OK we’ll give you 3 business days”, basically or 72 hours or something like that and people will say like, “Well that's not enough time!”. But the problem is it doesn't matter how much time you give, it’s always going to be not enough time for some people, right? And you got to get it out at some point.
JAMES:
Right.
AARON:
So it’s basically like a “damned if you do, damned if you don’t” situation. So some won’t have time to upgrade and then of course those people will find the bugs or whatever. I mean to be honest, I look at the release candidates as more of a like cover your ass thing. Like somebody comes along and they are like, “You completely broke our application!” You can say, “Well we did our best. We released candidate and asked for a feedback.” So I mean at least you can like say, “We did our best.”
CHUCK:
On top of that, I just wanna chime in and remind people, look if you have an app that you are planning on upgrading to Rails 4, go test it with the release candidate.
AARON:
Oh yeah.
CHUCK:
I think that's kind of like what you are saying Aaron -- that it’s out there exactly for that purpose and make sure that its stable before you push it to production.
AARON:
Definitely test with Git too like we try to keep master pretty stable. So it’s… I'm not going to say “rare” but it’s infrequent that master just doesn’t work. We try to keep it pretty stable.
JOSH:
Now, what about “beta” versus “release candidate”? Have you been finding in the last release cycle or two that people has been doing more testing of the new release before you get to the release candidate? Or does everybody just wait until they see a release the candidate to try it out?
AARON:
I think it’s about the same between… really I think the main factor is just advertisement -- really. Like getting the word out -- like tweets, mailing list, all that -- getting the word out really has an impact on testing I think.
JOSH:
So Aaron, we have… you know, a couple of thousand people who are listening to you. Would you like to say something to them?
AARON:
Yeah please test Edge Rails. Please.
CHUCK:
So Edge Rails is not a release candidate – edge Rails is go and get Rails and do stuff with that.
AARON:
Change a gem file point at git.
JAMES:
You can just in your bundler gem file that comes with Rails, that one of the commented outline shows you how to switch to Edge Rails.
CHUCK:
Yeah and then you just do a bundle update Rails and then pull it down. So one other thing that I have seen and I want to ask you about -- and its related to the test structure, but it’s more about mini test vs. test unit – I understand that that was a change that Rails 3.0 still use test unit by default and Rails 4.0 will use mini test spec?
AARON:
Yes.
CHUCK:
Was there something that have formed that decision or did you just have some feedback from people saying they want it or what?
JAMES:
It’s about time.
CHUCK:
[laughs] You have a point there James but I wanna hear what Aaron has to say.
AARON:
We just did it without asking anybody. [laughs]
JAMES:
[laughs] And folks, this is why Aaron will be kicked off of the Core Team by the time you hear this episode.
CHUCK:
[laughs]
JAMES:
He will be in committer’s status, which we have established as terrible.
AARON:
[laughs]
CHUCK:
Yeah but we have also established he can do whatever he wants as committer status so.
AARON:
So test unit… test in Ruby… test unit use mini tests. It’s a subclass -- like it’s actually subclass of mini test. So, all I really did was just change Rails’… so Rails provides a test class like active support test case. …did change super, the class mini test and activate mini test spec is just a sub class of mini test test case. So, all I did was change active support’s class to sub class for main test spec. So it’s not like I mean, everything is completely backwards compatible -- you just get spec’ing for free basically.
CHUCK:
I was going to say, doesn't it change that flavor of the test completely though since you now have the mini test spec DSL that you are writing in instead of actually building the class and calling it test underscore, underscore, underscore, underscore, underscore?
JOSH:
Somebody kick Chuck.
CHUCK:
And then, you know doing assertions instead of examples?
JAMES:
It’s optional -- you can do it either way. Once mini test spec has been loaded, both are loaded. So if you define a class and use the test underscore, that works and if you used the spec syntax, it will define the class for you.
CHUCK:
What do the generators give you? Do they give you example DSL flavor or do they give--
AARON:
They give you exactly like what Rails used to give you -- which was the normal classes. But like if you remember there are some stuff in Rails, like doing test and you give it a string and you do a do right?
JAMES:
Right.
AARON:
Those will have a kind of a little bit of DSL type stuff.
JAMES:
Right.
AARON:
But what was nice about changing it to mini test spec that we could define that DSL in terms of mini test spec. So basically, all those methods just turned in to like some alias, right.
JAMES:
Gotcha.
CHUCK:
I have to say that I really liked the approach because as James said, you can do it either way and you can mix asserts in with your example notation. So you can do a dot must equal or you can do an assert_equal and get what you want out of it.
AARON:
And you are not actually punished for using one versus the other – they are about the same like as far as performance is concerned, they are about the same. I think, I mean I see somebody… so I figured since everything was backwards compatible, I just slip this in, just because it’s completely backwards compatible and you could write it exactly the same, but now you just these extra features for free, so I predict or at least hope that once Rails 4 comes out, somebody will write a generator that's like, “OK generate stack style test now.”
CHUCK:
Mh-hmm.
JOSH:
And what about the test for Rails itself? Have they been modified to take advantage of mini spec or like mini test or mini spec?
AARON:
No. No.
JOSH:
Is that a goal for the code base to move the tests to take advantage of that stuff?
AARON:
We don’t like that style of tests.
CHUCK:
[laughs]
JOSH:
Well I mean but… OK sure I mean that's fine but there is stuff in mini test that is a super set of what's there in the test unit API.
AARON:
Well, we have converted… I mean all the Rails test use active support test case as the base, so we are completely switched to mini test. There's no uses of test unit in Rails anymore.
JOSH:
OK. But is there like some added value that you could take advantage of in mini test that wasn’t already been presided by active support test case?
JAMES:
Some of the benchmark methods maybe.
AARON:
There's benchmark methods. Also if you are on a Mac, Ctrl T is pretty nice. That would display the current test that you are on. So like let’s say you have a test and that’s way too slow and you don’t know what's going on, you don’t know what method it is, you hit Ctrl T and that sends an --- and mini test will actually trap that signal and then tell you like what test you are currently running. So you get some visibility of what's going on. It’s one thing I like.
JOSH:
OK.
AARON:
It’s nice.
JAMES:
And I wanna switch the topic a little bit (if you don’t mind). Some of the new things in Rails 4 have raised kind of some questions like I think we can all agree that turbolinks has been a little controversial in its introduction.
AVDI:
Just so I'm clear, that's a combination of an Atari Lynx and a TurboGrafx-16, right?
CHUCK:
[laughs]
JAMES:
Yup that's it.
CHUCK:
I want one.
JAMES:
But also, there is the new like routing concerns (which I don’t think anybody has a problem with) but I also wouldn’t say as like a wicked link popular library with 500 total downloads.
AARON:
That's very concerning.
JAMES:
So, I guess my question is, it seems like Rails used to be a… well, I think DHH has described several times as a place where the cultivated technologies are brought together. That after yeah, this is good and people do that. But it doesn’t seem like that's happening as much. Am I misunderstanding?
AARON:
Yeah… No, I don’t think you are. I mean, I guess it’s like [sighs] Oh boy… trying to figure out a nice way to say this. Hmm…
CHUCK:
Just say it how it is and we'll sure to cut it for you.
AARON:
Thanks. It’s stuff that DHH likes to use. So, like they needed concerns in base camp and so they used it -- or they use turbolinks in base camps. A lot of stuff like turbolinks came from pjax I guess. So a lot of it has been tested in production. They use it in production. The concerns, like I think the router concerns, those are… so I actually think the API is kind of weird. I'm not a huge fan of concerns but, the reason—
JOSH:
This is like mixins for routing right?
AARON:
Yeah like you can say like, “OK, I'm going to reuse this particular block. I'm going to share this route among a bunch of different routes.” I think really what it is its showing that thing -- that concern thing is showing weakness of the DSL.
JOSH:
Yeah. The one thing that that looked particularly useful for to me, was being able to define that concern in an engine and then mix it in at various places in your sort of resource hierarchy. So for instance, you have some sort of commentable thing in your engine (because your engine was providing commenting), you could drop that on to, “Oh, I have an image over here and I wanna let people comment on it. I have a blog post over here, I wanna let people to comment on it.” And then your engine doesn’t have to know about all the places that these things get used.
AARON:
But the problem is like, in my opinion what it boils down to is that all of views like this block style DSL is not very good for reusability and--
JAMES:
That's a good point.
AARON:
Like the thing is though like I mean… I can whine about that all day, It’s just I don’t have a better solution for it. So I try not to whine about it too much. I think like, it’s not actually a problem for me because I think like we can take that DSL and implement it under the hood in terms of good objects and then eventually expose a more OO-style routing.
AVDI:
That's basically what Sinatra did right? I think they started out with the DSL and then they kind of refactor things internally so that the DSL was basically just an expression of a pretty cleanly put together object system. And you know, and then if you found yourself in a situation where it needs to be more general than the DSL would let you be, you could just use the object directly.
AARON:
Yes exactly. That's the thing like I think a lot of people, when DHH put that in people like got in to a huff, because they are like “Oh this is so much perplexity, blah, blah, blah”. And really if you just think about it, it’s like well we just need to refactor the internals because it’s really just showing that we are missing a good OO system for doing reuse in our router. So I don’t know.
JOSH:
So I remember way back in Rails 1.0 days how the routing code was always like “here be dragons” part of the Rails code base. And who was it… Ulysses who was the Rails core person who was most knowledgeable about that code. And it’s just always seemed to carry that along with it that that every generation or so, there's a new routing… there's like this huge work done on routing and it gets changed and still nobody can understand how it works.
AARON:
Nobody has come up with, “OK if you go look in the routing code, the nouns that are being used aren’t very good,” like a lot of the time we are working through Rails code for example like “concern” is a terrible name. I don’t like because it’s like, “I'm concerned about many things.” “I'm concerned about the environment.” You are like, “What the hell does concern mean?” But there are also stuff like, specifically in the router, it’s like RouteSet and you are like, “What is a RouteSet?” And then not only that, but there is also like maybe there’s three or four different RouteSet, they are just under a different name space, right? So it’s like foo::RouteSet and also bar::RouteSet. I don’t know the qualified name but that's like what it is. So there is like multiple different ones with the same name and you are like, “Argh!”
CHUCK:
Got to get them all!
AARON:
Yeah.
JOSH:
[chuckles] Collect the whole set.
CHUCK:
That's right.
AARON:
…sit down for a minute like think about the actual words that we need to use and then you know, think about the requirements -- don’t think about the actual words and then split up the objects. I mean, the stuff takes time and especially with an older code base -- legacy code base like this -nobody wants to do it, you know.
CHUCK:
Yeah. It makes sense.
JAMES:
Makes sense.
JOSH:
So new topic, what about this “Matryoshka Doll Caching” stuff?
AARON:
Matryoshka? Yeah, I love those things.
AVDI:
Who doesn’t?
AARON:
I don’t know why we have to have fancy names for everything, like turbo caching or Russian Doll caching. Russian Doll Caching is a fancy name for a compound cache key -- that's all it is.
CHUCK: Oooh.
AARON:
So the basically the cache key [inaudible] it’s a dependency graph of your templates and the cache key is calculated based on that dependency graph.
JOSH:
Wait, we've finally reached the intersection of naming and caching validations being one problem. [laughter]
CHUCK:
Does that make it off by two errors? So, you said that this key -- what I'm wondering is so if you invalidate like the top level thing, do all the other things inside of it also get invalidated? Is that the kind of idea?
JOSH:
That's the other way around.
JAMES:
That's right.
AARON:
Yes. So it’s basically the key is a combination of the current template plus all of its children.
JAMES:
So basically if you, you know if you have a project with to do list and individual todo items and you invalidate one of those items because that's down in the chain, that's going to invalidate that item but it’s also going to invalidate the todo list that held that item, which is going t to invalidate the project that held todo list etc.
CHUCK:
Does it trickle back down to get all the siblings as well?
JAMES:
Well see the siblings are still valid, right? Because if you had a todo list that was 10 items and you changed one, the other 9 can still be pulled from cache. So we don’t want that invalidated.
CHUCK:
So basically, when it builds the new parent, the new parent still has the same key and references to the same children?
AARON:
Basically you need to think of your templates as a tree. So you have one template and you have reference in another template and that other template that references as a child and that one can reference other ones etc. you can have like a graph with these templates. And if the child, if it gets changed then everything back up the tree gets invalidated. The tree will necessarily get invalidated.
CHUCK:
I'm just saying so when something at the middle level gets re-instantiated, it just picks up the old children as it’s children as well that are still—
JAMES:
So basically, it will run back through and re-render itself. So, like the list will have to re-render itself but as it goes to render those ten children, 9 of them will still be cached right? And then the one is a cache miss and therefore the whole template has to be [inaudible] right?
AARON:
It’s good. Like I think it’s a very good thing.
JOSH:
It just seems like the most complicated thing about this feature is explaining it.
CHUCK:
[laughs]
JAMES:
But I think overall its good because it means genuinely speaking, if you start using some caches in your pages and you happen to nest that and stuff, Rails if going to do the right thing by default right? So to me that's good.
AARON:
It’s like I guess I don’t know, compound cache key based on template relationships is not as sexy in name as the Russian Doll Caching.
JAMES:
Which is by the way the name Aaron voted for.
AARON:
[laughs] Actually I had no idea about this feature until it landed and then I looked at it and I was like, “Oh, this isn’t thread safe.” [laughs] OK I guess I have to---.
CHUCK:
So that brings up another issue then is Rails 4.0 thread safe and does it support concurrency nicely?
AARON:
Yes.
JAMES:
Yay!
AARON:
We are removing the thread safe flag because--
JAMES:
I always wondered what thread safe when it was not on you know, it’s like, “OK now I want Rails to behave well but whenever I shut that off, they revert to other code that does this same thing but behaves badly.”
CHUCK:
It’s a placebo. It just makes you feel better.
AARON:
James that was exactly what I thought too. I was like, “This sound like the stupidest flag in the entire world! Why would you have a code path that isn't thread safe?”
JAMES:
[Chuckles] Right.
AVDI:
Why would you ever turn the turbo button off? [laughter]
CHUCK:
Oh, now I feel old.
JOSH:
Because you get terrible mileage with turbo. [laughter]
CHUCK:
They should have linked it to something else.
JOSH:
Takes more lines of code per method.
AARON:
You turn the turbo button off because the game moves too quickly otherwise, right?
JAMES:
Right.
AVDI:
The --- goes too fast.
AARON:
But actually. Let’s see… it’s mainly all that flag did was control code loading -- like basically whether or not your code was equally loaded. And then the only major thing it added was the there's a thing called “Rack::Lock” -- I don't know if you guys have seen that. Basically it’s a thing that takes out a lock before it does a request and then releases the lock at the end of the request.
CHUCK:
I think somebody brought that up at Aloha Ruby.
AARON:
I did. Yes.
CHUCK:
I know I'm just… Anyway.
AARON:
[chuckles] Well it’s like if you have that on and you are using a threaded web server, it means that you can only process one or two requests at a time.
JAMES:
Right.
AARON:
So yeah [inaudible] that thing.
JOSH:
So, is Rack::Lock just gone from the code base now?
AARON:
No. It’s still there for very small case -- which is… OK, alright I have a quiz for you guys, what is the most popular threaded Ruby web server?
JAMES:
That’s a good question.
JOSH:
WEBrick? Oh no WEBrick is not threa… Oh WEBrick! Yeah.
AARON:
Yes! Exactly! WEBrick is the most popular threaded Ruby web server -- except that the problem is nobody knows they are running WEBrick OK? So application up to Heroku and I have taken a survey or anything, this is how I'm guessing these numbers. If you push an app up at Heroku (which I suspect lots of Rubyists have test out or whatever) if you push an app out to Heroku, what web server does it use? It uses WEBrick. It uses whatever like Rails server uses -- which is WEBrick by default.
CHUCK:
Is that why they recommend that you install Thin or whatever if you want that?
AARON:
Yeah exactly. And I think what was happening was people are running WEBrick in production and there were problem with Rails, like Rails wasn’t thread safe.
JAMES:
That’s awesome.
AARON:
Right? So they were running WEBrick and they were going, “What the hell is going on? My application is busted!” and when they figured out the thread safety issues, they just added a lock around the requests, so that you can only process one or a time and now boom, your thread safe issues are gone.
CHUCK:
[laughs]
JAMES:
So when you removed that lock, did you have some thread safe issues that you haven’t resolved? Is that what happened?
AARON:
There were definitely some, but I mean a lot of people -- especially JRuby users – are running threaded web servers, so we fixed a lot of those already.
JAMES:
Right.
AARON:
There are a few with side effects. So I guess like basically the one place we still have Rack::Lock but we only use it if we are using WEBrick in production. And that is basically to be backwards compatible with the people who are running WEBrick on Heroku. [inaudible] running in Heroku are expecting it to do only one request at a time. So we are trying to make sure that those people are… like this is an example of the crazy stuff we have to think about when making a new release in Rails -- is like who is running WEBrick in production? You would think nobody, right? But then you realize that everybody who pushes up [inaudible] without changing their [inaudible] or whatever, they are using WEBrick in production. [chuckles] So we have to think about those people and say like, “Well, we don’t actually wanna break anybody.” Like when we ship a new release of Rails, we don’t want your app to break, right? Despite what happens with the upgrade, we really don’t want your app to break. So we have taken into account crazy situations like these. So basically what will happen is if you are using WEBrick in production, we’ll insert Rack::Lock.
JAMES:
Gotcha. So Aaron what have you worked on the most in Rails 4?
AARON:
Live streaming stuff -- that's most of the work that I've done. Also mainly bug fixes and bug fixes in Rails, some refactoring in action pack and then I guess Ruby 2.0 compatibility, pretty much.
JAMES:
Tell us about the live streaming.
AARON:
I wanted to… stream live. [laughs]
JOSH:
Was these all motivated my salami curing?
AARON:
No. it’s motivated by me being annoyed that you can’t stream data out to clients, from Rails. Like I want to use server-sent events and you have to keep a socket open. And the other thing that annoyed me too is seeing people with NodeJS going, “Oh, look we can [inaudible].” I'm like, “Well, you know, we can do that too.” So I will make it work. That's mainly what motivated me. Server-sent events are what really motivated me the most. I think that is an insanely useful feature.
CHUCK:
Yeah they are pretty cool. All right. Well I think we are running out of time. Are there other things any other aspects of Rails 4 that we wanna dig into?
AARON:
PostgreSQL.
CHUCK:
PostgreSQL.
JAMES:
Yay! JOSH: Yes! PostgreSQL!
AARON:
Like huge, huge changes on the PostgreSQL adapter.
CHUCK:
Does it default to PostgreSQL or is it still SQLite?
AARON:
It defaults the SQLite but--
CHUCK:
I shouldn’t get my hopes up. Anyway.
AARON:
It still uses SQLite by default, but there have been massive improvements to the PostgreSQL adapter so that we can support custom data types in PostgreSQL.
JOSH:
Like UUID -- which is a native a data type. Yay!
CHUCK:
Mh-hmm. And JSON or H-Store, I think both of those going in as well?
AARON:
JSON, H-Store, IP addresses pretty much any PostgresSQL array support -- anything that PostGres can support. Like I refactored the PostGres adapter such that it’s really easy just to add new data type. So it’s like I don’t think we shipped with GIS support, but it’s really easy to add now. Like before, you'd have to do a bunch of crazy monkey patches, but now all you need to do is just say like, “OK register this new data type.”
CHUCK:
That sounds nice. One question that I have about it is let’s say that you have this app and somebody else decides they want to run it on MySQL or something that doesn't have all these features, does it just gracefully fall-back to users strings or you just out of luck?
AARON:
You are out of luck. You are way out of luck. Like there's no way to keep that consistent between databases. I mean you'd have to say like, “OK --- on H-store, work on PostgresSQL.” Well now we got to port that over to MySQL. And also the other thing is like on PostgresSQL, you can do queries by the values in the H-Store, and so which would just be impossible to port through different database.
CHUCK:
This is one of the issues that I've seen or that I've had for a while with is that most of them would just support the lowest common denominator between any of the major engines on the back-end. This is really kind of exciting to see because if you are using PostgresSQL, you can actually use PostgresSQL.
AARON:
Yeah.
JAMES:
So with the PostgresSQL array, you would be able to like assign a Ruby array to the attribute and when you read that back form the database that attribute will be turned in to Ruby array?
AARON:
Yeah. Exactly like as if you are using a serialized column. One thing that is kind of weird is like (I don’t know if we want to get in to this sort of new show on the Ruby Rouges here) but all the keys and values in an H-Store are stored as strings -- so even if you try to dump number or whatever, you will get back string. And the reason is because you can’t differentiate like what’s data actually stored the string literal of “one” versus the number “1”, there's no way for us to differentiate those two, so -- the strings back and I believe that's the same way with PostgreSQL arrays.
JAMES:
Gotcha.
CHUCK:
Yeah, but you could do it -- that's what’s cool!
AARON:
Yes you can.
JAMES:
Yeah it’s really awesome.
AARON:
Pull JSON back out of databases actually really, really awesome.
CHUCK:
Is that your PostgreSQL slogan? “Yes you can”?
AARON:
Yes you can!
CHUCK:
Yes we can!
AARON:
Yeah we use SQLite in dev, but I highly recommend PostgreSQL in production.
JOSH:
That's awesome.
CHUCK:
All right. Anything else that we should know about? Any major changes to APIs? Things that got removed -- anything like that?
AARON:
Let me think… We already went over the test directory changes…
CHUCK:
Is there anything new in Active Record?
AARON:
Not really. I mean, all recurrence relation now -- it’s not like… Well, is everybody there?
JAMES:
We lost Avdi. He’ll come back.
AARON:
As far as Active Record is concerned, there is nothing major. There are small changes that make it a little bit nicer, but nothing like huge to announce besides the pg changes. What else do we have?
Oh, “Strong Parameters” -- we should probably talk about that.
JOSH:
Yes.
AARON:
That's kind of important -- well, I think it’s very important. Strong Parameters lets you… so it’s basically defense against people posting random like… what's the name of that thing in the model?
I can’t remember the name.
JAMES:
Mass Assignment?
AARON:
Yes, Mass Assignment. It’s Mass Assignment protection. And basically, what it is an API for you to say specifically what parameters you accept, right? Like you can say like, “I require that this action takes this [inaudible] parameter and these are the other parameters that are allowed.”
CHUCK:
Is this on the controller?
AARON:
Yeah you do this in the controller. And then you just house that off to the Active Record object.
JOSH:
Now in the lead up to this, I remember there was some modifications made to Mass Assignment protection that involve the use of a named role. Does the Strong Parameters have that same sort of support for particular roles or is that something that is just the controller deals with that?
AARON:
The Strong Parameters is just something that controller deals with. Basically, Active Record will [inaudible] something is allowed and the Strong Paramaters tags thing as allowed. And if Active Record gets something that hasn’t been tagged with allowed, it will override an exception.
CHUCK:
Oh wow. Nice.
JOSH:
It sounds like one of the advantages of this is (from my perspective) is it makes testing a lot easier. I think like a lot of people often run into problems dealing with the Mass Assignment protection in testing where I wanted to be able to set up objects and I was trying to pass in an attribute hash to initialize the object that was some protected parameter -- and that's never fun.
AARON:
And the thing is like what I actually like about the Strong Parameters is its stuff that I've been doing, everybody has been doing this in their controllers anyway. They have been saying like, “These are the parameters that we want.” You are already trying to specify the parameters that you want. And if you are not doing that, you may be vulnerable to an attack, right? Everybody goes through and they look at it and they say, “Well we only wanna accept these particular parameters. Now if somebody is posting like [inaudible] something, we wanna prevent that.” So we are doing these checks, but this is like the nice way to like do the checks. And also if somebody post something that they shouldn't, you get an exception out of it and you don’t have to worry as much.
So I'm actually really happy with that. We also have a “Queuing System”.
CHUCK:
Oh yeah I heard about that.
AARON:
Were still kind of polishing that up. I think it’s actually our last block before we release the beta.
CHUCK:
Yeah. But even still, a common for abstraction queuing is really nice as opposed having to build your own.
AARON:
Yeah. What I'm excited about from that perspective is just basically a common interface to a queuing system. So we can all… if you wanna change from Resque or Sidekiq, all you need to do is… Well I guess they are already compatible anyway. But let’s say you need to change from, I don’t know Resque to AMQP or something like that, then all you need to do is change the backend.
CHUCK:
Or you just pull in another adapter and there you go.
AARON:
And the other thing that I like about it especially is I don’t wanna run… when I'm doing testing, I wanna make sure that I have a server up and running. So in testing, I just use an in-memory queue.
JAMES:
Right. That's awesome.
AARON:
So that's—
JOSH:
With the queuing stuff, is there any support for having a distinguished environment for the background workers? Or is that just something you have to call altogether yourself?
[inaudible] environment for the job?
JOSH:
Yeah. Like having a different environment set up in your gem file, so that if all you’re doing your background job is mocking around with JSON, then--
AARON:
I see what you’re saying. No. I guess we don’t have anything explicitly for that. I mean, it seems easy enough to set up yourself so--
JOSH:
Yeah, sure. I was just curious if there was any sort of move towards establishing conventions around that.
AARON:
No not yet. Not yet.
JOSH:
OK.
AARON:
I can definitely see it happening though -- but you know, not yet.
JAMES:
The great hitting about the queuing API is it begins conversations like this, right? Now we have this queuing thing which has become a standard way to queue. And if you wanna hook in, then you just hook in and then we can’t have conversations about, “Wait, when we are running workers, only be able to turn down all the Rails stuff we don’t need,” or whatever.
AARON:
Yes exactly. Yes it gives us exactly what you are saying James -- it gives us that common like stepping stone to move forward -- like this is a thing that we do. We all queue stuff -- everybody queue stuff up. So let’s just make sure we have a common API for that and now that we moved forward to that stuff, then we can ask the next questions which are, “There need to have an environment thing set up specifically for this,” and just move on.
JAMES:
Well, it sounds like a cool release. We are looking forward to it. When do we get it?
AARON:
We were supposed to get it September. [chuckles] I think supposedly this year. It’s supposed to be… we are planning on having it on this year. I think we have like one block left, so betas should be soon. I'm not total sure. So, soon-ish. How’s that?
JAMES:
Awesome.
JOSH:
Soon-ish sounds great!
Yeah I love the… its real commitment for me. You know, soon-ish. [laughs]
JAMES:
So everyone, if we don’t have it by Christmas, just file a bunch of pool requests for Aaron, you know.
CHUCK:
[laughs] He's getting a whole bunch of pool request that are just incrementing diversion.
JOSH:
Aaron, I do wanna ask one last thing about the drive towards the release and the community participation.
AARON:
OK.
JOSH:
Like it seems like I saw a fairly concerted effort to get people involved in fixing bugs in recent releases. So, has there been that same sort of pitching in an effort around getting for a roll out?
AARON:
[sighs] No, not really. Like, we don’t have a… we don't really… [sighs] I'm trying to think of why we don’t do that and it’s mainly because… I think it’s mainly because we roughly sketch out what features we are going to have. But like for example when we first started talking about Rails 4.0 features, I had no idea that… like we never even talked about like, “Oh, Russian Doll Caching,” for example. That just happened to show up. So it’s really difficult to say like, “Hey community, these are the things we want Rails 4.0. Do them,” Because it just seems I don’t know… it doesn’t seem like there is formal planning around what particular features are in the next--
JAMES:
Right.
AARON:
So if we have …planning, then we can give work -- but we don’t, so this is what happens.
CHUCK:
Is Ruby Core any more or less disciplined than that?
AARON:
Much more disciplined -- absolutely.
AVDI:
So, I have kind of a related question. Every week I pair with somebody on some open source project (and by “somebody” I mean somebody different on some open source project) and a lot of times, there are people who are pretty new to the world of open source, maybe they haven't gotten any commits. And a lot of times, what they wanna work on is they’d really like to get to help Rails out. They like to do some kind of work on Rails. And I'm curious if you could give people to just some pointers for how to find a problem to work on -- a bug or enhancements or whatever -- to work on in Rails if they are just getting started.
So I think the best thing… I have been thinking about this lately because we will work with some students here coming in January and they are going to work on Rails and I need to help them find the best place to start. I think basically it depends on what is your interest is in or what you are most comfortable with. For example, myself, I started with working on Active Record because I love working with databases -- so that's where I dove in. And mainly what you do or what I do is go look at the [inaudible] find one that seemed easy, and then basically try to fix that. Like try to reproduce it and if it was difficult to reproduce, then just move on to another one. And techniques for finding easy ones are like, if they can find a test case or if the ticket is new (because newer tickets are easier than the older tickets) -- besides that I'm not really too sure. Like determining whether or not a ticket is easy is definitely come from experience. I don’t know how to describe that experience.
JAMES:
A lot of times you can tell by the way the ticket is explained you know, if it’s kind of vague, “I have this problem when…” and there's lots of code not related to the when or things like that or if it’s more specific, “When I do this then this happens and here’s is the minimum case that shows it,” you can usually tell if they have isolated the bug for you, you know.
AARON:
The best thing is to find new tickets where they’ve are isolated the bugs like that. But I mean those are kind of hard to find. [chuckles]
JAMES:
Right they are. Yes.
AARON:
I mean, the first thing that you can do is just ask on a ticket. Like, “Hey, can you send us a repro for this bug?” I hear somebody in Scotland, (Scottish Ruby Conference) she wanted to start participating in Rails and basically that's all we did was go through the ticket queue and be like, “Do you have a repro for this? [chuckles] Because most of time, people don't really post repro stuff. They just say like, “I have a bug.”
AVDI:
Hmm.
AARON:
And you are like--
CHUCK:
[laughs]
AARON:
[laughs]
CHUCK:
I'm laughing because I worked --- for a year and yeah we get those all the time.
AARON:
Well I mean like that's the way it is. People need… people might not know they have problems and they don’t know how to fork the problem, so they just need to be taught how to do it and then it’s
fine, right? So the problem is like we just have to teach all these people how to do it. So lot of our time is spent saying, “OK. Hey can you give us a sample application?” But the thing is people need to realize that even asking like… if you come along and find a ticket that is not specific, like they haven’t provided repro steps, even you just asking them for repro steps is a huge help for the Rails team, right? Just commenting on the bugs saying, “Hey, can you provide us with a sample application that shows the behavior,” like that is a huge help. So, basically what we did when we were pairing is we would just go through ask those questions until we actually found one that we could work on then we start working on that. But like what you should do while you are pairing is find… its helpful to have a pair in those situations because you might not know something is difficult. Like I've been pairing with her and we got to a bug and I was like, “Oh man this one is super difficult,” and she didn’t know why it was difficult because they provided a repro, but it depended on so much code and so much history, that explaining why this is… the problem with the new ones that I've seen. And that is why I think pairing was an experience person was like a good thing.
AVDI:
Have you ever thought of like a tag that people can put on tickets that might be easier for a noob to tackle?
AARON:
Yeah. We have been talking about that there other day because I mean I'm facing these problems that I need to be able to split up tickets for new people. We are going to start tagging them with I think will BM will be it and it stands of like Bob Mash. Because it will be--
JOSH:
[chuckles]
CHUCK:
You know that BM traditionally stands for something else, right? [laughter]
JAMES:
An unfortunate acronym.
AARON:
Oh no! [laughs] You know what… OK. Yes you’re right. [laughter]
CHUCK:
All right. Well, yeah.
JAMES:
We just saved Aaron from potentially stepping in poop. [laughter]
CHUCK:
All right. Well, shall we get to the picks? Is there something else you wanted to say Aaron?
AARON:
Yeah. I wanna say Happy Thanksgiving to everybody!
JAMES:
Yay!
CHUCK:
Happy Thanksgiving -- it’s tomorrow for us and it was last week for you.
JOSH:
And for many people listening, they'll have to come to America to enjoy our Turkey Fest. Sorry.
JAMES:
I'm working with a German company right now and they are all, “So Thursday we thought we’d do this big thing.”
AVDI:
[laughs]
JAMES:
And it’s like, “That’s not a good day for me.”
CHUCK:
Yeah. I emailed the team I’m working with. They are in the US and I was like, “So you are not going to see me for a few days. Call me if there is an emergency.”
AARON:
I had a week off and I've been just playing video games all day. That was super nice.
CHUCK:
That's good for you. Of course all day until it’s what… a few hours?
AARON:
No. Like 8 am until… sleep time? I don't know. [chuckles]
CHUCK:
Nice.
AVDI:
Awesome.
AARON:
Although I actually just… I was playing Borderlands 2 and I just finished it, so I need to find something new I think.
JOSH:
Maybe on our picks you’ll find something.
CHUCK:
[laughs] Is that a little foreshadowing?
AARON:
Yes and pick me last. I'm still trying to think of a pick.
JAMES:
[laughs] Aaron: “I got to go search.”
AARON:
[laughs]
CHUCK:
OK my picks will be the ones that I wanted to pick and Aaron.
AARON:
[laughs]
CHUCK:
All right. Well, let’s do the picks then. Avdi, do you want a go first?
AVDI:
Sure. Let’s see. Technical pick, (I don’t think I've picked this before) there is a gem called Squeel (S-Q-U-E-E-L) and it puts… it adds a lot of niceties in doing SQL queries to Active Record. So, basically it adds stuff where instead of passing just parameters to where you can pass a blocked-and a block can basically just have Ruby code in it that compares things to each other using equals or lesser than or various other operators and Squeel takes that and turns that into SQL. And it works really, really, well. It’s so nice for building up queries. It goes well beyond just that little bit of turning Ruby into SQL, but also makes it a lot easier to deal with joins and sub queries, and basically makes some things possible that are if not impossible, then really hard in just like base Active Record in arel. Like doing non… doing less common types of joins, oring together two different result sets and stuff like that -- without actually getting the results and putting them together in memory actually turning it into a composite query that does the right thing in SQL. I've been getting a lot of use out of it on one project I'm working on for a client and it’s been a huge, huge help. And another thing I've been getting a lot of use out of is Bulleit Bourbon. It’s better than the cheap stuff and it’s better than the best stuff. It’s become kind of my go-to every day bourbon.
B-U-L-L-E-I-T I think is the spelling.
CHUCK:
Awesome. Josh, what are your picks?
JOSH:
I'm just going to do one pick this week. We are coming up on a holiday giving season and holidays can be very emotionally difficult for many people -- especially gay youth who are trying to deal with family when family is one of the biggest emotional challenges for them. So there is an organization called The Trevor Project, which is supporting gay, lesbian, transsexual etc. youth and provides them counselling and support services to try and prevent youth suicide -- which is actually a really big deal. I think gay youth committing suicide is about three times the rate of straight youths. So it’s a big deal. the Trevor project has a much more dashing celebrity spokesperson in the person of Daniel Radcliff (Mr Harry Potter). It’s a real charity and I think it’s worth some donations -especially if you want to be helping out your young relatives who may be potentially dealing with all their family’s angst this season. So that's my pick.
CHUCK:
Awesome. That's great. I think there's a lot of angst over gay issues or not, but honestly if you could help people out, I think you should. So even if you… no matter how you feel, getting to a project like this is a good thing.
JOSH:
Yeah, well said.
CHUCK:
James, what are your picks?
JAMES:
I got just a couple of quick ones. First of all, the Pragmatic Programmers finally had I guess the rights to realise their original book -- The Pragmatic Programmer -- as an eBook on their own site. Which is awesome because it was originally published by someone else they just didn’t have it. This to me is one of the classic, all-time great books of programming and so many thing that we just take for granted like dry and fix broken windows and things like that come out of this. So if you haven't read it, it’s a great excuse to grab it and read it now -- or if you have read it, it’s a great excuse to grab it and read it again [chuckles] because it’s kind of one of those timeless programming books that's always great. So I think that's cool that they finally got that and that is more accessible to us now -- which is awesome.
AARON:
… my questions of the mysteries of the universe is why Pragmatic Programmers didn't publish that book.
JAMES:
Yeah I think they actually formed their company after they made that.
AVDI:
Yes.
CHUCK:
Yeah I was going to say they originally published with Addison-Wesley and I think they probably had to negotiate something with them in order to do that.
JAMES:
Right. So yeah, they didn’t own the rights to it. So yeah, I'm so glad to see that now. Two, as we've said its holiday season and we are going to be doing gifts and stuff. A lot of people exchange gifts this time of year. I've been looking for a cool interesting toys for my kid (because I have a kid now) and I found Wired had a pretty neat article called Tech Toys for Kids, From Tots to Teens. It just had some neat toys in there that I wasn’t totally aware of and I never would have known that Furby was back or things like that. But aside from you know, stuff like that, there is kind of some unusual things in here like these almost origami-like kits that you can use to make critters and stuff. Anyways, those are a couple of neat ideas that I got into while I was doing an online Christmas shopping the other day so I thought other parents might want to look at them. That's it. Those are my picks.
CHUCK:
Great. Well I'll go next because I told Aaron he'll go last. My first pick is… I was doing some coaching the other day and the guys I was doing the coaching with pulled in a couple of gems that I hadn’t seen before. One of them was called rolify. It’s R-O-L-I-F-Y. And it’s kind of a neat DSL… It provides a neat DSL for defending roles and applying those roles to objects. So it’s not just user that have a roll, but it’s a user that has a roll scoped to a particular object or set of objects. And it looked kind of cool, so I'm going to pick that. I'll put a link in the show notes. The other one that I wanna pick -- if you are curious about Rails 4 and you want to see a really good talk about – is actually Aaron’s talk at Aloha Ruby. And it’s not that long -- standard length for a talk I guess. But he goes over a lot of stuff that we talked about -- some of it in more detail and some of it in less -but I think it will clarify some of the stuff if you just want exposure to it again after listening to our show. Aaron, what are your picks?
AARON:
I pick my nose. [laughter]
JOSH:
Good thing it’s a podcast and not TV.
JAMES:
Geez, yeah.
AARON:
[laughs] OK let’s see. I don’t know if I picked this one before but I would pick ScreenFlow. You guys ever used that?
JAMES:
Yeah, it’s great.
CHUCK:
Yes.
AARON:
That is my favorite video making program ever. It’s the best. And then also I wanna pick like lately I've been playing with embedded systems and I would like to pick the BeagleBone, which is, it’s similar to… oh what is the other one… the Raspberry Pi. It’s just an embedded system that runs Embedded Linux, but the BeagleBone is by IT. It has an ARM processor. And what's kind of cool is it has like the footprint is an Altoid's tin -- it’s the size of an Altoid's tin. You put it in Altoid's tin if you want to. But I've been using that to control my salami box. And [inaudible] Ethernet cable, has USB host port, so you can like plug in peripherals if you want to. But it’s just totally fun. Like you can SSH and do any type of Linux stuff if you want. Like I'm running Ruby on it now -- it’s a lot of fun so yeah.
CHUCK:
Awesome. OK. Well I think that's it. So we'll wrap the show up. Thanks for coming again Aaron.
AARON:
Yeah you’re welcome.
AVDI:
Thanks a lot.
CHUCK:
It’s always fun to have you on the show. We really appreciate your expertise and your fun personality.
AARON:
Thank you. I really appreciate it.
CHUCK:
All right. Well I guess we'll wrap up the show. We'll catch you all next week and enjoy the holidays!
JAMES:
Bye.
AARON:
OK. Bye!