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