WEBVTT 00:00:17.060 --> 00:00:18.180 ERNIE MILLER: Good afternoon everybody. 00:00:18.180 --> 00:00:18.820 AUDIENCE: Good afternoon. 00:00:18.820 --> 00:00:19.580 E.M.: How's it going? 00:00:19.580 --> 00:00:21.360 AUDIENCE: It's going good! Hi Ernie! 00:00:21.360 --> 00:00:23.420 E.M.: Hi. My name's Ernie Miller. I work for 00:00:23.430 --> 00:00:26.250 a company called Appriss in Louisville, Kentucky. Please ask 00:00:26.250 --> 00:00:28.800 me about them later so that I can justify 00:00:28.800 --> 00:00:30.289 expensing the trip. 00:00:30.289 --> 00:00:31.750 AUDIENCE: Whoo! 00:00:31.750 --> 00:00:32.479 [applause] 00:00:32.479 --> 00:00:34.940 E.M.: If I could ask you all to do 00:00:34.940 --> 00:00:38.370 me a favor, as it turns out, most of 00:00:38.370 --> 00:00:41.370 my fellow co-workers that had come out to RailsConf 00:00:41.370 --> 00:00:44.170 have had to catch a flight to go back 00:00:44.170 --> 00:00:45.739 home, and so they're missing my talk. And so 00:00:45.739 --> 00:00:47.809 what I'd like you to do is to Tweet 00:00:47.809 --> 00:00:50.739 very enthusiastically about the talk, regardless of if it's 00:00:50.739 --> 00:00:52.430 very good, so that, you know, for at least 00:00:52.430 --> 00:00:53.909 until it goes on video, they're gonna think they 00:00:53.909 --> 00:00:56.129 missed the talk of a lifetime. 00:00:56.129 --> 00:00:59.729 So, RailsConf, huh? Have you guys had a good 00:00:59.729 --> 00:01:00.229 times? 00:01:00.229 --> 00:01:01.220 AUDIENCE: Whoo! 00:01:01.220 --> 00:01:01.720 [applause] 00:01:01.720 --> 00:01:03.210 E.M.: Yeah? Yeah. 00:01:03.210 --> 00:01:07.689 I've had a ball, too. I've had a ball, 00:01:07.689 --> 00:01:08.189 too. 00:01:08.189 --> 00:01:08.680 So. 00:01:08.680 --> 00:01:10.180 AUDIENCE: Ah, yeah! 00:01:10.180 --> 00:01:11.360 E.M.: I am not. 00:01:11.360 --> 00:01:12.530 AUDIENCE: [indecipherable - 00:01:10] 00:01:12.530 --> 00:01:14.869 E.M.: Yes. Yes it was. 00:01:14.869 --> 00:01:19.670 So, I am not a member of Ruby core. 00:01:19.670 --> 00:01:25.259 I am not a member of Rails core. However, 00:01:25.259 --> 00:01:27.850 last month, this game came out, and I'm an 00:01:27.850 --> 00:01:31.710 avid gamer, and I'd like to happily report that 00:01:31.710 --> 00:01:34.590 I am very frequently a member of Damage core, 00:01:34.590 --> 00:01:36.780 at this point. 00:01:36.780 --> 00:01:40.710 Unfortunately, membership only lasts for about fifteen seconds at 00:01:40.710 --> 00:01:42.939 a time. Then I get booted again. So, so 00:01:42.939 --> 00:01:46.460 there is that. But, you know, I'm thinking, you 00:01:46.460 --> 00:01:48.060 know, it's, it's moving up in the world. I'm 00:01:48.060 --> 00:01:50.429 a member of something core. 00:01:50.429 --> 00:01:54.829 So, so, it's come to my attention recently that 00:01:54.829 --> 00:01:57.299 I have been giving a fair number of talks 00:01:57.299 --> 00:01:59.709 that usually involve me ranting about something, and I 00:01:59.709 --> 00:02:01.770 think I'm becoming a bit of a curmudgeon. 00:02:01.770 --> 00:02:02.350 [applause] 00:02:02.350 --> 00:02:06.990 So, you're not supposed to clap for that. 00:02:06.990 --> 00:02:07.569 [laughter] 00:02:07.569 --> 00:02:09.740 OK. So, one of the things that I want 00:02:09.740 --> 00:02:11.569 to start off by doing is saying that I 00:02:11.569 --> 00:02:13.880 recognize that most of us would not be in 00:02:13.880 --> 00:02:17.000 this room if it weren't for Rails, and that 00:02:17.000 --> 00:02:20.090 we really owe a lot of our opportunity to 00:02:20.090 --> 00:02:22.250 get paid for doing Ruby, I know I do 00:02:22.250 --> 00:02:26.580 anyway, to Rails's existence. So, first off, I'd like 00:02:26.580 --> 00:02:28.890 to get a hand for Rails and how awesome 00:02:28.890 --> 00:02:30.239 it is and how it enables us to do 00:02:30.239 --> 00:02:31.140 everything. 00:02:31.140 --> 00:02:32.049 [applause] 00:02:32.049 --> 00:02:36.450 OK. OK. Nope. Nope. That's enough. Nope. No more. 00:02:36.450 --> 00:02:36.989 We're done celebrating. 00:02:36.989 --> 00:02:37.180 [laughter] 00:02:37.180 --> 00:02:39.530 Just that much celebration. Nothing more. 00:02:39.530 --> 00:02:40.280 [laughter] 00:02:40.280 --> 00:02:43.459 OK. All right. Stop the part. 00:02:43.459 --> 00:02:47.799 So. That. That gets me every time. 00:02:47.799 --> 00:02:50.439 So, that being the case, I, I have to 00:02:50.439 --> 00:02:54.400 say, a lot of us have been hitting brick 00:02:54.400 --> 00:02:57.180 walls. How many of you have been building something 00:02:57.180 --> 00:02:59.659 relatively complex with Rails, and you sort of feel 00:02:59.659 --> 00:03:02.269 like you've, you've gone up against a brick wall. 00:03:02.269 --> 00:03:04.579 You can't make anymore forward progress and you feel 00:03:04.579 --> 00:03:07.090 like you've been kind of, you know, so- yeah, 00:03:07.090 --> 00:03:08.970 OK. So some hands are going up right. 00:03:08.970 --> 00:03:12.209 And, and, and so it seems to me, like, 00:03:12.209 --> 00:03:14.930 if there is that much talk about it, you 00:03:14.930 --> 00:03:16.930 know, it seems like we often get the response 00:03:16.930 --> 00:03:18.769 that, you know, we just need to run with 00:03:18.769 --> 00:03:22.989 more passion at the wall. Run faster. And, and 00:03:22.989 --> 00:03:26.540 if we just fully commit that we'll burst through 00:03:26.540 --> 00:03:28.319 and we'll be in this sort of magical land 00:03:28.319 --> 00:03:31.890 where everything works the way that it's supposed to, 00:03:31.890 --> 00:03:34.319 and just don't fight so much, right? 00:03:34.319 --> 00:03:37.780 I have to think that if so many of 00:03:37.780 --> 00:03:39.590 us have kind of run into these sort of 00:03:39.590 --> 00:03:43.730 problems, that maybe there's something there. Maybe there's, there's 00:03:43.730 --> 00:03:44.939 some kind of an issue there, and I wanted 00:03:44.939 --> 00:03:47.939 to give a few opinions about, you know, why 00:03:47.939 --> 00:03:49.290 that might be. 00:03:49.290 --> 00:03:54.900 So, Rails is a convention over configuration advocate, right. 00:03:54.900 --> 00:03:56.900 That's, that's the big thing that we always talk 00:03:56.900 --> 00:03:59.299 about, that we would prefer to have convention over 00:03:59.299 --> 00:04:04.400 configuration. Now, conventions are really what, what opinions want 00:04:04.400 --> 00:04:07.230 to be when they grow up, right. So, most 00:04:07.230 --> 00:04:09.670 conventions have stemmed from an opinion. We hopefully share 00:04:09.670 --> 00:04:13.819 the opinion, but I want to be clear that, 00:04:13.819 --> 00:04:16.279 when I talk about the opinions that Rails has 00:04:16.279 --> 00:04:19.410 today, I am not talking specifically about any members 00:04:19.410 --> 00:04:21.329 of the core team. I'm not talking about the 00:04:21.329 --> 00:04:24.810 people, though the software may in fact reflect opinions 00:04:24.810 --> 00:04:26.640 of people, what I want to talk about is 00:04:26.640 --> 00:04:28.780 what does the software tell us, right? 00:04:28.780 --> 00:04:32.570 Because we know that Rails is opinionated software. So, 00:04:32.570 --> 00:04:35.220 with that out of the way, let's go with 00:04:35.220 --> 00:04:38.130 the first opinion that Rails, Rails has, that I 00:04:38.130 --> 00:04:40.650 believe Rails has anyway, which is that code should 00:04:40.650 --> 00:04:45.350 read like English. And we see this pretty frequently 00:04:45.350 --> 00:04:49.870 in comparisons between straight-up Ruby versus Rails kind of 00:04:49.870 --> 00:04:50.840 code, right, so. 00:04:50.840 --> 00:04:52.630 Here's something that a lot of us actually like. 00:04:52.630 --> 00:04:53.680 Like, I know this is one of the things 00:04:53.680 --> 00:04:55.569 that hooked me on Rails right off the bat, 00:04:55.569 --> 00:04:57.280 was like, oh, I can say, like, five dot 00:04:57.280 --> 00:05:00.699 days ago, or, you know, because I'm writing something 00:05:00.699 --> 00:05:03.430 in old English, I can say one dot fortnight.from_now. 00:05:03.430 --> 00:05:09.139 That's very useful. Right. 00:05:09.139 --> 00:05:11.550 So there's nothing particular, when we say like, one 00:05:11.550 --> 00:05:14.389 dot megabyte, right, there's, there's nothing megabyte-y about the 00:05:14.389 --> 00:05:17.740 number, right. It just does some multiplication. 00:05:17.740 --> 00:05:23.030 Similarly, we have some, oh yeah. Fortnight. Yeah. Similarly, 00:05:23.030 --> 00:05:26.990 we have some differences where we have something that 00:05:26.990 --> 00:05:29.800 array already has, for instance, on it, like the 00:05:29.800 --> 00:05:31.449 sh- I just found out it's called the shovel 00:05:31.449 --> 00:05:33.400 operator. I always just said less than less than, 00:05:33.400 --> 00:05:35.449 but whatever it is, right. So we have, like, 00:05:35.449 --> 00:05:38.090 array less than less than object, right, and we've, 00:05:38.090 --> 00:05:40.080 we've got that alias to append, so that we 00:05:40.080 --> 00:05:41.830 can say append. 00:05:41.830 --> 00:05:44.120 We have object dot in, so we can ask 00:05:44.120 --> 00:05:45.750 whether an object is in an array include of 00:05:45.750 --> 00:05:47.770 ask an array whether it has an object. Things 00:05:47.770 --> 00:05:49.550 like that. 00:05:49.550 --> 00:05:53.789 We have string methods that have been, you know, 00:05:53.789 --> 00:05:56.910 kind of patched in for, for instance, the string 00:05:56.910 --> 00:05:58.389 inquirer. That's one of my, one of my favorite 00:05:58.389 --> 00:06:00.520 ones. Right in the middle there, we have a 00:06:00.520 --> 00:06:02.470 check on the left. In Ruby, you simply ask 00:06:02.470 --> 00:06:06.120 if the environment string equals production. But in Rails, 00:06:06.120 --> 00:06:08.750 there's a thing called a string inquirer, which simply 00:06:08.750 --> 00:06:13.259 patches method_missing so that you can actually say, OK. 00:06:13.259 --> 00:06:16.240 Is the string actually containing the method that you 00:06:16.240 --> 00:06:18.919 just sent minus the question mark? And so, that's 00:06:18.919 --> 00:06:21.370 really all its doing - the thing on the 00:06:21.370 --> 00:06:22.669 left. 00:06:22.669 --> 00:06:26.960 Here's another one. So, in time, we can say 00:06:26.960 --> 00:06:30.419 beginning_of_day, we can say midnight, we can sat at_midnight, 00:06:30.419 --> 00:06:33.930 we can say at_beginning_of_day. We can say midday, noon, 00:06:33.930 --> 00:06:37.259 at_midday, at_noon, at_middle_of_day, right. They're all the same thing, 00:06:37.259 --> 00:06:41.979 and yet there's this really clean API that's exposed 00:06:41.979 --> 00:06:44.690 this whole change thing, right. It's fairly discoverable. Like, 00:06:44.690 --> 00:06:46.889 I could make a reasonable guess that if I 00:06:46.889 --> 00:06:49.569 said change_minute to something, or if I said change 00:06:49.569 --> 00:06:52.479 any piece of the time to something, it would 00:06:52.479 --> 00:06:55.069 be able to do exactly what I ask it 00:06:55.069 --> 00:06:57.370 to do just then. But instead we have these, 00:06:57.370 --> 00:07:00.020 these aliases that allow us to write code that's 00:07:00.020 --> 00:07:00.860 like English. 00:07:00.860 --> 00:07:03.669 Now, when I go into a coffee shop and 00:07:03.669 --> 00:07:05.199 I want something that's got a high caffeine content, 00:07:05.199 --> 00:07:07.400 I may order one of these. You all know 00:07:07.400 --> 00:07:10.220 what this is, right. This is coffee brewed by 00:07:10.220 --> 00:07:12.069 forcing a small amount of nearly boiling water under 00:07:12.069 --> 00:07:14.580 pressure through finely ground coffee beans. And that's what 00:07:14.580 --> 00:07:16.069 I go up to the counter and ask for, 00:07:16.069 --> 00:07:16.430 right. 00:07:16.430 --> 00:07:18.949 Nope. You know. They'd probably go, you mean an 00:07:18.949 --> 00:07:24.039 espresso, right? Because espresso is what we call a 00:07:24.039 --> 00:07:28.800 loan word. We borrowed that word from Italian because 00:07:28.800 --> 00:07:30.940 it was concise, it was a good way to 00:07:30.940 --> 00:07:33.789 say what it was that, that we wanted to 00:07:33.789 --> 00:07:36.069 say without all of those words, right. 00:07:36.069 --> 00:07:40.129 Ruby is a language in-and-of-itself. It borrows from English 00:07:40.129 --> 00:07:42.919 where it makes sense. But it is my opinion, 00:07:42.919 --> 00:07:44.690 anyway, that if there is a concise way to 00:07:44.690 --> 00:07:47.190 say something in Ruby, we don't necessarily need to 00:07:47.190 --> 00:07:49.500 borrow a loan word in English. You know how 00:07:49.500 --> 00:07:51.319 you sit across the table from that guy who 00:07:51.319 --> 00:07:53.440 always like to use a foreign word for something 00:07:53.440 --> 00:07:57.139 just to sound clever, right? Right. That's what we're 00:07:57.139 --> 00:08:00.470 doing, right. Like, it doesn't make a lot of 00:08:00.470 --> 00:08:00.789 sense. 00:08:00.789 --> 00:08:03.759 Now, here's one you may initially disagree with. I 00:08:03.759 --> 00:08:06.479 believe that Rails believes that models descend from ActiveRecord, 00:08:06.479 --> 00:08:09.870 or at the very least an ORM. Now, if 00:08:09.870 --> 00:08:12.300 you disagree with me, I have three words for 00:08:12.300 --> 00:08:17.289 you. Rails generate model. 00:08:17.289 --> 00:08:20.340 What do you get? You get an ActiveRecord subclass, 00:08:20.340 --> 00:08:23.259 right. Now, you might say, well that's silly, right. 00:08:23.259 --> 00:08:26.319 But this is the first exposure that Rails developers 00:08:26.319 --> 00:08:28.610 are likely to have to what goes in a 00:08:28.610 --> 00:08:31.199 model's directory, and I have talked to extremely smart 00:08:31.199 --> 00:08:34.030 developers who have told me that they went a 00:08:34.030 --> 00:08:36.679 number of years before they realized they could stick 00:08:36.679 --> 00:08:39.820 plain-old Ruby classes in app models, because they just 00:08:39.820 --> 00:08:42.679 thought that, that's not what models are. Right? 00:08:42.679 --> 00:08:45.280 And so, rightfully so then, Rails believes that the 00:08:45.280 --> 00:08:47.990 data is the domain, right. That's the ActiveRecord pattern. 00:08:47.990 --> 00:08:50.230 That's the whole point of it. And if you 00:08:50.230 --> 00:08:52.450 don't believe me, I'll show you some README information, 00:08:52.450 --> 00:08:53.170 right. 00:08:53.170 --> 00:08:55.990 The prime directive is that we're minimizing the code 00:08:55.990 --> 00:08:59.820 needed to build a real-world domain model. Lots of 00:08:59.820 --> 00:09:03.060 reflection and runtime extension is the understatement of the 00:09:03.060 --> 00:09:10.060 year. And magic is not inherently a bad word. 00:09:10.269 --> 00:09:13.690 Now, what this really comes down to is, is 00:09:13.690 --> 00:09:18.329 Rails was very much a reaction to very configuration-heavy 00:09:18.329 --> 00:09:24.130 frameworks in Java, XML files and the like. Big 00:09:24.130 --> 00:09:26.779 reaction to that, right. So what we had determined 00:09:26.779 --> 00:09:29.510 at that point was that configuration is the devil, 00:09:29.510 --> 00:09:33.640 right. And once you have, once you have determined 00:09:33.640 --> 00:09:35.779 that there is a greater evil out there, then 00:09:35.779 --> 00:09:38.010 a lot of lesser evils start to seem pretty 00:09:38.010 --> 00:09:41.089 great by comparison, right. So you can rationalize yourself 00:09:41.089 --> 00:09:43.760 into a really tricky spot. 00:09:43.760 --> 00:09:46.930 And so, our goal is to be able to 00:09:46.930 --> 00:09:50.600 write class Post inherits from ActiveRecord::Base end and have 00:09:50.600 --> 00:09:54.640 magic happen, right. Like, for instance, we infer, and 00:09:54.640 --> 00:09:56.190 I want to talk a little about, about one 00:09:56.190 --> 00:09:58.630 thing that we do in that case, right. We 00:09:58.630 --> 00:10:02.829 infer what the attributes should be on that, on 00:10:02.829 --> 00:10:05.170 that model without writing a single line of code. 00:10:05.170 --> 00:10:08.050 Now, there's a problem with that. Namely, that in 00:10:08.050 --> 00:10:10.149 order to infer the attribute names, you must first 00:10:10.149 --> 00:10:13.140 invent the universe. So I want to walk us 00:10:13.140 --> 00:10:17.279 through what that looks like. We're gonna do one 00:10:17.279 --> 00:10:19.360 deep dive into some Rails internals, and then I 00:10:19.360 --> 00:10:21.399 promise we'll come back up for air and we'll, 00:10:21.399 --> 00:10:24.630 we'll talk about happy things. 00:10:24.630 --> 00:10:28.740 So, so you might imagine pretty, pretty early on, 00:10:28.740 --> 00:10:32.740 that we're gonna go ahead and initialize a module, 00:10:32.740 --> 00:10:34.680 and we're gonna actually have a module to store 00:10:34.680 --> 00:10:36.920 our attribute methods in. That's actually something I kind 00:10:36.920 --> 00:10:39.529 of like, right, because as a Rubyist, I expect 00:10:39.529 --> 00:10:40.910 to be able to call super if I define 00:10:40.910 --> 00:10:42.399 my own method on the class, so that makes 00:10:42.399 --> 00:10:43.920 a lot of sense, right. 00:10:43.920 --> 00:10:45.050 So if we look at what happens when we 00:10:45.050 --> 00:10:47.649 generate the module, we have a new anonymous module 00:10:47.649 --> 00:10:50.040 that extends Mutex, cause we don't want to be 00:10:50.040 --> 00:10:53.070 modifying the module from two different threads. 00:10:53.070 --> 00:10:56.440 And, then in method_missing, we have this handy little 00:10:56.440 --> 00:11:02.029 hook that defines the attribute methods, right. And so, 00:11:02.029 --> 00:11:06.480 in method_missing, we call this every single time, right. 00:11:06.480 --> 00:11:09.290 And the idea being that once we've defined the 00:11:09.290 --> 00:11:10.829 methods, they're, we're not gonna hit method_missing, at least 00:11:10.829 --> 00:11:13.660 for those methods anymore. 00:11:13.660 --> 00:11:15.320 And so we bail out, if, in fact, we've 00:11:15.320 --> 00:11:21.110 already generated them. And we call super with column 00:11:21.110 --> 00:11:23.980 names, right. Now, where do we get column names 00:11:23.980 --> 00:11:26.750 from? Well, it's not there. In fact, method_missing was 00:11:26.750 --> 00:11:29.740 the only thing that actually sits on, on the 00:11:29.740 --> 00:11:31.529 instance level. The rest of the stuff that we're 00:11:31.529 --> 00:11:33.310 gonna be looking at sits on the singleton. It 00:11:33.310 --> 00:11:36.300 sits on the subclass of ActiveRecord itself as a 00:11:36.300 --> 00:11:37.430 class method. 00:11:37.430 --> 00:11:41.149 So, when we call super, we're actually calling super 00:11:41.149 --> 00:11:45.269 into ActiveModels. Definition of defining attributes, right. So we're 00:11:45.269 --> 00:11:47.600 saying, define attributes methods from ActiveModel. We're passing it 00:11:47.600 --> 00:11:50.860 the column names. So here's column names. Well, column 00:11:50.860 --> 00:11:54.610 names is, again, a singleton method. It knows that 00:11:54.610 --> 00:11:57.649 it needs columns, right. And below here, we have 00:11:57.649 --> 00:11:58.459 columns. 00:11:58.459 --> 00:12:01.889 Well, columns needs the connections, for starters, to the 00:12:01.889 --> 00:12:03.540 database to talk, to figure out, you know, what 00:12:03.540 --> 00:12:05.360 table it's gonna read from. And it also needs 00:12:05.360 --> 00:12:08.160 to determine table name, right. So now we need 00:12:08.160 --> 00:12:11.470 to know the table name. So we don't have 00:12:11.470 --> 00:12:13.620 the table name yet, so we call a reset 00:12:13.620 --> 00:12:18.480 table name, and most of the time I'm gonna 00:12:18.480 --> 00:12:20.529 skip past some of the, some of the more 00:12:20.529 --> 00:12:22.760 convoluted things and just talk about the compute table 00:12:22.760 --> 00:12:24.300 name, right. So we have to compute the table 00:12:24.300 --> 00:12:27.370 name. It makes sense, right? 00:12:27.370 --> 00:12:29.480 So, this is kind of a big method. Hopefully 00:12:29.480 --> 00:12:31.339 you all can see the, the part that matters, 00:12:31.339 --> 00:12:35.600 which is we call undecorated table name with the, 00:12:35.600 --> 00:12:37.760 again, we're sitting on the class. So name refers 00:12:37.760 --> 00:12:39.839 to class dot name, right. The string name of 00:12:39.839 --> 00:12:43.279 the class. The full module name. 00:12:43.279 --> 00:12:47.350 And, undecorated table name basically does exactly what you 00:12:47.350 --> 00:12:50.320 see here. Let's say we have a namespace model, 00:12:50.320 --> 00:12:54.740 Conferences::RailsConf becomes RailsConf becomes rails underscore conf becomes rails_confs, 00:12:54.740 --> 00:12:59.130 OK. Which is great. And then, of course, if 00:12:59.130 --> 00:13:01.320 we have Animals::Moose it becomes Moose it becomes moose 00:13:01.320 --> 00:13:05.360 it becomes mooses. Which makes lots of sense, right? 00:13:05.360 --> 00:13:12.130 Well, that means we need to handle irregular pluralization. 00:13:12.130 --> 00:13:14.170 So we check and we see whether or not 00:13:14.170 --> 00:13:18.940 there's a default pluralization to find for moose. There 00:13:18.940 --> 00:13:21.209 is not. There, there, there are some interesting ones, 00:13:21.209 --> 00:13:23.589 I think. We've got, like, sheep. We do have 00:13:23.589 --> 00:13:27.600 sheep, so we're at least in the ball park. 00:13:27.600 --> 00:13:30.769 We have jeans. We have fish. But we don't 00:13:30.769 --> 00:13:32.209 have moose. 00:13:32.209 --> 00:13:36.110 So, we go into an initializer and we set 00:13:36.110 --> 00:13:43.110 inflect.uncountable "moose" and then it works, right. But. Configuration. 00:13:43.649 --> 00:13:46.220 Or we can say self dot table_name equal 'moose' 00:13:46.220 --> 00:13:50.070 and then bypass all of that altogether, right. But, 00:13:50.070 --> 00:13:51.880 again, configuration. 00:13:51.880 --> 00:13:54.540 Now, if configuration is the devil and magic is 00:13:54.540 --> 00:13:58.529 the goal, then we have to think to ourselves, 00:13:58.529 --> 00:14:00.790 what is, what is magic, really? And, and an 00:14:00.790 --> 00:14:06.070 enjoyable magic trick is basically willful suspension of disbelief, 00:14:06.070 --> 00:14:09.459 right. So, that is, if this magician came up 00:14:09.459 --> 00:14:11.880 and said, I'm going to saw my assistant in 00:14:11.880 --> 00:14:14.519 half, and you didn't think, there's a trick here, 00:14:14.519 --> 00:14:17.009 like, it's based in the rules of reality, like, 00:14:17.009 --> 00:14:19.149 there's something going on. It would be pretty horrified, 00:14:19.149 --> 00:14:21.880 right. We'd be like, I don't be- where have 00:14:21.880 --> 00:14:24.480 I gone? Like, what is going on here, right? 00:14:24.480 --> 00:14:27.269 And so there is this level where we would 00:14:27.269 --> 00:14:29.970 do better to consider, how can we root this 00:14:29.970 --> 00:14:32.630 kind of magic in some reality that the average 00:14:32.630 --> 00:14:35.220 person is going to be able to understand? And 00:14:35.220 --> 00:14:37.509 then kind of build on that knowledge, sort of 00:14:37.509 --> 00:14:39.740 scaffold, if you will. And, otherwise, you end up 00:14:39.740 --> 00:14:41.720 with what I, what I referred to as douche 00:14:41.720 --> 00:14:44.310 bag magic, which magic that bites you, magic that 00:14:44.310 --> 00:14:47.070 screws you over in all sorts of wonderful ways. 00:14:47.070 --> 00:14:51.540 So, let's imagine, for a moment, a world, a 00:14:51.540 --> 00:14:55.060 world where we do have magic that we can 00:14:55.060 --> 00:15:01.250 understand. And, so let's just say we have ImaginaryRecord::Record 00:15:01.250 --> 00:15:04.600 that always asks us to configure a table name. 00:15:04.600 --> 00:15:07.389 That always asks us to define the attributes in 00:15:07.389 --> 00:15:10.820 a very mapper style, data mapper style. Right? 00:15:10.820 --> 00:15:12.980 Given an attribute name, tell it's how its to 00:15:12.980 --> 00:15:14.019 load the attributes. Tell it how to load the 00:15:14.019 --> 00:15:15.449 attributes. Maybe some other stuff. We don't, we're just, 00:15:15.449 --> 00:15:18.529 we're imagining here, right. We're, we're just in your 00:15:18.529 --> 00:15:20.019 imagination. 00:15:20.019 --> 00:15:22.630 And then let's say that we have a MagicRecord 00:15:22.630 --> 00:15:26.480 that inherits from the ImaginaryRecord::Record, and does all the 00:15:26.480 --> 00:15:30.880 same stuff that we did before, except it calls 00:15:30.880 --> 00:15:34.230 these methods on the class in order to set 00:15:34.230 --> 00:15:36.339 the table name programmatically, in order to set the 00:15:36.339 --> 00:15:37.009 attributes programmatically, right. 00:15:37.009 --> 00:15:41.279 Well, that would be pretty cool. We would have 00:15:41.279 --> 00:15:43.130 to make some trade offs, but we'd basically get 00:15:43.130 --> 00:15:45.509 to the point where we could do something like 00:15:45.509 --> 00:15:48.449 inherit from MagicRecord and get the exact same behavior 00:15:48.449 --> 00:15:51.930 as we wanted. But as a freebie, now we 00:15:51.930 --> 00:15:54.009 have the ability to drop down another layer, if 00:15:54.009 --> 00:15:57.000 we want. And to actually define this stuff with 00:15:57.000 --> 00:15:58.060 less magic. 00:15:58.060 --> 00:16:01.800 And you say, well that's great. So that's attributes. 00:16:01.800 --> 00:16:04.620 We kind of understand that. That's pretty simple, right. 00:16:04.620 --> 00:16:08.069 Big whoop. ActiveRecord also does all these other things, 00:16:08.069 --> 00:16:11.170 I mean, you know, it's got like attribute typecasting 00:16:11.170 --> 00:16:13.779 and associations and serializations and secure passwords and transactions 00:16:13.779 --> 00:16:17.000 and macro reflection and nested attributes, time stamps, lifecycle 00:16:17.000 --> 00:16:20.839 callbacks, validations, dirty tracking, mass assignment, sanitation, to name 00:16:20.839 --> 00:16:23.880 some, and oh, by the way, we have querying 00:16:23.880 --> 00:16:26.829 and persisting, right. That's kind of a important thing 00:16:26.829 --> 00:16:29.670 in a persistence library. 00:16:29.670 --> 00:16:33.630 And so, I say yeah. Yeah, exactly. That's. That's 00:16:33.630 --> 00:16:36.019 an interesting problem that we have, right. Because they're 00:16:36.019 --> 00:16:38.329 all kind of living in one place, and how 00:16:38.329 --> 00:16:43.149 do you expose this kind of interface, this kind 00:16:43.149 --> 00:16:47.060 of way of interacting with, with your library, to 00:16:47.060 --> 00:16:48.589 cover all of these things. And my answer would 00:16:48.589 --> 00:16:51.350 be basically that you, you don't. You, you allow 00:16:51.350 --> 00:16:53.329 this to tell you maybe I've got a crazy 00:16:53.329 --> 00:16:54.339 idea. 00:16:54.339 --> 00:16:58.699 So, this is the ancestry chain of, of an 00:16:58.699 --> 00:17:01.940 ActiveRecord::Base subclass. I just wanted to show it to 00:17:01.940 --> 00:17:08.040 you real quickly. Now, yeah. Yeah. Three cheers for 00:17:08.040 --> 00:17:11.959 the, for the ancestry chain of ActieRecord::Base. So, somebody's 00:17:11.959 --> 00:17:15.430 clapping. Oh no. Right. 00:17:15.430 --> 00:17:18.329 SO, in Rails we call this clarity. You may 00:17:18.329 --> 00:17:25.329 have heard that earlier. Because API surface area is 00:17:25.690 --> 00:17:29.420 irrelevant. We don't care about that. In other words, 00:17:29.420 --> 00:17:32.940 the Single Responsibility Principle is super simple for sufficiently 00:17:32.940 --> 00:17:38.170 large values of responsibility. Like, if you're responsibility is 00:17:38.170 --> 00:17:40.790 to do everything, then you just say, OK, gotta 00:17:40.790 --> 00:17:43.630 do everything. It's gotta work, right. That's my responsibility. 00:17:43.630 --> 00:17:47.320 Well, it works. All right. Done. 00:17:47.320 --> 00:17:50.360 And so awhile back, actually last weekend, I Tweeted 00:17:50.360 --> 00:17:55.020 some of these statistics about an observation on an, 00:17:55.020 --> 00:17:58.770 a brand new Rails 4.1 app, what a subclass 00:17:58.770 --> 00:18:02.100 of ActiveRecord has, what the view has, and what 00:18:02.100 --> 00:18:06.190 the controller has in terms of ancestors, public protected 00:18:06.190 --> 00:18:08.830 class methods, public protected instance methods, and same for 00:18:08.830 --> 00:18:10.780 private methods, right. 00:18:10.780 --> 00:18:13.940 Now, look. It may very well be that this 00:18:13.940 --> 00:18:16.260 is exactly the API size that we need. I'm 00:18:16.260 --> 00:18:17.750 not gonna argue that one way or the other 00:18:17.750 --> 00:18:21.070 right now. But what I will say is that 00:18:21.070 --> 00:18:23.560 there are other ways to get there. Just because 00:18:23.560 --> 00:18:25.340 we want these methods does not mean they all 00:18:25.340 --> 00:18:28.320 actually have to be implemented in modules that are 00:18:28.320 --> 00:18:31.960 included onto the class. 00:18:31.960 --> 00:18:34.140 And so what I'm getting at is that, it's 00:18:34.140 --> 00:18:37.220 very, very hard to keep track of just what 00:18:37.220 --> 00:18:40.340 you're doing. I've been writing Rails for over seven 00:18:40.340 --> 00:18:42.160 years. I'm not exactly sure how long at this 00:18:42.160 --> 00:18:45.590 point. But, I know that, since I've been doing 00:18:45.590 --> 00:18:48.790 it, I still have to have documentation open most 00:18:48.790 --> 00:18:51.250 of the time when I'm doing anything serious. Like, 00:18:51.250 --> 00:18:53.640 maybe I'm just dumb. Possible. I don't know. But 00:18:53.640 --> 00:18:57.390 I need documentation. It's a really big namespace to 00:18:57.390 --> 00:18:58.900 try to keep in your head all at one 00:18:58.900 --> 00:18:59.600 point. 00:18:59.600 --> 00:19:04.720 So, this is on, online at GitHub, and you 00:19:04.720 --> 00:19:07.150 are free to do science to verify my empirical 00:19:07.150 --> 00:19:11.480 observations and see whether or not they are accurate, 00:19:11.480 --> 00:19:13.310 and I would love to see PRs to this 00:19:13.310 --> 00:19:17.330 repo, actually, with, you know, different versions of Rails 00:19:17.330 --> 00:19:19.460 to see how things have changed, complexity-wise. 00:19:19.460 --> 00:19:22.480 Now, it's not enough really for ActiveRecord to just 00:19:22.480 --> 00:19:25.940 do this on its own. It actually encourages us 00:19:25.940 --> 00:19:31.020 to do this, right. Rails has this whole helper 00:19:31.020 --> 00:19:33.550 thing, right. And, let me give you an example 00:19:33.550 --> 00:19:36.220 of something I actually encountered and, I'm embarrassed to 00:19:36.220 --> 00:19:38.290 say, spent like half a day trouble shooting with 00:19:38.290 --> 00:19:40.390 the, with helpers. 00:19:40.390 --> 00:19:44.080 So, I decided I had a really great idea, 00:19:44.080 --> 00:19:45.840 and I was gonna use something that I heard 00:19:45.840 --> 00:19:48.840 that OO developers like to do, which is polymorphism, 00:19:48.840 --> 00:19:50.370 and use it at the view layer, right. And 00:19:50.370 --> 00:19:54.250 I'm like, I can have something that is summarizable, 00:19:54.250 --> 00:19:56.020 and so I might have a helper for posts 00:19:56.020 --> 00:19:57.940 that's summary, and I might have a helper for 00:19:57.940 --> 00:20:00.150 reviews that's summary. 00:20:00.150 --> 00:20:02.550 And I can share a partial that prints that 00:20:02.550 --> 00:20:06.170 summary in an appropriate way for that particular thing, 00:20:06.170 --> 00:20:08.500 right. That seemed pretty cool. So this is how 00:20:08.500 --> 00:20:12.060 it would look in a partial. And in development 00:20:12.060 --> 00:20:16.220 it worked wonderfully. It worked exactly the way I 00:20:16.220 --> 00:20:18.450 expected. And then I deployed to production. 00:20:18.450 --> 00:20:23.530 Now, how many of you think it worked? Right. 00:20:23.530 --> 00:20:25.840 How many of you think it didn't work. Well, 00:20:25.840 --> 00:20:29.150 it's kind of a trick question, because honestly you 00:20:29.150 --> 00:20:30.920 can't really tell me, because you don't have enough 00:20:30.920 --> 00:20:34.810 information right now. Because there's this thing, right. 00:20:34.810 --> 00:20:38.620 OK, so, seven years ago, there was a commit 00:20:38.620 --> 00:20:41.390 to Rails that said, we are going to make 00:20:41.390 --> 00:20:43.210 it default assumption you want all helpers all the 00:20:43.210 --> 00:20:48.830 time. No comment. 00:20:48.830 --> 00:20:51.950 And, for a long period of time, I'd like 00:20:51.950 --> 00:20:53.460 to imagine it was some kind of a dark 00:20:53.460 --> 00:20:55.530 age in Rails. There was really no way to 00:20:55.530 --> 00:20:57.640 opt out of this, per se, until a patch 00:20:57.640 --> 00:21:00.300 came in that added include all helpers as a 00:21:00.300 --> 00:21:03.580 configuration option. So I thought, this is great. I 00:21:03.580 --> 00:21:07.270 found this, now I found this after hours of 00:21:07.270 --> 00:21:10.050 searching, like, because I just somehow missed the memo 00:21:10.050 --> 00:21:11.570 that we had done that. It was way back 00:21:11.570 --> 00:21:13.290 in 2.3, like, this has been the way for 00:21:13.290 --> 00:21:14.430 awhile, right. 00:21:14.430 --> 00:21:17.070 But, like I just kind of assume, like, it's 00:21:17.070 --> 00:21:21.730 named post_helper, it should help posts. Not, like, other 00:21:21.730 --> 00:21:24.420 things. But that's not how it works. So there's 00:21:24.420 --> 00:21:28.110 this kind of big namespace, right. And so, I 00:21:28.110 --> 00:21:31.300 would recommend that nearly all of you consider adding 00:21:31.300 --> 00:21:35.470 this to to your application dot rb. You will 00:21:35.470 --> 00:21:37.800 be much more sane for it. If you're going 00:21:37.800 --> 00:21:40.290 to use helpers, at the very least, having a 00:21:40.290 --> 00:21:42.050 namespace that you can kind of control. If you 00:21:42.050 --> 00:21:44.460 want to be available to all controllers, then throw 00:21:44.460 --> 00:21:46.870 it in application_helper or have a module. You can 00:21:46.870 --> 00:21:48.840 still use modules, I hear. It works. 00:21:48.840 --> 00:21:50.920 Now, we did all this in the name of 00:21:50.920 --> 00:21:55.090 convenience, right. Convenience is, is going to trump everything 00:21:55.090 --> 00:21:58.120 else. We want convenient usage at expense of anything 00:21:58.120 --> 00:22:02.870 else. And, you know, so I own a house. 00:22:02.870 --> 00:22:05.900 And I think to myself often that, you know, 00:22:05.900 --> 00:22:09.520 when nature calls, I have, like, to get up 00:22:09.520 --> 00:22:12.140 and like, go to a special room to go 00:22:12.140 --> 00:22:14.760 do my business, right. 00:22:14.760 --> 00:22:15.850 [laughter] 00:22:15.850 --> 00:22:20.300 And I mean that's really inconvenient. So like, why 00:22:20.300 --> 00:22:23.000 don't I just install a toilet, like, in every 00:22:23.000 --> 00:22:26.300 room in the house, right? Because then, like, if 00:22:26.300 --> 00:22:28.700 I'm watching the tube, it doesn't matter you know. 00:22:28.700 --> 00:22:31.240 Do my thing. It's all good. but the problem 00:22:31.240 --> 00:22:34.150 with that is, right, that first off, you've got, 00:22:34.150 --> 00:22:37.340 like, plumbing now to help support this, this aspiration 00:22:37.340 --> 00:22:40.660 of having a toilet in every room. And plumbers 00:22:40.660 --> 00:22:43.020 are expensive and, like, stuff breaks and then it's 00:22:43.020 --> 00:22:45.210 like, I've got a leak and I've got damage 00:22:45.210 --> 00:22:48.120 and stuff, and then the other problem is, like, 00:22:48.120 --> 00:22:51.180 every room is a toilet, right. 00:22:51.180 --> 00:22:56.330 So, I would encourage you to consider that if 00:22:56.330 --> 00:22:58.590 this is kind of what you're looking for, if 00:22:58.590 --> 00:23:02.700 a giant namespace of, of, of methods and functions 00:23:02.700 --> 00:23:04.850 is what you would really like to have, then 00:23:04.850 --> 00:23:09.820 have I got the language for you. 00:23:09.820 --> 00:23:16.120 It is super convenient, like, everything is at arm's 00:23:16.120 --> 00:23:17.520 length. What's that? You want to do something with 00:23:17.520 --> 00:23:20.610 a string and an array, yeah, doesn't matter. MySQL, 00:23:20.610 --> 00:23:24.720 sure. Absolutely. I mean, just a thought. 00:23:24.720 --> 00:23:30.090 So now another, another Rails opinion is, who needs 00:23:30.090 --> 00:23:35.710 classes when we've got modules? And I say this 00:23:35.710 --> 00:23:40.330 primarily because of one interesting piece of code, which 00:23:40.330 --> 00:23:47.330 is ActiveSupport::Concern. So, ActiveSupport::Concern you may think is mainly 00:23:47.540 --> 00:23:50.420 for having a convention around having a class methods 00:23:50.420 --> 00:23:54.030 module inside your module. And instance methods and so 00:23:54.030 --> 00:23:56.520 forth. But it's not. 00:23:56.520 --> 00:24:00.140 The problem the it's designed to solve is that, 00:24:00.140 --> 00:24:02.710 in this world, the Ruby world, the one that 00:24:02.710 --> 00:24:06.890 we live in lots of times, we, we actually 00:24:06.890 --> 00:24:09.150 would have to include. There's a lot of extension 00:24:09.150 --> 00:24:11.420 onto a class, right, when you include a module 00:24:11.420 --> 00:24:13.180 in the Rails world. Like, a lot of the 00:24:13.180 --> 00:24:15.490 modules that Rails is built on go and do 00:24:15.490 --> 00:24:18.110 metaprogramming and add methods to the singleton or whatever 00:24:18.110 --> 00:24:19.980 onto the class itself, right. 00:24:19.980 --> 00:24:22.410 And if you're adding stuff to the singleton, then 00:24:22.410 --> 00:24:25.280 it's not sufficient for you to go ahead and, 00:24:25.280 --> 00:24:27.870 and do that in a module that is itself 00:24:27.870 --> 00:24:29.810 included, right. Because when it gets included in the 00:24:29.810 --> 00:24:32.230 module, it modifies the module singleton, not the class 00:24:32.230 --> 00:24:33.660 singleton. With me so far? 00:24:33.660 --> 00:24:36.540 Right. This is a huge problem. So. So let's 00:24:36.540 --> 00:24:39.610 solve it. Now, we have this ability to have 00:24:39.610 --> 00:24:44.790 dependencies that get trapped by ActiveSupport::Concern, so that each 00:24:44.790 --> 00:24:47.770 singleton knows what, what its dependencies are, and then 00:24:47.770 --> 00:24:51.650 at the time that you include the, the dependency 00:24:51.650 --> 00:24:53.750 that you're really looking for, it can also go 00:24:53.750 --> 00:24:55.580 back and include into your module all the other 00:24:55.580 --> 00:24:57.410 ones that it needed, and so then that way 00:24:57.410 --> 00:24:59.660 they can do their metaprogramming magic on your singleton 00:24:59.660 --> 00:25:01.650 instead of their singleton. 00:25:01.650 --> 00:25:04.890 It's great. And it's, you know, so what it 00:25:04.890 --> 00:25:06.650 is is that there was this, this, this problem. 00:25:06.650 --> 00:25:11.720 There was this problem that we had. And, you 00:25:11.720 --> 00:25:14.660 know, we decided to bundle a, a, a free 00:25:14.660 --> 00:25:18.850 razor with every yak. And, I mean, I guess 00:25:18.850 --> 00:25:22.530 that's one solution, sure. And so, so I've been 00:25:22.530 --> 00:25:25.430 thinking a lot about this lately. 00:25:25.430 --> 00:25:27.290 And one of the things that sort of bothers 00:25:27.290 --> 00:25:29.620 me is that, you know, we're regularly told not 00:25:29.620 --> 00:25:34.490 to, not to fight the framework, right. But our 00:25:34.490 --> 00:25:39.120 framework pretty actively fights the language. There are things 00:25:39.120 --> 00:25:41.800 that the language is saying, hey, this might be 00:25:41.800 --> 00:25:43.160 crazy. Maybe you don't want to do this. And 00:25:43.160 --> 00:25:46.980 we're like, I won't do what you tell me. 00:25:46.980 --> 00:25:50.630 I will do exactly what I want to do. 00:25:50.630 --> 00:25:54.590 And it encourages this, this kind of module-centric design. 00:25:54.590 --> 00:25:56.750 Limits the entry points that we can have. So, 00:25:56.750 --> 00:25:58.830 you know, Yehuda made a really great point, actually, 00:25:58.830 --> 00:26:00.960 when he talked about that we're kind of on 00:26:00.960 --> 00:26:03.990 the 400th story, right. And, and I agree. We 00:26:03.990 --> 00:26:06.600 are, we are like way up here in terms 00:26:06.600 --> 00:26:08.120 of abstraction. 00:26:08.120 --> 00:26:12.180 But, like, I've heard rumors that, like, maybe, on 00:26:12.180 --> 00:26:14.730 most buildings, like, those other floors like have people 00:26:14.730 --> 00:26:18.280 in them, and like, they do things. And like 00:26:18.280 --> 00:26:21.170 maybe you can not just be trapped on the 00:26:21.170 --> 00:26:23.100 400th floor forever, but maybe you want to like 00:26:23.100 --> 00:26:25.780 go down, cause like, I heard, like, on floor 00:26:25.780 --> 00:26:29.330 350 there's like an ice cream store, and like, 00:26:29.330 --> 00:26:31.710 I like ice cream. Right. So maybe I want 00:26:31.710 --> 00:26:33.020 to go down and have some ice cream. 00:26:33.020 --> 00:26:36.520 But, like, I can't. Because I could only do 00:26:36.520 --> 00:26:39.720 things with things that are instantiatable, right. And if 00:26:39.720 --> 00:26:42.110 everything is a module, I'm not instantiating that. I 00:26:42.110 --> 00:26:44.530 guess I could write my own class and include 00:26:44.530 --> 00:26:47.050 half of what's going on, but that seems like 00:26:47.050 --> 00:26:49.190 I'm just perpetuating the problem. 00:26:49.190 --> 00:26:54.470 So, here's another, here's another Rails opinion. Rails believes 00:26:54.470 --> 00:26:59.390 that your conventions suck. First example is, now, I 00:26:59.390 --> 00:27:01.250 know it's gonna be hard for you to believe, 00:27:01.250 --> 00:27:05.730 but there were conventions for building applications before Rails 00:27:05.730 --> 00:27:08.710 came out. Like, people were actually building - I 00:27:08.710 --> 00:27:12.820 know, it's a little weird. They were building web 00:27:12.820 --> 00:27:14.220 applications, and, and one of the things that they 00:27:14.220 --> 00:27:16.100 used was JavaScript, right. 00:27:16.100 --> 00:27:19.870 Now, love or hate JavaScript, it, it, it's here 00:27:19.870 --> 00:27:21.620 to stay at this point. We, we, we're gonna 00:27:21.620 --> 00:27:25.290 be writing it. And so, Rails, once upon a 00:27:25.290 --> 00:27:28.330 time - you guys remember this? You remember this? 00:27:28.330 --> 00:27:32.500 Like, let's, so. If this was before your time 00:27:32.500 --> 00:27:35.110 with Rails, we had, we had this great idea, 00:27:35.110 --> 00:27:39.580 right, which is, JavaScript's a pain to write. And 00:27:39.580 --> 00:27:44.220 let's write Ruby that writes JavaScript instead. And so 00:27:44.220 --> 00:27:46.820 we called that RJS, and you could write these, 00:27:46.820 --> 00:27:48.420 there were these methods that if you said page 00:27:48.420 --> 00:27:50.650 dot whatever, it would generate some JavaScript. And you 00:27:50.650 --> 00:27:52.720 could go look at the JavaScript and it was, 00:27:52.720 --> 00:27:55.000 you know, about what you would expect generated JavaScript 00:27:55.000 --> 00:27:57.260 to be. 00:27:57.260 --> 00:27:59.880 And then we decided, you know, OK, maybe that 00:27:59.880 --> 00:28:01.970 was crazy. But we're still not happy with the 00:28:01.970 --> 00:28:06.600 whole state that we have to write JavaScript. So 00:28:06.600 --> 00:28:09.860 we decided to use JavaScript that looks like Ruby, 00:28:09.860 --> 00:28:14.680 right. OK. Great. All right. Fine. I can see 00:28:14.680 --> 00:28:17.400 that. 00:28:17.400 --> 00:28:21.130 And then, at that point, now, we were at 00:28:21.130 --> 00:28:24.360 a point where there's this other convention, where like, 00:28:24.360 --> 00:28:26.810 if you're using jQuery, and many of us are, 00:28:26.810 --> 00:28:31.010 like, let's say, let's say that I want to 00:28:31.010 --> 00:28:33.530 render, I have decided I'm gonna be on the 00:28:33.530 --> 00:28:35.760 straight and narrow, I am going to render my, 00:28:35.760 --> 00:28:40.220 my, my views in Ruby. I want to render 00:28:40.220 --> 00:28:41.890 static html that I spit out. But I need 00:28:41.890 --> 00:28:45.870 some dynamic parts, and so I'm gonna render some, 00:28:45.870 --> 00:28:48.580 some JavaScript as well that's gonna do some things, 00:28:48.580 --> 00:28:49.960 right. Use jQuery. 00:28:49.960 --> 00:28:51.510 This is a pretty standard convention, right. I mean, 00:28:51.510 --> 00:28:53.470 how many of you have this exact code in 00:28:53.470 --> 00:28:56.220 your code base somewhere, right. If you're not raising 00:28:56.220 --> 00:29:00.530 your hand, I'm very shocked. So, we thought, you 00:29:00.530 --> 00:29:02.470 know, that's, that's great. It's really cool to be 00:29:02.470 --> 00:29:04.660 able to hook into $(document).ready and do some stuff. 00:29:04.660 --> 00:29:08.750 And so, so Rails said, that's a horrible idea. 00:29:08.750 --> 00:29:12.580 You should use Turbolinks. And so now, look, you 00:29:12.580 --> 00:29:16.340 can yank Turbolinks out of your gemfile and that's 00:29:16.340 --> 00:29:18.630 true. You can do that, right. But it's my 00:29:18.630 --> 00:29:22.900 opinion that convention should probably not completely break someone's 00:29:22.900 --> 00:29:25.430 expectations if they're doing server-side rendering, and this is 00:29:25.430 --> 00:29:27.410 something that you, you are going to run into 00:29:27.410 --> 00:29:28.990 if you're just starting out with Rails. You'll be 00:29:28.990 --> 00:29:30.330 like, well, why isn't this doing? Well, we don't 00:29:30.330 --> 00:29:31.840 fire. We don't fire the doc. 00:29:31.840 --> 00:29:34.780 No, there are, there are other gems that will 00:29:34.780 --> 00:29:37.140 make this seem like that is not the case. 00:29:37.140 --> 00:29:39.050 But the fact of the matter is, it's gonna 00:29:39.050 --> 00:29:42.180 bite you. So, so Rails said, you know, we 00:29:42.180 --> 00:29:45.840 have opinions about how you should write JavaScript. 00:29:45.840 --> 00:29:47.600 Rails has opinions about how you should maintain data 00:29:47.600 --> 00:29:54.600 integrity as well. And so in the Rails world, 00:29:54.970 --> 00:29:57.320 this is a typical, typical way to handle some, 00:29:57.320 --> 00:30:00.040 some validation of data integrity, right. Maybe you make 00:30:00.040 --> 00:30:02.800 sure that you have a customer, and you need 00:30:02.800 --> 00:30:07.150 a unique reference number, and you have a typo 00:30:07.150 --> 00:30:08.020 there. 00:30:08.020 --> 00:30:10.950 validates_associates. Validates :associates and :line_items, right. And you won't 00:30:10.950 --> 00:30:15.520 save an order unless its :line_items are valid. And 00:30:15.520 --> 00:30:20.020 that's really interesting to me, because objects, unfortunately, you 00:30:20.020 --> 00:30:22.820 know, they don't really understand their relations to other 00:30:22.820 --> 00:30:25.570 things very well, because those live somewhere else. They're 00:30:25.570 --> 00:30:28.840 in the data store separate, right. And, you know, 00:30:28.840 --> 00:30:30.790 I, I really think that it would be great, 00:30:30.790 --> 00:30:33.620 like, if there was some sort of a system 00:30:33.620 --> 00:30:36.150 that we could use. So, like, I don't know, 00:30:36.150 --> 00:30:41.270 it would be like a system for managing, I 00:30:41.270 --> 00:30:48.220 don't know, relational data, maybe? I don't know. 00:30:48.220 --> 00:30:50.890 It would be great if we had one of 00:30:50.890 --> 00:30:55.470 those. And it turns out that, like, we do. 00:30:55.470 --> 00:30:59.000 And they are, like, super good at understanding relationships 00:30:59.000 --> 00:31:02.920 between data. And they are super good at, at 00:31:02.920 --> 00:31:05.230 validating the data that goes in and out and 00:31:05.230 --> 00:31:09.900 ensuring that things are atomic, right, and that, that 00:31:09.900 --> 00:31:12.370 our updates are not gonna run into race conditions 00:31:12.370 --> 00:31:14.400 and the like, right? 00:31:14.400 --> 00:31:16.400 I mean, and I'm talking about, even the, let's 00:31:16.400 --> 00:31:21.590 say, less than civilized versions of databases, those are, 00:31:21.590 --> 00:31:24.070 those are also able, able to do pretty well 00:31:24.070 --> 00:31:27.720 at this. Because, Ruby, the Ruby land has to 00:31:27.720 --> 00:31:29.550 cross a process boundary to know any of this 00:31:29.550 --> 00:31:33.110 stuff, and that's pretty lossy, really. 00:31:33.110 --> 00:31:35.150 So, I don't think it would be fair, you 00:31:35.150 --> 00:31:36.960 know, I've griped a lot at this point about 00:31:36.960 --> 00:31:38.290 a few of the opinions that I think Rails 00:31:38.290 --> 00:31:41.310 has, and I feel like you came here hoping 00:31:41.310 --> 00:31:43.110 that I would offer you some solutions, right. I 00:31:43.110 --> 00:31:47.630 want to show you some solutions that I've found. 00:31:47.630 --> 00:31:53.530 These are my solutions. They look pretty nice, I 00:31:53.530 --> 00:31:54.300 think. 00:31:54.300 --> 00:31:55.080 Science. 00:31:55.080 --> 00:32:00.330 No. So, I've been doing this thing lately, and 00:32:00.330 --> 00:32:04.540 I'm calling it IDD. And that stands for Ignorance-Driven 00:32:04.540 --> 00:32:10.970 Development. It's really blissful. And it's this, this crazy 00:32:10.970 --> 00:32:15.970 idea that, like, maybe starting with Rails g model, 00:32:15.970 --> 00:32:19.400 like starting out thinking about your persistence, is maybe 00:32:19.400 --> 00:32:21.300 not the way to go. 00:32:21.300 --> 00:32:23.470 If you're thinking about your persistence for - I 00:32:23.470 --> 00:32:26.470 mean, I can tell you, all right. Raise your 00:32:26.470 --> 00:32:30.050 hand if you have stopped to consider what your 00:32:30.050 --> 00:32:32.130 database scheme, schema is gonna look like after you've 00:32:32.130 --> 00:32:33.920 typed Rails g model, and you're just kind of 00:32:33.920 --> 00:32:37.300 frozen there, like, crap. Analysis paralysis sets in, right. 00:32:37.300 --> 00:32:40.660 Because, like, migrations are a pain and databases are, 00:32:40.660 --> 00:32:43.300 ew, yuck. We want to do everything in Ruby, 00:32:43.300 --> 00:32:44.010 right? 00:32:44.010 --> 00:32:45.990 And, and so that's a problem, right, because I 00:32:45.990 --> 00:32:47.840 don't necessarily know what the best way to store 00:32:47.840 --> 00:32:49.630 my data is off the top of my head, 00:32:49.630 --> 00:32:52.710 right? I may find that out as I go. 00:32:52.710 --> 00:32:54.990 So here's a crazy idea. 00:32:54.990 --> 00:32:57.700 Start with Ruby and ignore persistence, off the bat. 00:32:57.700 --> 00:33:00.950 Like, probably that is not your domain. Your domain 00:33:00.950 --> 00:33:03.070 is not to be a CRUD app. Most of 00:33:03.070 --> 00:33:04.840 us here, anyway, our domain is not to just 00:33:04.840 --> 00:33:06.600 be a CRUD app, right. We have some business 00:33:06.600 --> 00:33:08.240 logic. 00:33:08.240 --> 00:33:11.490 And after you start with Ruby, then you start 00:33:11.490 --> 00:33:14.340 to identify the scary things, right. And this is 00:33:14.340 --> 00:33:16.240 like the part of our domain that we're really 00:33:16.240 --> 00:33:19.070 scared we're not gonna be able to implement. Like, 00:33:19.070 --> 00:33:21.020 what is the thing that's gonna be super hairy, 00:33:21.020 --> 00:33:22.960 that we're just kind of like, afraid to tackle, 00:33:22.960 --> 00:33:25.900 right. And removing the, like, the analysis paralysis that 00:33:25.900 --> 00:33:28.160 can set in when you're trying to figure out 00:33:28.160 --> 00:33:29.700 where your, what your data's gonna look like, while 00:33:29.700 --> 00:33:31.750 you're just kind of playing around with, with an 00:33:31.750 --> 00:33:33.870 algorithm, is great, because it gives you this sort 00:33:33.870 --> 00:33:35.670 of power to attack the scary things. You can 00:33:35.670 --> 00:33:39.950 do, I know it's crazy to say, some TDD 00:33:39.950 --> 00:33:41.860 and attack these scary things. 00:33:41.860 --> 00:33:44.010 And it's, the cost of experimentation is a lot 00:33:44.010 --> 00:33:46.100 lower when you're not messing around running migrations. You're 00:33:46.100 --> 00:33:49.720 just running super fast tests. Everything is really nice. 00:33:49.720 --> 00:33:51.420 And you validate that the business logic that you're 00:33:51.420 --> 00:33:54.080 trying to write is going to be sane before 00:33:54.080 --> 00:33:56.220 you go any further. 00:33:56.220 --> 00:33:58.540 And so, so what that might look like, for 00:33:58.540 --> 00:34:00.880 instance, is let's say I have a monster class, 00:34:00.880 --> 00:34:03.740 right. I simply give it some teeth and some 00:34:03.740 --> 00:34:06.080 claws, right, and it can bite and it can 00:34:06.080 --> 00:34:07.580 scratch, and I write my test. And let's just 00:34:07.580 --> 00:34:09.770 assume that biting and scratching is a very, very 00:34:09.770 --> 00:34:12.668 difficult thing for a monster to do, right. 00:34:12.668 --> 00:34:15.329 And, and so it starts out that way. And 00:34:15.329 --> 00:34:17.829 you gradually iterate on the things that you want 00:34:17.829 --> 00:34:20.960 your monster to do, right. And then what you 00:34:20.960 --> 00:34:25.080 find out is that, eventually, after having iterated through 00:34:25.080 --> 00:34:27.750 maybe, maybe many, many iterations on what this class 00:34:27.750 --> 00:34:30.600 looks like, what its collaborators might look like, you 00:34:30.600 --> 00:34:32.820 get to a point where you're like, OK. I 00:34:32.820 --> 00:34:34.510 know how to make this monster now. I know 00:34:34.510 --> 00:34:36.710 how to, how to tackle it, right. 00:34:36.710 --> 00:34:39.489 And now is a time for you to admit 00:34:39.489 --> 00:34:42.600 persistence. Right, now you start to think, OK, well, 00:34:42.600 --> 00:34:45.040 I've gotta persist this stuff somewhere. I have some, 00:34:45.040 --> 00:34:46.690 some things about this business logic that are gonna 00:34:46.690 --> 00:34:49.580 require me to save some data to the database. 00:34:49.580 --> 00:34:51.940 And so you decide, well, what database am I 00:34:51.940 --> 00:34:54.199 gonna use? Or is it gonna be NoSQL or 00:34:54.199 --> 00:34:55.489 is it gonna be SQL or is it gonna 00:34:55.489 --> 00:34:59.430 be, I don't know, something in memory? Right. 00:34:59.430 --> 00:35:03.030 And then from that point, let's just say you 00:35:03.030 --> 00:35:06.540 decide, well, now I'm gonna do some ActiveRecord. And 00:35:06.540 --> 00:35:09.330 so you say, all I do is now inherit 00:35:09.330 --> 00:35:11.270 from ActiveRecord::Base. The teeth and claws are no longer 00:35:11.270 --> 00:35:15.790 supplied via injection. But instead they come from relationships 00:35:15.790 --> 00:35:19.140 in some way, and we maybe have determined that 00:35:19.140 --> 00:35:23.530 we require that we have teeth and claws. 00:35:23.530 --> 00:35:25.100 And then, you guys are gonna think. You notice 00:35:25.100 --> 00:35:28.780 there's no methods here, right. Right. No methods. It's 00:35:28.780 --> 00:35:31.660 not doing anything yet, except the ActiveRecord stuff. You're 00:35:31.660 --> 00:35:33.900 gonna think I'm trolling you. But here's what I've 00:35:33.900 --> 00:35:35.610 started to do. 00:35:35.610 --> 00:35:41.050 I use modules. Now, the way I see it, 00:35:41.050 --> 00:35:42.650 you know, in firefighting there's this thing called a 00:35:42.650 --> 00:35:46.510 back fire, where it's like, OK, so, when they 00:35:46.510 --> 00:35:48.660 say, like, fight fire with fire, that's actually a 00:35:48.660 --> 00:35:51.040 thing. And like, I'm like, you know what, Rails, 00:35:51.040 --> 00:35:52.760 if you really wanna burn the whole place down, 00:35:52.760 --> 00:35:54.380 that's OK. I got my own little fire going 00:35:54.380 --> 00:35:56.910 over here. And it's gonna, it's gonna allow me 00:35:56.910 --> 00:35:59.290 to have some semblance of order. And let me 00:35:59.290 --> 00:36:01.560 show you what that looks like. And before you 00:36:01.560 --> 00:36:03.090 think that it won't work, I can only just 00:36:03.090 --> 00:36:05.840 say that it has worked for me. Give it 00:36:05.840 --> 00:36:08.620 a try. Strangely, I'm not going to prescribe that 00:36:08.620 --> 00:36:10.320 it's gonna be the solution for everyone. I know 00:36:10.320 --> 00:36:11.410 that's kind of the hip thing to do is 00:36:11.410 --> 00:36:14.720 to say, like, my solution will work for you. 00:36:14.720 --> 00:36:17.350 But it worked for me. 00:36:17.350 --> 00:36:19.560 And what it would look like is this. So 00:36:19.560 --> 00:36:23.860 I now have behaviors that I expose in modules, 00:36:23.860 --> 00:36:30.460 right. These behaviors are specifically intended to provide one 00:36:30.460 --> 00:36:35.170 isolated thing, one isolated capability to the persisted record, 00:36:35.170 --> 00:36:37.390 right. And so in this case, like, here is 00:36:37.390 --> 00:36:41.740 the biting module, for instance, right. And it knows 00:36:41.740 --> 00:36:43.270 how to bite. And let's say this is after 00:36:43.270 --> 00:36:45.040 we have developed all of our, all of our 00:36:45.040 --> 00:36:47.210 stuff in plain Ruby, right, this is what we 00:36:47.210 --> 00:36:49.510 landed on for what bite need to, need to 00:36:49.510 --> 00:36:52.340 perform, right. 00:36:52.340 --> 00:36:57.800 And so once we've done that, we can write 00:36:57.800 --> 00:37:00.510 a class, you know, we can actually just test 00:37:00.510 --> 00:37:03.240 against the class that limits the API service that 00:37:03.240 --> 00:37:06.110 our behavior interacts with. This was the goal. Like, 00:37:06.110 --> 00:37:10.130 this is why I do this at all, is 00:37:10.130 --> 00:37:13.170 because thinking about how I'm gonna interact with this, 00:37:13.170 --> 00:37:16.180 like, essentially infinite API that, that a lot of, 00:37:16.180 --> 00:37:19.080 a lot of Rails provides, particularly ActiveRecord provides in 00:37:19.080 --> 00:37:22.150 this case, is, is too hard for me. Cause 00:37:22.150 --> 00:37:24.580 I'm dumb, OK. So, what I need is some 00:37:24.580 --> 00:37:26.400 help to help me just be able to see 00:37:26.400 --> 00:37:28.180 into the test. This is the part of the 00:37:28.180 --> 00:37:29.550 API I care about. 00:37:29.550 --> 00:37:31.840 And you may be concerned about this. You may 00:37:31.840 --> 00:37:35.250 say, this looks a lot like ActiveSupport::Concern. I can 00:37:35.250 --> 00:37:36.600 understand why you would say that. Let me show 00:37:36.600 --> 00:37:39.250 you why that's not the case. So, earlier we 00:37:39.250 --> 00:37:44.930 talked about how ActiveSupport::Concern's primary goal is to solve 00:37:44.930 --> 00:37:48.210 the problem of modules that depend on other modules 00:37:48.210 --> 00:37:51.370 that modify their base class, right. 00:37:51.370 --> 00:37:53.770 The intention in this, and that might look like 00:37:53.770 --> 00:37:55.380 this. Like, let's say now there's like a whole 00:37:55.380 --> 00:37:58.290 fighting behavior that might bite and might scratch, we 00:37:58.290 --> 00:38:00.500 don't know yet. There may be some probability associated 00:38:00.500 --> 00:38:02.870 with it, that against a particular target or maybe 00:38:02.870 --> 00:38:05.250 more than one target or whatever, and so it 00:38:05.250 --> 00:38:08.830 sort of has this dependency, not just on the 00:38:08.830 --> 00:38:11.190 API that the class that it's being included into 00:38:11.190 --> 00:38:14.070 has, but also the stuff that's getting included into 00:38:14.070 --> 00:38:16.760 that class already. So it expects bite and scratch, 00:38:16.760 --> 00:38:19.830 which are provided by other two behaviors. So, that 00:38:19.830 --> 00:38:23.730 kind of thing becomes actually painful. That actually becomes 00:38:23.730 --> 00:38:27.350 painful when you're not using ActiveSupport::Concern. 00:38:27.350 --> 00:38:29.970 And so, what you actually have here is a 00:38:29.970 --> 00:38:32.130 canary in the coal mine, a sentinel animal, right. 00:38:32.130 --> 00:38:35.210 It's, it's something that's telling you, there's this thing 00:38:35.210 --> 00:38:38.240 that's doing more than one kind of thing that's 00:38:38.240 --> 00:38:43.100 more complex, right. And it really isn't fully encapsulated 00:38:43.100 --> 00:38:46.210 in the stuff that I've got so far. And 00:38:46.210 --> 00:38:48.720 it leads you to understand that maybe there's another 00:38:48.720 --> 00:38:51.280 thing. Like maybe there's an encounter, right, and it 00:38:51.280 --> 00:38:53.770 might include one or more combatants that select targets 00:38:53.770 --> 00:38:56.290 and do one of their actions, right. Either bite 00:38:56.290 --> 00:38:59.330 or scratch. All right. 00:38:59.330 --> 00:39:02.010 So, to kind of start to sum things up, 00:39:02.010 --> 00:39:04.360 it, we, we, a lot of us work in 00:39:04.360 --> 00:39:07.660 the startup world, right. And it's really frustrating and 00:39:07.660 --> 00:39:09.980 surprising to me that we embrace this idea of 00:39:09.980 --> 00:39:13.460 a minimal, minimum viable product in the startup world, 00:39:13.460 --> 00:39:15.520 right. Build the smallest thing that could possibly work 00:39:15.520 --> 00:39:17.270 and then go from there. 00:39:17.270 --> 00:39:21.900 I, I kind of feel like in software, the 00:39:21.900 --> 00:39:25.550 whole goal, really, is to make as few decisions 00:39:25.550 --> 00:39:28.540 as you possibly can in order to make, get 00:39:28.540 --> 00:39:31.420 the desired result, right. Every decision you defer till 00:39:31.420 --> 00:39:34.460 later is going to give you some capability to 00:39:34.460 --> 00:39:37.500 be able to react to change, right. So I 00:39:37.500 --> 00:39:39.690 would like to see us, both in Rails and 00:39:39.690 --> 00:39:41.420 in the software that we write, start off with 00:39:41.420 --> 00:39:46.380 fewer opinions. Start off with fewer assumptions. Make sure 00:39:46.380 --> 00:39:48.450 that the floors that we build have a purpose. 00:39:48.450 --> 00:39:49.650 One great way to do that is to make 00:39:49.650 --> 00:39:51.370 sure that you can instantiate a lot of the 00:39:51.370 --> 00:39:52.260 things, right. 00:39:52.260 --> 00:39:54.080 If you can instantiate a lot of the things 00:39:54.080 --> 00:39:55.530 then they must have a purpose that we can 00:39:55.530 --> 00:39:58.210 reason about. We can think about. As opposed to, 00:39:58.210 --> 00:40:01.580 well, they might modify five hundred methods on another 00:40:01.580 --> 00:40:06.570 class. And in general, just be a considerate software 00:40:06.570 --> 00:40:07.040 writer. 00:40:07.040 --> 00:40:09.260 Thanks for your time.