1 00:00:17,060 --> 00:00:18,180 ERNIE MILLER: Good afternoon everybody. 2 00:00:18,180 --> 00:00:18,820 AUDIENCE: Good afternoon. 3 00:00:18,820 --> 00:00:19,580 E.M.: How's it going? 4 00:00:19,580 --> 00:00:21,360 AUDIENCE: It's going good! Hi Ernie! 5 00:00:21,360 --> 00:00:23,420 E.M.: Hi. My name's Ernie Miller. I work for 6 00:00:23,430 --> 00:00:26,250 a company called Appriss in Louisville, Kentucky. Please ask 7 00:00:26,250 --> 00:00:28,800 me about them later so that I can justify 8 00:00:28,800 --> 00:00:30,289 expensing the trip. 9 00:00:30,289 --> 00:00:31,750 AUDIENCE: Whoo! 10 00:00:31,750 --> 00:00:32,479 [applause] 11 00:00:32,479 --> 00:00:34,940 E.M.: If I could ask you all to do 12 00:00:34,940 --> 00:00:38,370 me a favor, as it turns out, most of 13 00:00:38,370 --> 00:00:41,370 my fellow co-workers that had come out to RailsConf 14 00:00:41,370 --> 00:00:44,170 have had to catch a flight to go back 15 00:00:44,170 --> 00:00:45,739 home, and so they're missing my talk. And so 16 00:00:45,739 --> 00:00:47,809 what I'd like you to do is to Tweet 17 00:00:47,809 --> 00:00:50,739 very enthusiastically about the talk, regardless of if it's 18 00:00:50,739 --> 00:00:52,430 very good, so that, you know, for at least 19 00:00:52,430 --> 00:00:53,909 until it goes on video, they're gonna think they 20 00:00:53,909 --> 00:00:56,129 missed the talk of a lifetime. 21 00:00:56,129 --> 00:00:59,729 So, RailsConf, huh? Have you guys had a good 22 00:00:59,729 --> 00:01:00,229 times? 23 00:01:00,229 --> 00:01:01,220 AUDIENCE: Whoo! 24 00:01:01,220 --> 00:01:01,720 [applause] 25 00:01:01,720 --> 00:01:03,210 E.M.: Yeah? Yeah. 26 00:01:03,210 --> 00:01:07,689 I've had a ball, too. I've had a ball, 27 00:01:07,689 --> 00:01:08,189 too. 28 00:01:08,189 --> 00:01:08,680 So. 29 00:01:08,680 --> 00:01:10,180 AUDIENCE: Ah, yeah! 30 00:01:10,180 --> 00:01:11,360 E.M.: I am not. 31 00:01:11,360 --> 00:01:12,530 AUDIENCE: [indecipherable - 00:01:10] 32 00:01:12,530 --> 00:01:14,869 E.M.: Yes. Yes it was. 33 00:01:14,869 --> 00:01:19,670 So, I am not a member of Ruby core. 34 00:01:19,670 --> 00:01:25,259 I am not a member of Rails core. However, 35 00:01:25,259 --> 00:01:27,850 last month, this game came out, and I'm an 36 00:01:27,850 --> 00:01:31,710 avid gamer, and I'd like to happily report that 37 00:01:31,710 --> 00:01:34,590 I am very frequently a member of Damage core, 38 00:01:34,590 --> 00:01:36,780 at this point. 39 00:01:36,780 --> 00:01:40,710 Unfortunately, membership only lasts for about fifteen seconds at 40 00:01:40,710 --> 00:01:42,939 a time. Then I get booted again. So, so 41 00:01:42,939 --> 00:01:46,460 there is that. But, you know, I'm thinking, you 42 00:01:46,460 --> 00:01:48,060 know, it's, it's moving up in the world. I'm 43 00:01:48,060 --> 00:01:50,429 a member of something core. 44 00:01:50,429 --> 00:01:54,829 So, so, it's come to my attention recently that 45 00:01:54,829 --> 00:01:57,299 I have been giving a fair number of talks 46 00:01:57,299 --> 00:01:59,709 that usually involve me ranting about something, and I 47 00:01:59,709 --> 00:02:01,770 think I'm becoming a bit of a curmudgeon. 48 00:02:01,770 --> 00:02:02,350 [applause] 49 00:02:02,350 --> 00:02:06,990 So, you're not supposed to clap for that. 50 00:02:06,990 --> 00:02:07,569 [laughter] 51 00:02:07,569 --> 00:02:09,740 OK. So, one of the things that I want 52 00:02:09,740 --> 00:02:11,569 to start off by doing is saying that I 53 00:02:11,569 --> 00:02:13,880 recognize that most of us would not be in 54 00:02:13,880 --> 00:02:17,000 this room if it weren't for Rails, and that 55 00:02:17,000 --> 00:02:20,090 we really owe a lot of our opportunity to 56 00:02:20,090 --> 00:02:22,250 get paid for doing Ruby, I know I do 57 00:02:22,250 --> 00:02:26,580 anyway, to Rails's existence. So, first off, I'd like 58 00:02:26,580 --> 00:02:28,890 to get a hand for Rails and how awesome 59 00:02:28,890 --> 00:02:30,239 it is and how it enables us to do 60 00:02:30,239 --> 00:02:31,140 everything. 61 00:02:31,140 --> 00:02:32,049 [applause] 62 00:02:32,049 --> 00:02:36,450 OK. OK. Nope. Nope. That's enough. Nope. No more. 63 00:02:36,450 --> 00:02:36,989 We're done celebrating. 64 00:02:36,989 --> 00:02:37,180 [laughter] 65 00:02:37,180 --> 00:02:39,530 Just that much celebration. Nothing more. 66 00:02:39,530 --> 00:02:40,280 [laughter] 67 00:02:40,280 --> 00:02:43,459 OK. All right. Stop the part. 68 00:02:43,459 --> 00:02:47,799 So. That. That gets me every time. 69 00:02:47,799 --> 00:02:50,439 So, that being the case, I, I have to 70 00:02:50,439 --> 00:02:54,400 say, a lot of us have been hitting brick 71 00:02:54,400 --> 00:02:57,180 walls. How many of you have been building something 72 00:02:57,180 --> 00:02:59,659 relatively complex with Rails, and you sort of feel 73 00:02:59,659 --> 00:03:02,269 like you've, you've gone up against a brick wall. 74 00:03:02,269 --> 00:03:04,579 You can't make anymore forward progress and you feel 75 00:03:04,579 --> 00:03:07,090 like you've been kind of, you know, so- yeah, 76 00:03:07,090 --> 00:03:08,970 OK. So some hands are going up right. 77 00:03:08,970 --> 00:03:12,209 And, and, and so it seems to me, like, 78 00:03:12,209 --> 00:03:14,930 if there is that much talk about it, you 79 00:03:14,930 --> 00:03:16,930 know, it seems like we often get the response 80 00:03:16,930 --> 00:03:18,769 that, you know, we just need to run with 81 00:03:18,769 --> 00:03:22,989 more passion at the wall. Run faster. And, and 82 00:03:22,989 --> 00:03:26,540 if we just fully commit that we'll burst through 83 00:03:26,540 --> 00:03:28,319 and we'll be in this sort of magical land 84 00:03:28,319 --> 00:03:31,890 where everything works the way that it's supposed to, 85 00:03:31,890 --> 00:03:34,319 and just don't fight so much, right? 86 00:03:34,319 --> 00:03:37,780 I have to think that if so many of 87 00:03:37,780 --> 00:03:39,590 us have kind of run into these sort of 88 00:03:39,590 --> 00:03:43,730 problems, that maybe there's something there. Maybe there's, there's 89 00:03:43,730 --> 00:03:44,939 some kind of an issue there, and I wanted 90 00:03:44,939 --> 00:03:47,939 to give a few opinions about, you know, why 91 00:03:47,939 --> 00:03:49,290 that might be. 92 00:03:49,290 --> 00:03:54,900 So, Rails is a convention over configuration advocate, right. 93 00:03:54,900 --> 00:03:56,900 That's, that's the big thing that we always talk 94 00:03:56,900 --> 00:03:59,299 about, that we would prefer to have convention over 95 00:03:59,299 --> 00:04:04,400 configuration. Now, conventions are really what, what opinions want 96 00:04:04,400 --> 00:04:07,230 to be when they grow up, right. So, most 97 00:04:07,230 --> 00:04:09,670 conventions have stemmed from an opinion. We hopefully share 98 00:04:09,670 --> 00:04:13,819 the opinion, but I want to be clear that, 99 00:04:13,819 --> 00:04:16,279 when I talk about the opinions that Rails has 100 00:04:16,279 --> 00:04:19,410 today, I am not talking specifically about any members 101 00:04:19,410 --> 00:04:21,329 of the core team. I'm not talking about the 102 00:04:21,329 --> 00:04:24,810 people, though the software may in fact reflect opinions 103 00:04:24,810 --> 00:04:26,640 of people, what I want to talk about is 104 00:04:26,640 --> 00:04:28,780 what does the software tell us, right? 105 00:04:28,780 --> 00:04:32,570 Because we know that Rails is opinionated software. So, 106 00:04:32,570 --> 00:04:35,220 with that out of the way, let's go with 107 00:04:35,220 --> 00:04:38,130 the first opinion that Rails, Rails has, that I 108 00:04:38,130 --> 00:04:40,650 believe Rails has anyway, which is that code should 109 00:04:40,650 --> 00:04:45,350 read like English. And we see this pretty frequently 110 00:04:45,350 --> 00:04:49,870 in comparisons between straight-up Ruby versus Rails kind of 111 00:04:49,870 --> 00:04:50,840 code, right, so. 112 00:04:50,840 --> 00:04:52,630 Here's something that a lot of us actually like. 113 00:04:52,630 --> 00:04:53,680 Like, I know this is one of the things 114 00:04:53,680 --> 00:04:55,569 that hooked me on Rails right off the bat, 115 00:04:55,569 --> 00:04:57,280 was like, oh, I can say, like, five dot 116 00:04:57,280 --> 00:05:00,699 days ago, or, you know, because I'm writing something 117 00:05:00,699 --> 00:05:03,430 in old English, I can say one dot fortnight.from_now. 118 00:05:03,430 --> 00:05:09,139 That's very useful. Right. 119 00:05:09,139 --> 00:05:11,550 So there's nothing particular, when we say like, one 120 00:05:11,550 --> 00:05:14,389 dot megabyte, right, there's, there's nothing megabyte-y about the 121 00:05:14,389 --> 00:05:17,740 number, right. It just does some multiplication. 122 00:05:17,740 --> 00:05:23,030 Similarly, we have some, oh yeah. Fortnight. Yeah. Similarly, 123 00:05:23,030 --> 00:05:26,990 we have some differences where we have something that 124 00:05:26,990 --> 00:05:29,800 array already has, for instance, on it, like the 125 00:05:29,800 --> 00:05:31,449 sh- I just found out it's called the shovel 126 00:05:31,449 --> 00:05:33,400 operator. I always just said less than less than, 127 00:05:33,400 --> 00:05:35,449 but whatever it is, right. So we have, like, 128 00:05:35,449 --> 00:05:38,090 array less than less than object, right, and we've, 129 00:05:38,090 --> 00:05:40,080 we've got that alias to append, so that we 130 00:05:40,080 --> 00:05:41,830 can say append. 131 00:05:41,830 --> 00:05:44,120 We have object dot in, so we can ask 132 00:05:44,120 --> 00:05:45,750 whether an object is in an array include of 133 00:05:45,750 --> 00:05:47,770 ask an array whether it has an object. Things 134 00:05:47,770 --> 00:05:49,550 like that. 135 00:05:49,550 --> 00:05:53,789 We have string methods that have been, you know, 136 00:05:53,789 --> 00:05:56,910 kind of patched in for, for instance, the string 137 00:05:56,910 --> 00:05:58,389 inquirer. That's one of my, one of my favorite 138 00:05:58,389 --> 00:06:00,520 ones. Right in the middle there, we have a 139 00:06:00,520 --> 00:06:02,470 check on the left. In Ruby, you simply ask 140 00:06:02,470 --> 00:06:06,120 if the environment string equals production. But in Rails, 141 00:06:06,120 --> 00:06:08,750 there's a thing called a string inquirer, which simply 142 00:06:08,750 --> 00:06:13,259 patches method_missing so that you can actually say, OK. 143 00:06:13,259 --> 00:06:16,240 Is the string actually containing the method that you 144 00:06:16,240 --> 00:06:18,919 just sent minus the question mark? And so, that's 145 00:06:18,919 --> 00:06:21,370 really all its doing - the thing on the 146 00:06:21,370 --> 00:06:22,669 left. 147 00:06:22,669 --> 00:06:26,960 Here's another one. So, in time, we can say 148 00:06:26,960 --> 00:06:30,419 beginning_of_day, we can say midnight, we can sat at_midnight, 149 00:06:30,419 --> 00:06:33,930 we can say at_beginning_of_day. We can say midday, noon, 150 00:06:33,930 --> 00:06:37,259 at_midday, at_noon, at_middle_of_day, right. They're all the same thing, 151 00:06:37,259 --> 00:06:41,979 and yet there's this really clean API that's exposed 152 00:06:41,979 --> 00:06:44,690 this whole change thing, right. It's fairly discoverable. Like, 153 00:06:44,690 --> 00:06:46,889 I could make a reasonable guess that if I 154 00:06:46,889 --> 00:06:49,569 said change_minute to something, or if I said change 155 00:06:49,569 --> 00:06:52,479 any piece of the time to something, it would 156 00:06:52,479 --> 00:06:55,069 be able to do exactly what I ask it 157 00:06:55,069 --> 00:06:57,370 to do just then. But instead we have these, 158 00:06:57,370 --> 00:07:00,020 these aliases that allow us to write code that's 159 00:07:00,020 --> 00:07:00,860 like English. 160 00:07:00,860 --> 00:07:03,669 Now, when I go into a coffee shop and 161 00:07:03,669 --> 00:07:05,199 I want something that's got a high caffeine content, 162 00:07:05,199 --> 00:07:07,400 I may order one of these. You all know 163 00:07:07,400 --> 00:07:10,220 what this is, right. This is coffee brewed by 164 00:07:10,220 --> 00:07:12,069 forcing a small amount of nearly boiling water under 165 00:07:12,069 --> 00:07:14,580 pressure through finely ground coffee beans. And that's what 166 00:07:14,580 --> 00:07:16,069 I go up to the counter and ask for, 167 00:07:16,069 --> 00:07:16,430 right. 168 00:07:16,430 --> 00:07:18,949 Nope. You know. They'd probably go, you mean an 169 00:07:18,949 --> 00:07:24,039 espresso, right? Because espresso is what we call a 170 00:07:24,039 --> 00:07:28,800 loan word. We borrowed that word from Italian because 171 00:07:28,800 --> 00:07:30,940 it was concise, it was a good way to 172 00:07:30,940 --> 00:07:33,789 say what it was that, that we wanted to 173 00:07:33,789 --> 00:07:36,069 say without all of those words, right. 174 00:07:36,069 --> 00:07:40,129 Ruby is a language in-and-of-itself. It borrows from English 175 00:07:40,129 --> 00:07:42,919 where it makes sense. But it is my opinion, 176 00:07:42,919 --> 00:07:44,690 anyway, that if there is a concise way to 177 00:07:44,690 --> 00:07:47,190 say something in Ruby, we don't necessarily need to 178 00:07:47,190 --> 00:07:49,500 borrow a loan word in English. You know how 179 00:07:49,500 --> 00:07:51,319 you sit across the table from that guy who 180 00:07:51,319 --> 00:07:53,440 always like to use a foreign word for something 181 00:07:53,440 --> 00:07:57,139 just to sound clever, right? Right. That's what we're 182 00:07:57,139 --> 00:08:00,470 doing, right. Like, it doesn't make a lot of 183 00:08:00,470 --> 00:08:00,789 sense. 184 00:08:00,789 --> 00:08:03,759 Now, here's one you may initially disagree with. I 185 00:08:03,759 --> 00:08:06,479 believe that Rails believes that models descend from ActiveRecord, 186 00:08:06,479 --> 00:08:09,870 or at the very least an ORM. Now, if 187 00:08:09,870 --> 00:08:12,300 you disagree with me, I have three words for 188 00:08:12,300 --> 00:08:17,289 you. Rails generate model. 189 00:08:17,289 --> 00:08:20,340 What do you get? You get an ActiveRecord subclass, 190 00:08:20,340 --> 00:08:23,259 right. Now, you might say, well that's silly, right. 191 00:08:23,259 --> 00:08:26,319 But this is the first exposure that Rails developers 192 00:08:26,319 --> 00:08:28,610 are likely to have to what goes in a 193 00:08:28,610 --> 00:08:31,199 model's directory, and I have talked to extremely smart 194 00:08:31,199 --> 00:08:34,030 developers who have told me that they went a 195 00:08:34,030 --> 00:08:36,679 number of years before they realized they could stick 196 00:08:36,679 --> 00:08:39,820 plain-old Ruby classes in app models, because they just 197 00:08:39,820 --> 00:08:42,679 thought that, that's not what models are. Right? 198 00:08:42,679 --> 00:08:45,280 And so, rightfully so then, Rails believes that the 199 00:08:45,280 --> 00:08:47,990 data is the domain, right. That's the ActiveRecord pattern. 200 00:08:47,990 --> 00:08:50,230 That's the whole point of it. And if you 201 00:08:50,230 --> 00:08:52,450 don't believe me, I'll show you some README information, 202 00:08:52,450 --> 00:08:53,170 right. 203 00:08:53,170 --> 00:08:55,990 The prime directive is that we're minimizing the code 204 00:08:55,990 --> 00:08:59,820 needed to build a real-world domain model. Lots of 205 00:08:59,820 --> 00:09:03,060 reflection and runtime extension is the understatement of the 206 00:09:03,060 --> 00:09:10,060 year. And magic is not inherently a bad word. 207 00:09:10,269 --> 00:09:13,690 Now, what this really comes down to is, is 208 00:09:13,690 --> 00:09:18,329 Rails was very much a reaction to very configuration-heavy 209 00:09:18,329 --> 00:09:24,130 frameworks in Java, XML files and the like. Big 210 00:09:24,130 --> 00:09:26,779 reaction to that, right. So what we had determined 211 00:09:26,779 --> 00:09:29,510 at that point was that configuration is the devil, 212 00:09:29,510 --> 00:09:33,640 right. And once you have, once you have determined 213 00:09:33,640 --> 00:09:35,779 that there is a greater evil out there, then 214 00:09:35,779 --> 00:09:38,010 a lot of lesser evils start to seem pretty 215 00:09:38,010 --> 00:09:41,089 great by comparison, right. So you can rationalize yourself 216 00:09:41,089 --> 00:09:43,760 into a really tricky spot. 217 00:09:43,760 --> 00:09:46,930 And so, our goal is to be able to 218 00:09:46,930 --> 00:09:50,600 write class Post inherits from ActiveRecord::Base end and have 219 00:09:50,600 --> 00:09:54,640 magic happen, right. Like, for instance, we infer, and 220 00:09:54,640 --> 00:09:56,190 I want to talk a little about, about one 221 00:09:56,190 --> 00:09:58,630 thing that we do in that case, right. We 222 00:09:58,630 --> 00:10:02,829 infer what the attributes should be on that, on 223 00:10:02,829 --> 00:10:05,170 that model without writing a single line of code. 224 00:10:05,170 --> 00:10:08,050 Now, there's a problem with that. Namely, that in 225 00:10:08,050 --> 00:10:10,149 order to infer the attribute names, you must first 226 00:10:10,149 --> 00:10:13,140 invent the universe. So I want to walk us 227 00:10:13,140 --> 00:10:17,279 through what that looks like. We're gonna do one 228 00:10:17,279 --> 00:10:19,360 deep dive into some Rails internals, and then I 229 00:10:19,360 --> 00:10:21,399 promise we'll come back up for air and we'll, 230 00:10:21,399 --> 00:10:24,630 we'll talk about happy things. 231 00:10:24,630 --> 00:10:28,740 So, so you might imagine pretty, pretty early on, 232 00:10:28,740 --> 00:10:32,740 that we're gonna go ahead and initialize a module, 233 00:10:32,740 --> 00:10:34,680 and we're gonna actually have a module to store 234 00:10:34,680 --> 00:10:36,920 our attribute methods in. That's actually something I kind 235 00:10:36,920 --> 00:10:39,529 of like, right, because as a Rubyist, I expect 236 00:10:39,529 --> 00:10:40,910 to be able to call super if I define 237 00:10:40,910 --> 00:10:42,399 my own method on the class, so that makes 238 00:10:42,399 --> 00:10:43,920 a lot of sense, right. 239 00:10:43,920 --> 00:10:45,050 So if we look at what happens when we 240 00:10:45,050 --> 00:10:47,649 generate the module, we have a new anonymous module 241 00:10:47,649 --> 00:10:50,040 that extends Mutex, cause we don't want to be 242 00:10:50,040 --> 00:10:53,070 modifying the module from two different threads. 243 00:10:53,070 --> 00:10:56,440 And, then in method_missing, we have this handy little 244 00:10:56,440 --> 00:11:02,029 hook that defines the attribute methods, right. And so, 245 00:11:02,029 --> 00:11:06,480 in method_missing, we call this every single time, right. 246 00:11:06,480 --> 00:11:09,290 And the idea being that once we've defined the 247 00:11:09,290 --> 00:11:10,829 methods, they're, we're not gonna hit method_missing, at least 248 00:11:10,829 --> 00:11:13,660 for those methods anymore. 249 00:11:13,660 --> 00:11:15,320 And so we bail out, if, in fact, we've 250 00:11:15,320 --> 00:11:21,110 already generated them. And we call super with column 251 00:11:21,110 --> 00:11:23,980 names, right. Now, where do we get column names 252 00:11:23,980 --> 00:11:26,750 from? Well, it's not there. In fact, method_missing was 253 00:11:26,750 --> 00:11:29,740 the only thing that actually sits on, on the 254 00:11:29,740 --> 00:11:31,529 instance level. The rest of the stuff that we're 255 00:11:31,529 --> 00:11:33,310 gonna be looking at sits on the singleton. It 256 00:11:33,310 --> 00:11:36,300 sits on the subclass of ActiveRecord itself as a 257 00:11:36,300 --> 00:11:37,430 class method. 258 00:11:37,430 --> 00:11:41,149 So, when we call super, we're actually calling super 259 00:11:41,149 --> 00:11:45,269 into ActiveModels. Definition of defining attributes, right. So we're 260 00:11:45,269 --> 00:11:47,600 saying, define attributes methods from ActiveModel. We're passing it 261 00:11:47,600 --> 00:11:50,860 the column names. So here's column names. Well, column 262 00:11:50,860 --> 00:11:54,610 names is, again, a singleton method. It knows that 263 00:11:54,610 --> 00:11:57,649 it needs columns, right. And below here, we have 264 00:11:57,649 --> 00:11:58,459 columns. 265 00:11:58,459 --> 00:12:01,889 Well, columns needs the connections, for starters, to the 266 00:12:01,889 --> 00:12:03,540 database to talk, to figure out, you know, what 267 00:12:03,540 --> 00:12:05,360 table it's gonna read from. And it also needs 268 00:12:05,360 --> 00:12:08,160 to determine table name, right. So now we need 269 00:12:08,160 --> 00:12:11,470 to know the table name. So we don't have 270 00:12:11,470 --> 00:12:13,620 the table name yet, so we call a reset 271 00:12:13,620 --> 00:12:18,480 table name, and most of the time I'm gonna 272 00:12:18,480 --> 00:12:20,529 skip past some of the, some of the more 273 00:12:20,529 --> 00:12:22,760 convoluted things and just talk about the compute table 274 00:12:22,760 --> 00:12:24,300 name, right. So we have to compute the table 275 00:12:24,300 --> 00:12:27,370 name. It makes sense, right? 276 00:12:27,370 --> 00:12:29,480 So, this is kind of a big method. Hopefully 277 00:12:29,480 --> 00:12:31,339 you all can see the, the part that matters, 278 00:12:31,339 --> 00:12:35,600 which is we call undecorated table name with the, 279 00:12:35,600 --> 00:12:37,760 again, we're sitting on the class. So name refers 280 00:12:37,760 --> 00:12:39,839 to class dot name, right. The string name of 281 00:12:39,839 --> 00:12:43,279 the class. The full module name. 282 00:12:43,279 --> 00:12:47,350 And, undecorated table name basically does exactly what you 283 00:12:47,350 --> 00:12:50,320 see here. Let's say we have a namespace model, 284 00:12:50,320 --> 00:12:54,740 Conferences::RailsConf becomes RailsConf becomes rails underscore conf becomes rails_confs, 285 00:12:54,740 --> 00:12:59,130 OK. Which is great. And then, of course, if 286 00:12:59,130 --> 00:13:01,320 we have Animals::Moose it becomes Moose it becomes moose 287 00:13:01,320 --> 00:13:05,360 it becomes mooses. Which makes lots of sense, right? 288 00:13:05,360 --> 00:13:12,130 Well, that means we need to handle irregular pluralization. 289 00:13:12,130 --> 00:13:14,170 So we check and we see whether or not 290 00:13:14,170 --> 00:13:18,940 there's a default pluralization to find for moose. There 291 00:13:18,940 --> 00:13:21,209 is not. There, there, there are some interesting ones, 292 00:13:21,209 --> 00:13:23,589 I think. We've got, like, sheep. We do have 293 00:13:23,589 --> 00:13:27,600 sheep, so we're at least in the ball park. 294 00:13:27,600 --> 00:13:30,769 We have jeans. We have fish. But we don't 295 00:13:30,769 --> 00:13:32,209 have moose. 296 00:13:32,209 --> 00:13:36,110 So, we go into an initializer and we set 297 00:13:36,110 --> 00:13:43,110 inflect.uncountable "moose" and then it works, right. But. Configuration. 298 00:13:43,649 --> 00:13:46,220 Or we can say self dot table_name equal 'moose' 299 00:13:46,220 --> 00:13:50,070 and then bypass all of that altogether, right. But, 300 00:13:50,070 --> 00:13:51,880 again, configuration. 301 00:13:51,880 --> 00:13:54,540 Now, if configuration is the devil and magic is 302 00:13:54,540 --> 00:13:58,529 the goal, then we have to think to ourselves, 303 00:13:58,529 --> 00:14:00,790 what is, what is magic, really? And, and an 304 00:14:00,790 --> 00:14:06,070 enjoyable magic trick is basically willful suspension of disbelief, 305 00:14:06,070 --> 00:14:09,459 right. So, that is, if this magician came up 306 00:14:09,459 --> 00:14:11,880 and said, I'm going to saw my assistant in 307 00:14:11,880 --> 00:14:14,519 half, and you didn't think, there's a trick here, 308 00:14:14,519 --> 00:14:17,009 like, it's based in the rules of reality, like, 309 00:14:17,009 --> 00:14:19,149 there's something going on. It would be pretty horrified, 310 00:14:19,149 --> 00:14:21,880 right. We'd be like, I don't be- where have 311 00:14:21,880 --> 00:14:24,480 I gone? Like, what is going on here, right? 312 00:14:24,480 --> 00:14:27,269 And so there is this level where we would 313 00:14:27,269 --> 00:14:29,970 do better to consider, how can we root this 314 00:14:29,970 --> 00:14:32,630 kind of magic in some reality that the average 315 00:14:32,630 --> 00:14:35,220 person is going to be able to understand? And 316 00:14:35,220 --> 00:14:37,509 then kind of build on that knowledge, sort of 317 00:14:37,509 --> 00:14:39,740 scaffold, if you will. And, otherwise, you end up 318 00:14:39,740 --> 00:14:41,720 with what I, what I referred to as douche 319 00:14:41,720 --> 00:14:44,310 bag magic, which magic that bites you, magic that 320 00:14:44,310 --> 00:14:47,070 screws you over in all sorts of wonderful ways. 321 00:14:47,070 --> 00:14:51,540 So, let's imagine, for a moment, a world, a 322 00:14:51,540 --> 00:14:55,060 world where we do have magic that we can 323 00:14:55,060 --> 00:15:01,250 understand. And, so let's just say we have ImaginaryRecord::Record 324 00:15:01,250 --> 00:15:04,600 that always asks us to configure a table name. 325 00:15:04,600 --> 00:15:07,389 That always asks us to define the attributes in 326 00:15:07,389 --> 00:15:10,820 a very mapper style, data mapper style. Right? 327 00:15:10,820 --> 00:15:12,980 Given an attribute name, tell it's how its to 328 00:15:12,980 --> 00:15:14,019 load the attributes. Tell it how to load the 329 00:15:14,019 --> 00:15:15,449 attributes. Maybe some other stuff. We don't, we're just, 330 00:15:15,449 --> 00:15:18,529 we're imagining here, right. We're, we're just in your 331 00:15:18,529 --> 00:15:20,019 imagination. 332 00:15:20,019 --> 00:15:22,630 And then let's say that we have a MagicRecord 333 00:15:22,630 --> 00:15:26,480 that inherits from the ImaginaryRecord::Record, and does all the 334 00:15:26,480 --> 00:15:30,880 same stuff that we did before, except it calls 335 00:15:30,880 --> 00:15:34,230 these methods on the class in order to set 336 00:15:34,230 --> 00:15:36,339 the table name programmatically, in order to set the 337 00:15:36,339 --> 00:15:37,009 attributes programmatically, right. 338 00:15:37,009 --> 00:15:41,279 Well, that would be pretty cool. We would have 339 00:15:41,279 --> 00:15:43,130 to make some trade offs, but we'd basically get 340 00:15:43,130 --> 00:15:45,509 to the point where we could do something like 341 00:15:45,509 --> 00:15:48,449 inherit from MagicRecord and get the exact same behavior 342 00:15:48,449 --> 00:15:51,930 as we wanted. But as a freebie, now we 343 00:15:51,930 --> 00:15:54,009 have the ability to drop down another layer, if 344 00:15:54,009 --> 00:15:57,000 we want. And to actually define this stuff with 345 00:15:57,000 --> 00:15:58,060 less magic. 346 00:15:58,060 --> 00:16:01,800 And you say, well that's great. So that's attributes. 347 00:16:01,800 --> 00:16:04,620 We kind of understand that. That's pretty simple, right. 348 00:16:04,620 --> 00:16:08,069 Big whoop. ActiveRecord also does all these other things, 349 00:16:08,069 --> 00:16:11,170 I mean, you know, it's got like attribute typecasting 350 00:16:11,170 --> 00:16:13,779 and associations and serializations and secure passwords and transactions 351 00:16:13,779 --> 00:16:17,000 and macro reflection and nested attributes, time stamps, lifecycle 352 00:16:17,000 --> 00:16:20,839 callbacks, validations, dirty tracking, mass assignment, sanitation, to name 353 00:16:20,839 --> 00:16:23,880 some, and oh, by the way, we have querying 354 00:16:23,880 --> 00:16:26,829 and persisting, right. That's kind of a important thing 355 00:16:26,829 --> 00:16:29,670 in a persistence library. 356 00:16:29,670 --> 00:16:33,630 And so, I say yeah. Yeah, exactly. That's. That's 357 00:16:33,630 --> 00:16:36,019 an interesting problem that we have, right. Because they're 358 00:16:36,019 --> 00:16:38,329 all kind of living in one place, and how 359 00:16:38,329 --> 00:16:43,149 do you expose this kind of interface, this kind 360 00:16:43,149 --> 00:16:47,060 of way of interacting with, with your library, to 361 00:16:47,060 --> 00:16:48,589 cover all of these things. And my answer would 362 00:16:48,589 --> 00:16:51,350 be basically that you, you don't. You, you allow 363 00:16:51,350 --> 00:16:53,329 this to tell you maybe I've got a crazy 364 00:16:53,329 --> 00:16:54,339 idea. 365 00:16:54,339 --> 00:16:58,699 So, this is the ancestry chain of, of an 366 00:16:58,699 --> 00:17:01,940 ActiveRecord::Base subclass. I just wanted to show it to 367 00:17:01,940 --> 00:17:08,040 you real quickly. Now, yeah. Yeah. Three cheers for 368 00:17:08,040 --> 00:17:11,959 the, for the ancestry chain of ActieRecord::Base. So, somebody's 369 00:17:11,959 --> 00:17:15,430 clapping. Oh no. Right. 370 00:17:15,430 --> 00:17:18,329 SO, in Rails we call this clarity. You may 371 00:17:18,329 --> 00:17:25,329 have heard that earlier. Because API surface area is 372 00:17:25,690 --> 00:17:29,420 irrelevant. We don't care about that. In other words, 373 00:17:29,420 --> 00:17:32,940 the Single Responsibility Principle is super simple for sufficiently 374 00:17:32,940 --> 00:17:38,170 large values of responsibility. Like, if you're responsibility is 375 00:17:38,170 --> 00:17:40,790 to do everything, then you just say, OK, gotta 376 00:17:40,790 --> 00:17:43,630 do everything. It's gotta work, right. That's my responsibility. 377 00:17:43,630 --> 00:17:47,320 Well, it works. All right. Done. 378 00:17:47,320 --> 00:17:50,360 And so awhile back, actually last weekend, I Tweeted 379 00:17:50,360 --> 00:17:55,020 some of these statistics about an observation on an, 380 00:17:55,020 --> 00:17:58,770 a brand new Rails 4.1 app, what a subclass 381 00:17:58,770 --> 00:18:02,100 of ActiveRecord has, what the view has, and what 382 00:18:02,100 --> 00:18:06,190 the controller has in terms of ancestors, public protected 383 00:18:06,190 --> 00:18:08,830 class methods, public protected instance methods, and same for 384 00:18:08,830 --> 00:18:10,780 private methods, right. 385 00:18:10,780 --> 00:18:13,940 Now, look. It may very well be that this 386 00:18:13,940 --> 00:18:16,260 is exactly the API size that we need. I'm 387 00:18:16,260 --> 00:18:17,750 not gonna argue that one way or the other 388 00:18:17,750 --> 00:18:21,070 right now. But what I will say is that 389 00:18:21,070 --> 00:18:23,560 there are other ways to get there. Just because 390 00:18:23,560 --> 00:18:25,340 we want these methods does not mean they all 391 00:18:25,340 --> 00:18:28,320 actually have to be implemented in modules that are 392 00:18:28,320 --> 00:18:31,960 included onto the class. 393 00:18:31,960 --> 00:18:34,140 And so what I'm getting at is that, it's 394 00:18:34,140 --> 00:18:37,220 very, very hard to keep track of just what 395 00:18:37,220 --> 00:18:40,340 you're doing. I've been writing Rails for over seven 396 00:18:40,340 --> 00:18:42,160 years. I'm not exactly sure how long at this 397 00:18:42,160 --> 00:18:45,590 point. But, I know that, since I've been doing 398 00:18:45,590 --> 00:18:48,790 it, I still have to have documentation open most 399 00:18:48,790 --> 00:18:51,250 of the time when I'm doing anything serious. Like, 400 00:18:51,250 --> 00:18:53,640 maybe I'm just dumb. Possible. I don't know. But 401 00:18:53,640 --> 00:18:57,390 I need documentation. It's a really big namespace to 402 00:18:57,390 --> 00:18:58,900 try to keep in your head all at one 403 00:18:58,900 --> 00:18:59,600 point. 404 00:18:59,600 --> 00:19:04,720 So, this is on, online at GitHub, and you 405 00:19:04,720 --> 00:19:07,150 are free to do science to verify my empirical 406 00:19:07,150 --> 00:19:11,480 observations and see whether or not they are accurate, 407 00:19:11,480 --> 00:19:13,310 and I would love to see PRs to this 408 00:19:13,310 --> 00:19:17,330 repo, actually, with, you know, different versions of Rails 409 00:19:17,330 --> 00:19:19,460 to see how things have changed, complexity-wise. 410 00:19:19,460 --> 00:19:22,480 Now, it's not enough really for ActiveRecord to just 411 00:19:22,480 --> 00:19:25,940 do this on its own. It actually encourages us 412 00:19:25,940 --> 00:19:31,020 to do this, right. Rails has this whole helper 413 00:19:31,020 --> 00:19:33,550 thing, right. And, let me give you an example 414 00:19:33,550 --> 00:19:36,220 of something I actually encountered and, I'm embarrassed to 415 00:19:36,220 --> 00:19:38,290 say, spent like half a day trouble shooting with 416 00:19:38,290 --> 00:19:40,390 the, with helpers. 417 00:19:40,390 --> 00:19:44,080 So, I decided I had a really great idea, 418 00:19:44,080 --> 00:19:45,840 and I was gonna use something that I heard 419 00:19:45,840 --> 00:19:48,840 that OO developers like to do, which is polymorphism, 420 00:19:48,840 --> 00:19:50,370 and use it at the view layer, right. And 421 00:19:50,370 --> 00:19:54,250 I'm like, I can have something that is summarizable, 422 00:19:54,250 --> 00:19:56,020 and so I might have a helper for posts 423 00:19:56,020 --> 00:19:57,940 that's summary, and I might have a helper for 424 00:19:57,940 --> 00:20:00,150 reviews that's summary. 425 00:20:00,150 --> 00:20:02,550 And I can share a partial that prints that 426 00:20:02,550 --> 00:20:06,170 summary in an appropriate way for that particular thing, 427 00:20:06,170 --> 00:20:08,500 right. That seemed pretty cool. So this is how 428 00:20:08,500 --> 00:20:12,060 it would look in a partial. And in development 429 00:20:12,060 --> 00:20:16,220 it worked wonderfully. It worked exactly the way I 430 00:20:16,220 --> 00:20:18,450 expected. And then I deployed to production. 431 00:20:18,450 --> 00:20:23,530 Now, how many of you think it worked? Right. 432 00:20:23,530 --> 00:20:25,840 How many of you think it didn't work. Well, 433 00:20:25,840 --> 00:20:29,150 it's kind of a trick question, because honestly you 434 00:20:29,150 --> 00:20:30,920 can't really tell me, because you don't have enough 435 00:20:30,920 --> 00:20:34,810 information right now. Because there's this thing, right. 436 00:20:34,810 --> 00:20:38,620 OK, so, seven years ago, there was a commit 437 00:20:38,620 --> 00:20:41,390 to Rails that said, we are going to make 438 00:20:41,390 --> 00:20:43,210 it default assumption you want all helpers all the 439 00:20:43,210 --> 00:20:48,830 time. No comment. 440 00:20:48,830 --> 00:20:51,950 And, for a long period of time, I'd like 441 00:20:51,950 --> 00:20:53,460 to imagine it was some kind of a dark 442 00:20:53,460 --> 00:20:55,530 age in Rails. There was really no way to 443 00:20:55,530 --> 00:20:57,640 opt out of this, per se, until a patch 444 00:20:57,640 --> 00:21:00,300 came in that added include all helpers as a 445 00:21:00,300 --> 00:21:03,580 configuration option. So I thought, this is great. I 446 00:21:03,580 --> 00:21:07,270 found this, now I found this after hours of 447 00:21:07,270 --> 00:21:10,050 searching, like, because I just somehow missed the memo 448 00:21:10,050 --> 00:21:11,570 that we had done that. It was way back 449 00:21:11,570 --> 00:21:13,290 in 2.3, like, this has been the way for 450 00:21:13,290 --> 00:21:14,430 awhile, right. 451 00:21:14,430 --> 00:21:17,070 But, like I just kind of assume, like, it's 452 00:21:17,070 --> 00:21:21,730 named post_helper, it should help posts. Not, like, other 453 00:21:21,730 --> 00:21:24,420 things. But that's not how it works. So there's 454 00:21:24,420 --> 00:21:28,110 this kind of big namespace, right. And so, I 455 00:21:28,110 --> 00:21:31,300 would recommend that nearly all of you consider adding 456 00:21:31,300 --> 00:21:35,470 this to to your application dot rb. You will 457 00:21:35,470 --> 00:21:37,800 be much more sane for it. If you're going 458 00:21:37,800 --> 00:21:40,290 to use helpers, at the very least, having a 459 00:21:40,290 --> 00:21:42,050 namespace that you can kind of control. If you 460 00:21:42,050 --> 00:21:44,460 want to be available to all controllers, then throw 461 00:21:44,460 --> 00:21:46,870 it in application_helper or have a module. You can 462 00:21:46,870 --> 00:21:48,840 still use modules, I hear. It works. 463 00:21:48,840 --> 00:21:50,920 Now, we did all this in the name of 464 00:21:50,920 --> 00:21:55,090 convenience, right. Convenience is, is going to trump everything 465 00:21:55,090 --> 00:21:58,120 else. We want convenient usage at expense of anything 466 00:21:58,120 --> 00:22:02,870 else. And, you know, so I own a house. 467 00:22:02,870 --> 00:22:05,900 And I think to myself often that, you know, 468 00:22:05,900 --> 00:22:09,520 when nature calls, I have, like, to get up 469 00:22:09,520 --> 00:22:12,140 and like, go to a special room to go 470 00:22:12,140 --> 00:22:14,760 do my business, right. 471 00:22:14,760 --> 00:22:15,850 [laughter] 472 00:22:15,850 --> 00:22:20,300 And I mean that's really inconvenient. So like, why 473 00:22:20,300 --> 00:22:23,000 don't I just install a toilet, like, in every 474 00:22:23,000 --> 00:22:26,300 room in the house, right? Because then, like, if 475 00:22:26,300 --> 00:22:28,700 I'm watching the tube, it doesn't matter you know. 476 00:22:28,700 --> 00:22:31,240 Do my thing. It's all good. but the problem 477 00:22:31,240 --> 00:22:34,150 with that is, right, that first off, you've got, 478 00:22:34,150 --> 00:22:37,340 like, plumbing now to help support this, this aspiration 479 00:22:37,340 --> 00:22:40,660 of having a toilet in every room. And plumbers 480 00:22:40,660 --> 00:22:43,020 are expensive and, like, stuff breaks and then it's 481 00:22:43,020 --> 00:22:45,210 like, I've got a leak and I've got damage 482 00:22:45,210 --> 00:22:48,120 and stuff, and then the other problem is, like, 483 00:22:48,120 --> 00:22:51,180 every room is a toilet, right. 484 00:22:51,180 --> 00:22:56,330 So, I would encourage you to consider that if 485 00:22:56,330 --> 00:22:58,590 this is kind of what you're looking for, if 486 00:22:58,590 --> 00:23:02,700 a giant namespace of, of, of methods and functions 487 00:23:02,700 --> 00:23:04,850 is what you would really like to have, then 488 00:23:04,850 --> 00:23:09,820 have I got the language for you. 489 00:23:09,820 --> 00:23:16,120 It is super convenient, like, everything is at arm's 490 00:23:16,120 --> 00:23:17,520 length. What's that? You want to do something with 491 00:23:17,520 --> 00:23:20,610 a string and an array, yeah, doesn't matter. MySQL, 492 00:23:20,610 --> 00:23:24,720 sure. Absolutely. I mean, just a thought. 493 00:23:24,720 --> 00:23:30,090 So now another, another Rails opinion is, who needs 494 00:23:30,090 --> 00:23:35,710 classes when we've got modules? And I say this 495 00:23:35,710 --> 00:23:40,330 primarily because of one interesting piece of code, which 496 00:23:40,330 --> 00:23:47,330 is ActiveSupport::Concern. So, ActiveSupport::Concern you may think is mainly 497 00:23:47,540 --> 00:23:50,420 for having a convention around having a class methods 498 00:23:50,420 --> 00:23:54,030 module inside your module. And instance methods and so 499 00:23:54,030 --> 00:23:56,520 forth. But it's not. 500 00:23:56,520 --> 00:24:00,140 The problem the it's designed to solve is that, 501 00:24:00,140 --> 00:24:02,710 in this world, the Ruby world, the one that 502 00:24:02,710 --> 00:24:06,890 we live in lots of times, we, we actually 503 00:24:06,890 --> 00:24:09,150 would have to include. There's a lot of extension 504 00:24:09,150 --> 00:24:11,420 onto a class, right, when you include a module 505 00:24:11,420 --> 00:24:13,180 in the Rails world. Like, a lot of the 506 00:24:13,180 --> 00:24:15,490 modules that Rails is built on go and do 507 00:24:15,490 --> 00:24:18,110 metaprogramming and add methods to the singleton or whatever 508 00:24:18,110 --> 00:24:19,980 onto the class itself, right. 509 00:24:19,980 --> 00:24:22,410 And if you're adding stuff to the singleton, then 510 00:24:22,410 --> 00:24:25,280 it's not sufficient for you to go ahead and, 511 00:24:25,280 --> 00:24:27,870 and do that in a module that is itself 512 00:24:27,870 --> 00:24:29,810 included, right. Because when it gets included in the 513 00:24:29,810 --> 00:24:32,230 module, it modifies the module singleton, not the class 514 00:24:32,230 --> 00:24:33,660 singleton. With me so far? 515 00:24:33,660 --> 00:24:36,540 Right. This is a huge problem. So. So let's 516 00:24:36,540 --> 00:24:39,610 solve it. Now, we have this ability to have 517 00:24:39,610 --> 00:24:44,790 dependencies that get trapped by ActiveSupport::Concern, so that each 518 00:24:44,790 --> 00:24:47,770 singleton knows what, what its dependencies are, and then 519 00:24:47,770 --> 00:24:51,650 at the time that you include the, the dependency 520 00:24:51,650 --> 00:24:53,750 that you're really looking for, it can also go 521 00:24:53,750 --> 00:24:55,580 back and include into your module all the other 522 00:24:55,580 --> 00:24:57,410 ones that it needed, and so then that way 523 00:24:57,410 --> 00:24:59,660 they can do their metaprogramming magic on your singleton 524 00:24:59,660 --> 00:25:01,650 instead of their singleton. 525 00:25:01,650 --> 00:25:04,890 It's great. And it's, you know, so what it 526 00:25:04,890 --> 00:25:06,650 is is that there was this, this, this problem. 527 00:25:06,650 --> 00:25:11,720 There was this problem that we had. And, you 528 00:25:11,720 --> 00:25:14,660 know, we decided to bundle a, a, a free 529 00:25:14,660 --> 00:25:18,850 razor with every yak. And, I mean, I guess 530 00:25:18,850 --> 00:25:22,530 that's one solution, sure. And so, so I've been 531 00:25:22,530 --> 00:25:25,430 thinking a lot about this lately. 532 00:25:25,430 --> 00:25:27,290 And one of the things that sort of bothers 533 00:25:27,290 --> 00:25:29,620 me is that, you know, we're regularly told not 534 00:25:29,620 --> 00:25:34,490 to, not to fight the framework, right. But our 535 00:25:34,490 --> 00:25:39,120 framework pretty actively fights the language. There are things 536 00:25:39,120 --> 00:25:41,800 that the language is saying, hey, this might be 537 00:25:41,800 --> 00:25:43,160 crazy. Maybe you don't want to do this. And 538 00:25:43,160 --> 00:25:46,980 we're like, I won't do what you tell me. 539 00:25:46,980 --> 00:25:50,630 I will do exactly what I want to do. 540 00:25:50,630 --> 00:25:54,590 And it encourages this, this kind of module-centric design. 541 00:25:54,590 --> 00:25:56,750 Limits the entry points that we can have. So, 542 00:25:56,750 --> 00:25:58,830 you know, Yehuda made a really great point, actually, 543 00:25:58,830 --> 00:26:00,960 when he talked about that we're kind of on 544 00:26:00,960 --> 00:26:03,990 the 400th story, right. And, and I agree. We 545 00:26:03,990 --> 00:26:06,600 are, we are like way up here in terms 546 00:26:06,600 --> 00:26:08,120 of abstraction. 547 00:26:08,120 --> 00:26:12,180 But, like, I've heard rumors that, like, maybe, on 548 00:26:12,180 --> 00:26:14,730 most buildings, like, those other floors like have people 549 00:26:14,730 --> 00:26:18,280 in them, and like, they do things. And like 550 00:26:18,280 --> 00:26:21,170 maybe you can not just be trapped on the 551 00:26:21,170 --> 00:26:23,100 400th floor forever, but maybe you want to like 552 00:26:23,100 --> 00:26:25,780 go down, cause like, I heard, like, on floor 553 00:26:25,780 --> 00:26:29,330 350 there's like an ice cream store, and like, 554 00:26:29,330 --> 00:26:31,710 I like ice cream. Right. So maybe I want 555 00:26:31,710 --> 00:26:33,020 to go down and have some ice cream. 556 00:26:33,020 --> 00:26:36,520 But, like, I can't. Because I could only do 557 00:26:36,520 --> 00:26:39,720 things with things that are instantiatable, right. And if 558 00:26:39,720 --> 00:26:42,110 everything is a module, I'm not instantiating that. I 559 00:26:42,110 --> 00:26:44,530 guess I could write my own class and include 560 00:26:44,530 --> 00:26:47,050 half of what's going on, but that seems like 561 00:26:47,050 --> 00:26:49,190 I'm just perpetuating the problem. 562 00:26:49,190 --> 00:26:54,470 So, here's another, here's another Rails opinion. Rails believes 563 00:26:54,470 --> 00:26:59,390 that your conventions suck. First example is, now, I 564 00:26:59,390 --> 00:27:01,250 know it's gonna be hard for you to believe, 565 00:27:01,250 --> 00:27:05,730 but there were conventions for building applications before Rails 566 00:27:05,730 --> 00:27:08,710 came out. Like, people were actually building - I 567 00:27:08,710 --> 00:27:12,820 know, it's a little weird. They were building web 568 00:27:12,820 --> 00:27:14,220 applications, and, and one of the things that they 569 00:27:14,220 --> 00:27:16,100 used was JavaScript, right. 570 00:27:16,100 --> 00:27:19,870 Now, love or hate JavaScript, it, it, it's here 571 00:27:19,870 --> 00:27:21,620 to stay at this point. We, we, we're gonna 572 00:27:21,620 --> 00:27:25,290 be writing it. And so, Rails, once upon a 573 00:27:25,290 --> 00:27:28,330 time - you guys remember this? You remember this? 574 00:27:28,330 --> 00:27:32,500 Like, let's, so. If this was before your time 575 00:27:32,500 --> 00:27:35,110 with Rails, we had, we had this great idea, 576 00:27:35,110 --> 00:27:39,580 right, which is, JavaScript's a pain to write. And 577 00:27:39,580 --> 00:27:44,220 let's write Ruby that writes JavaScript instead. And so 578 00:27:44,220 --> 00:27:46,820 we called that RJS, and you could write these, 579 00:27:46,820 --> 00:27:48,420 there were these methods that if you said page 580 00:27:48,420 --> 00:27:50,650 dot whatever, it would generate some JavaScript. And you 581 00:27:50,650 --> 00:27:52,720 could go look at the JavaScript and it was, 582 00:27:52,720 --> 00:27:55,000 you know, about what you would expect generated JavaScript 583 00:27:55,000 --> 00:27:57,260 to be. 584 00:27:57,260 --> 00:27:59,880 And then we decided, you know, OK, maybe that 585 00:27:59,880 --> 00:28:01,970 was crazy. But we're still not happy with the 586 00:28:01,970 --> 00:28:06,600 whole state that we have to write JavaScript. So 587 00:28:06,600 --> 00:28:09,860 we decided to use JavaScript that looks like Ruby, 588 00:28:09,860 --> 00:28:14,680 right. OK. Great. All right. Fine. I can see 589 00:28:14,680 --> 00:28:17,400 that. 590 00:28:17,400 --> 00:28:21,130 And then, at that point, now, we were at 591 00:28:21,130 --> 00:28:24,360 a point where there's this other convention, where like, 592 00:28:24,360 --> 00:28:26,810 if you're using jQuery, and many of us are, 593 00:28:26,810 --> 00:28:31,010 like, let's say, let's say that I want to 594 00:28:31,010 --> 00:28:33,530 render, I have decided I'm gonna be on the 595 00:28:33,530 --> 00:28:35,760 straight and narrow, I am going to render my, 596 00:28:35,760 --> 00:28:40,220 my, my views in Ruby. I want to render 597 00:28:40,220 --> 00:28:41,890 static html that I spit out. But I need 598 00:28:41,890 --> 00:28:45,870 some dynamic parts, and so I'm gonna render some, 599 00:28:45,870 --> 00:28:48,580 some JavaScript as well that's gonna do some things, 600 00:28:48,580 --> 00:28:49,960 right. Use jQuery. 601 00:28:49,960 --> 00:28:51,510 This is a pretty standard convention, right. I mean, 602 00:28:51,510 --> 00:28:53,470 how many of you have this exact code in 603 00:28:53,470 --> 00:28:56,220 your code base somewhere, right. If you're not raising 604 00:28:56,220 --> 00:29:00,530 your hand, I'm very shocked. So, we thought, you 605 00:29:00,530 --> 00:29:02,470 know, that's, that's great. It's really cool to be 606 00:29:02,470 --> 00:29:04,660 able to hook into $(document).ready and do some stuff. 607 00:29:04,660 --> 00:29:08,750 And so, so Rails said, that's a horrible idea. 608 00:29:08,750 --> 00:29:12,580 You should use Turbolinks. And so now, look, you 609 00:29:12,580 --> 00:29:16,340 can yank Turbolinks out of your gemfile and that's 610 00:29:16,340 --> 00:29:18,630 true. You can do that, right. But it's my 611 00:29:18,630 --> 00:29:22,900 opinion that convention should probably not completely break someone's 612 00:29:22,900 --> 00:29:25,430 expectations if they're doing server-side rendering, and this is 613 00:29:25,430 --> 00:29:27,410 something that you, you are going to run into 614 00:29:27,410 --> 00:29:28,990 if you're just starting out with Rails. You'll be 615 00:29:28,990 --> 00:29:30,330 like, well, why isn't this doing? Well, we don't 616 00:29:30,330 --> 00:29:31,840 fire. We don't fire the doc. 617 00:29:31,840 --> 00:29:34,780 No, there are, there are other gems that will 618 00:29:34,780 --> 00:29:37,140 make this seem like that is not the case. 619 00:29:37,140 --> 00:29:39,050 But the fact of the matter is, it's gonna 620 00:29:39,050 --> 00:29:42,180 bite you. So, so Rails said, you know, we 621 00:29:42,180 --> 00:29:45,840 have opinions about how you should write JavaScript. 622 00:29:45,840 --> 00:29:47,600 Rails has opinions about how you should maintain data 623 00:29:47,600 --> 00:29:54,600 integrity as well. And so in the Rails world, 624 00:29:54,970 --> 00:29:57,320 this is a typical, typical way to handle some, 625 00:29:57,320 --> 00:30:00,040 some validation of data integrity, right. Maybe you make 626 00:30:00,040 --> 00:30:02,800 sure that you have a customer, and you need 627 00:30:02,800 --> 00:30:07,150 a unique reference number, and you have a typo 628 00:30:07,150 --> 00:30:08,020 there. 629 00:30:08,020 --> 00:30:10,950 validates_associates. Validates :associates and :line_items, right. And you won't 630 00:30:10,950 --> 00:30:15,520 save an order unless its :line_items are valid. And 631 00:30:15,520 --> 00:30:20,020 that's really interesting to me, because objects, unfortunately, you 632 00:30:20,020 --> 00:30:22,820 know, they don't really understand their relations to other 633 00:30:22,820 --> 00:30:25,570 things very well, because those live somewhere else. They're 634 00:30:25,570 --> 00:30:28,840 in the data store separate, right. And, you know, 635 00:30:28,840 --> 00:30:30,790 I, I really think that it would be great, 636 00:30:30,790 --> 00:30:33,620 like, if there was some sort of a system 637 00:30:33,620 --> 00:30:36,150 that we could use. So, like, I don't know, 638 00:30:36,150 --> 00:30:41,270 it would be like a system for managing, I 639 00:30:41,270 --> 00:30:48,220 don't know, relational data, maybe? I don't know. 640 00:30:48,220 --> 00:30:50,890 It would be great if we had one of 641 00:30:50,890 --> 00:30:55,470 those. And it turns out that, like, we do. 642 00:30:55,470 --> 00:30:59,000 And they are, like, super good at understanding relationships 643 00:30:59,000 --> 00:31:02,920 between data. And they are super good at, at 644 00:31:02,920 --> 00:31:05,230 validating the data that goes in and out and 645 00:31:05,230 --> 00:31:09,900 ensuring that things are atomic, right, and that, that 646 00:31:09,900 --> 00:31:12,370 our updates are not gonna run into race conditions 647 00:31:12,370 --> 00:31:14,400 and the like, right? 648 00:31:14,400 --> 00:31:16,400 I mean, and I'm talking about, even the, let's 649 00:31:16,400 --> 00:31:21,590 say, less than civilized versions of databases, those are, 650 00:31:21,590 --> 00:31:24,070 those are also able, able to do pretty well 651 00:31:24,070 --> 00:31:27,720 at this. Because, Ruby, the Ruby land has to 652 00:31:27,720 --> 00:31:29,550 cross a process boundary to know any of this 653 00:31:29,550 --> 00:31:33,110 stuff, and that's pretty lossy, really. 654 00:31:33,110 --> 00:31:35,150 So, I don't think it would be fair, you 655 00:31:35,150 --> 00:31:36,960 know, I've griped a lot at this point about 656 00:31:36,960 --> 00:31:38,290 a few of the opinions that I think Rails 657 00:31:38,290 --> 00:31:41,310 has, and I feel like you came here hoping 658 00:31:41,310 --> 00:31:43,110 that I would offer you some solutions, right. I 659 00:31:43,110 --> 00:31:47,630 want to show you some solutions that I've found. 660 00:31:47,630 --> 00:31:53,530 These are my solutions. They look pretty nice, I 661 00:31:53,530 --> 00:31:54,300 think. 662 00:31:54,300 --> 00:31:55,080 Science. 663 00:31:55,080 --> 00:32:00,330 No. So, I've been doing this thing lately, and 664 00:32:00,330 --> 00:32:04,540 I'm calling it IDD. And that stands for Ignorance-Driven 665 00:32:04,540 --> 00:32:10,970 Development. It's really blissful. And it's this, this crazy 666 00:32:10,970 --> 00:32:15,970 idea that, like, maybe starting with Rails g model, 667 00:32:15,970 --> 00:32:19,400 like starting out thinking about your persistence, is maybe 668 00:32:19,400 --> 00:32:21,300 not the way to go. 669 00:32:21,300 --> 00:32:23,470 If you're thinking about your persistence for - I 670 00:32:23,470 --> 00:32:26,470 mean, I can tell you, all right. Raise your 671 00:32:26,470 --> 00:32:30,050 hand if you have stopped to consider what your 672 00:32:30,050 --> 00:32:32,130 database scheme, schema is gonna look like after you've 673 00:32:32,130 --> 00:32:33,920 typed Rails g model, and you're just kind of 674 00:32:33,920 --> 00:32:37,300 frozen there, like, crap. Analysis paralysis sets in, right. 675 00:32:37,300 --> 00:32:40,660 Because, like, migrations are a pain and databases are, 676 00:32:40,660 --> 00:32:43,300 ew, yuck. We want to do everything in Ruby, 677 00:32:43,300 --> 00:32:44,010 right? 678 00:32:44,010 --> 00:32:45,990 And, and so that's a problem, right, because I 679 00:32:45,990 --> 00:32:47,840 don't necessarily know what the best way to store 680 00:32:47,840 --> 00:32:49,630 my data is off the top of my head, 681 00:32:49,630 --> 00:32:52,710 right? I may find that out as I go. 682 00:32:52,710 --> 00:32:54,990 So here's a crazy idea. 683 00:32:54,990 --> 00:32:57,700 Start with Ruby and ignore persistence, off the bat. 684 00:32:57,700 --> 00:33:00,950 Like, probably that is not your domain. Your domain 685 00:33:00,950 --> 00:33:03,070 is not to be a CRUD app. Most of 686 00:33:03,070 --> 00:33:04,840 us here, anyway, our domain is not to just 687 00:33:04,840 --> 00:33:06,600 be a CRUD app, right. We have some business 688 00:33:06,600 --> 00:33:08,240 logic. 689 00:33:08,240 --> 00:33:11,490 And after you start with Ruby, then you start 690 00:33:11,490 --> 00:33:14,340 to identify the scary things, right. And this is 691 00:33:14,340 --> 00:33:16,240 like the part of our domain that we're really 692 00:33:16,240 --> 00:33:19,070 scared we're not gonna be able to implement. Like, 693 00:33:19,070 --> 00:33:21,020 what is the thing that's gonna be super hairy, 694 00:33:21,020 --> 00:33:22,960 that we're just kind of like, afraid to tackle, 695 00:33:22,960 --> 00:33:25,900 right. And removing the, like, the analysis paralysis that 696 00:33:25,900 --> 00:33:28,160 can set in when you're trying to figure out 697 00:33:28,160 --> 00:33:29,700 where your, what your data's gonna look like, while 698 00:33:29,700 --> 00:33:31,750 you're just kind of playing around with, with an 699 00:33:31,750 --> 00:33:33,870 algorithm, is great, because it gives you this sort 700 00:33:33,870 --> 00:33:35,670 of power to attack the scary things. You can 701 00:33:35,670 --> 00:33:39,950 do, I know it's crazy to say, some TDD 702 00:33:39,950 --> 00:33:41,860 and attack these scary things. 703 00:33:41,860 --> 00:33:44,010 And it's, the cost of experimentation is a lot 704 00:33:44,010 --> 00:33:46,100 lower when you're not messing around running migrations. You're 705 00:33:46,100 --> 00:33:49,720 just running super fast tests. Everything is really nice. 706 00:33:49,720 --> 00:33:51,420 And you validate that the business logic that you're 707 00:33:51,420 --> 00:33:54,080 trying to write is going to be sane before 708 00:33:54,080 --> 00:33:56,220 you go any further. 709 00:33:56,220 --> 00:33:58,540 And so, so what that might look like, for 710 00:33:58,540 --> 00:34:00,880 instance, is let's say I have a monster class, 711 00:34:00,880 --> 00:34:03,740 right. I simply give it some teeth and some 712 00:34:03,740 --> 00:34:06,080 claws, right, and it can bite and it can 713 00:34:06,080 --> 00:34:07,580 scratch, and I write my test. And let's just 714 00:34:07,580 --> 00:34:09,770 assume that biting and scratching is a very, very 715 00:34:09,770 --> 00:34:12,668 difficult thing for a monster to do, right. 716 00:34:12,668 --> 00:34:15,329 And, and so it starts out that way. And 717 00:34:15,329 --> 00:34:17,829 you gradually iterate on the things that you want 718 00:34:17,829 --> 00:34:20,960 your monster to do, right. And then what you 719 00:34:20,960 --> 00:34:25,080 find out is that, eventually, after having iterated through 720 00:34:25,080 --> 00:34:27,750 maybe, maybe many, many iterations on what this class 721 00:34:27,750 --> 00:34:30,600 looks like, what its collaborators might look like, you 722 00:34:30,600 --> 00:34:32,820 get to a point where you're like, OK. I 723 00:34:32,820 --> 00:34:34,510 know how to make this monster now. I know 724 00:34:34,510 --> 00:34:36,710 how to, how to tackle it, right. 725 00:34:36,710 --> 00:34:39,489 And now is a time for you to admit 726 00:34:39,489 --> 00:34:42,600 persistence. Right, now you start to think, OK, well, 727 00:34:42,600 --> 00:34:45,040 I've gotta persist this stuff somewhere. I have some, 728 00:34:45,040 --> 00:34:46,690 some things about this business logic that are gonna 729 00:34:46,690 --> 00:34:49,580 require me to save some data to the database. 730 00:34:49,580 --> 00:34:51,940 And so you decide, well, what database am I 731 00:34:51,940 --> 00:34:54,199 gonna use? Or is it gonna be NoSQL or 732 00:34:54,199 --> 00:34:55,489 is it gonna be SQL or is it gonna 733 00:34:55,489 --> 00:34:59,430 be, I don't know, something in memory? Right. 734 00:34:59,430 --> 00:35:03,030 And then from that point, let's just say you 735 00:35:03,030 --> 00:35:06,540 decide, well, now I'm gonna do some ActiveRecord. And 736 00:35:06,540 --> 00:35:09,330 so you say, all I do is now inherit 737 00:35:09,330 --> 00:35:11,270 from ActiveRecord::Base. The teeth and claws are no longer 738 00:35:11,270 --> 00:35:15,790 supplied via injection. But instead they come from relationships 739 00:35:15,790 --> 00:35:19,140 in some way, and we maybe have determined that 740 00:35:19,140 --> 00:35:23,530 we require that we have teeth and claws. 741 00:35:23,530 --> 00:35:25,100 And then, you guys are gonna think. You notice 742 00:35:25,100 --> 00:35:28,780 there's no methods here, right. Right. No methods. It's 743 00:35:28,780 --> 00:35:31,660 not doing anything yet, except the ActiveRecord stuff. You're 744 00:35:31,660 --> 00:35:33,900 gonna think I'm trolling you. But here's what I've 745 00:35:33,900 --> 00:35:35,610 started to do. 746 00:35:35,610 --> 00:35:41,050 I use modules. Now, the way I see it, 747 00:35:41,050 --> 00:35:42,650 you know, in firefighting there's this thing called a 748 00:35:42,650 --> 00:35:46,510 back fire, where it's like, OK, so, when they 749 00:35:46,510 --> 00:35:48,660 say, like, fight fire with fire, that's actually a 750 00:35:48,660 --> 00:35:51,040 thing. And like, I'm like, you know what, Rails, 751 00:35:51,040 --> 00:35:52,760 if you really wanna burn the whole place down, 752 00:35:52,760 --> 00:35:54,380 that's OK. I got my own little fire going 753 00:35:54,380 --> 00:35:56,910 over here. And it's gonna, it's gonna allow me 754 00:35:56,910 --> 00:35:59,290 to have some semblance of order. And let me 755 00:35:59,290 --> 00:36:01,560 show you what that looks like. And before you 756 00:36:01,560 --> 00:36:03,090 think that it won't work, I can only just 757 00:36:03,090 --> 00:36:05,840 say that it has worked for me. Give it 758 00:36:05,840 --> 00:36:08,620 a try. Strangely, I'm not going to prescribe that 759 00:36:08,620 --> 00:36:10,320 it's gonna be the solution for everyone. I know 760 00:36:10,320 --> 00:36:11,410 that's kind of the hip thing to do is 761 00:36:11,410 --> 00:36:14,720 to say, like, my solution will work for you. 762 00:36:14,720 --> 00:36:17,350 But it worked for me. 763 00:36:17,350 --> 00:36:19,560 And what it would look like is this. So 764 00:36:19,560 --> 00:36:23,860 I now have behaviors that I expose in modules, 765 00:36:23,860 --> 00:36:30,460 right. These behaviors are specifically intended to provide one 766 00:36:30,460 --> 00:36:35,170 isolated thing, one isolated capability to the persisted record, 767 00:36:35,170 --> 00:36:37,390 right. And so in this case, like, here is 768 00:36:37,390 --> 00:36:41,740 the biting module, for instance, right. And it knows 769 00:36:41,740 --> 00:36:43,270 how to bite. And let's say this is after 770 00:36:43,270 --> 00:36:45,040 we have developed all of our, all of our 771 00:36:45,040 --> 00:36:47,210 stuff in plain Ruby, right, this is what we 772 00:36:47,210 --> 00:36:49,510 landed on for what bite need to, need to 773 00:36:49,510 --> 00:36:52,340 perform, right. 774 00:36:52,340 --> 00:36:57,800 And so once we've done that, we can write 775 00:36:57,800 --> 00:37:00,510 a class, you know, we can actually just test 776 00:37:00,510 --> 00:37:03,240 against the class that limits the API service that 777 00:37:03,240 --> 00:37:06,110 our behavior interacts with. This was the goal. Like, 778 00:37:06,110 --> 00:37:10,130 this is why I do this at all, is 779 00:37:10,130 --> 00:37:13,170 because thinking about how I'm gonna interact with this, 780 00:37:13,170 --> 00:37:16,180 like, essentially infinite API that, that a lot of, 781 00:37:16,180 --> 00:37:19,080 a lot of Rails provides, particularly ActiveRecord provides in 782 00:37:19,080 --> 00:37:22,150 this case, is, is too hard for me. Cause 783 00:37:22,150 --> 00:37:24,580 I'm dumb, OK. So, what I need is some 784 00:37:24,580 --> 00:37:26,400 help to help me just be able to see 785 00:37:26,400 --> 00:37:28,180 into the test. This is the part of the 786 00:37:28,180 --> 00:37:29,550 API I care about. 787 00:37:29,550 --> 00:37:31,840 And you may be concerned about this. You may 788 00:37:31,840 --> 00:37:35,250 say, this looks a lot like ActiveSupport::Concern. I can 789 00:37:35,250 --> 00:37:36,600 understand why you would say that. Let me show 790 00:37:36,600 --> 00:37:39,250 you why that's not the case. So, earlier we 791 00:37:39,250 --> 00:37:44,930 talked about how ActiveSupport::Concern's primary goal is to solve 792 00:37:44,930 --> 00:37:48,210 the problem of modules that depend on other modules 793 00:37:48,210 --> 00:37:51,370 that modify their base class, right. 794 00:37:51,370 --> 00:37:53,770 The intention in this, and that might look like 795 00:37:53,770 --> 00:37:55,380 this. Like, let's say now there's like a whole 796 00:37:55,380 --> 00:37:58,290 fighting behavior that might bite and might scratch, we 797 00:37:58,290 --> 00:38:00,500 don't know yet. There may be some probability associated 798 00:38:00,500 --> 00:38:02,870 with it, that against a particular target or maybe 799 00:38:02,870 --> 00:38:05,250 more than one target or whatever, and so it 800 00:38:05,250 --> 00:38:08,830 sort of has this dependency, not just on the 801 00:38:08,830 --> 00:38:11,190 API that the class that it's being included into 802 00:38:11,190 --> 00:38:14,070 has, but also the stuff that's getting included into 803 00:38:14,070 --> 00:38:16,760 that class already. So it expects bite and scratch, 804 00:38:16,760 --> 00:38:19,830 which are provided by other two behaviors. So, that 805 00:38:19,830 --> 00:38:23,730 kind of thing becomes actually painful. That actually becomes 806 00:38:23,730 --> 00:38:27,350 painful when you're not using ActiveSupport::Concern. 807 00:38:27,350 --> 00:38:29,970 And so, what you actually have here is a 808 00:38:29,970 --> 00:38:32,130 canary in the coal mine, a sentinel animal, right. 809 00:38:32,130 --> 00:38:35,210 It's, it's something that's telling you, there's this thing 810 00:38:35,210 --> 00:38:38,240 that's doing more than one kind of thing that's 811 00:38:38,240 --> 00:38:43,100 more complex, right. And it really isn't fully encapsulated 812 00:38:43,100 --> 00:38:46,210 in the stuff that I've got so far. And 813 00:38:46,210 --> 00:38:48,720 it leads you to understand that maybe there's another 814 00:38:48,720 --> 00:38:51,280 thing. Like maybe there's an encounter, right, and it 815 00:38:51,280 --> 00:38:53,770 might include one or more combatants that select targets 816 00:38:53,770 --> 00:38:56,290 and do one of their actions, right. Either bite 817 00:38:56,290 --> 00:38:59,330 or scratch. All right. 818 00:38:59,330 --> 00:39:02,010 So, to kind of start to sum things up, 819 00:39:02,010 --> 00:39:04,360 it, we, we, a lot of us work in 820 00:39:04,360 --> 00:39:07,660 the startup world, right. And it's really frustrating and 821 00:39:07,660 --> 00:39:09,980 surprising to me that we embrace this idea of 822 00:39:09,980 --> 00:39:13,460 a minimal, minimum viable product in the startup world, 823 00:39:13,460 --> 00:39:15,520 right. Build the smallest thing that could possibly work 824 00:39:15,520 --> 00:39:17,270 and then go from there. 825 00:39:17,270 --> 00:39:21,900 I, I kind of feel like in software, the 826 00:39:21,900 --> 00:39:25,550 whole goal, really, is to make as few decisions 827 00:39:25,550 --> 00:39:28,540 as you possibly can in order to make, get 828 00:39:28,540 --> 00:39:31,420 the desired result, right. Every decision you defer till 829 00:39:31,420 --> 00:39:34,460 later is going to give you some capability to 830 00:39:34,460 --> 00:39:37,500 be able to react to change, right. So I 831 00:39:37,500 --> 00:39:39,690 would like to see us, both in Rails and 832 00:39:39,690 --> 00:39:41,420 in the software that we write, start off with 833 00:39:41,420 --> 00:39:46,380 fewer opinions. Start off with fewer assumptions. Make sure 834 00:39:46,380 --> 00:39:48,450 that the floors that we build have a purpose. 835 00:39:48,450 --> 00:39:49,650 One great way to do that is to make 836 00:39:49,650 --> 00:39:51,370 sure that you can instantiate a lot of the 837 00:39:51,370 --> 00:39:52,260 things, right. 838 00:39:52,260 --> 00:39:54,080 If you can instantiate a lot of the things 839 00:39:54,080 --> 00:39:55,530 then they must have a purpose that we can 840 00:39:55,530 --> 00:39:58,210 reason about. We can think about. As opposed to, 841 00:39:58,210 --> 00:40:01,580 well, they might modify five hundred methods on another 842 00:40:01,580 --> 00:40:06,570 class. And in general, just be a considerate software 843 00:40:06,570 --> 00:40:07,040 writer. 844 00:40:07,040 --> 00:40:09,260 Thanks for your time.