RailsConf 2013

Rails is Just Ruby

Rails is Just Ruby

by Jesse Wolgamott

In the video titled Rails is Just Ruby, hosted by Jesse Wolgamott at Rails Conf 2013, the primary focus is on demystifying the Rails framework by illustrating how it is fundamentally grounded in the Ruby programming language. Wolgamott emphasizes that what may initially appear as magical occurrences within Rails can be attributed to the effective patterns, APIs, and conventions inherited from Ruby, designed for developer happiness.

Key Points Discussed:

  • Understanding Rails' Magic: The session begins with Wolgamott's astonishment upon discovering Rails after working with other frameworks, highlighting the inherent design for maximizing developer happiness.

  • Development Workflow: Participants begin with preparations for a workshop that involves creating a simple beeper application that sends notifications through Twilio API, reinforcing practical engagement with Ruby’s capabilities.

  • Ruby's 'Magic' Features:

    • Blocks: Wolgamott discusses the concept of blocks in Ruby, describing them as versatile constructs that allow code to be passed into methods for flexible execution. He illustrates their utility in various scenarios such as looping through data and modifying user creation processes.
    • Before Filters: The importance of before filters in controllers is explored. Wolgamott illustrates how they can streamline code by controlling access and executing specific logic before user actions.
    • Callbacks in Active Record: The functionality of callbacks within Active Record is conveyed, where code can be executed at various points in a model's lifecycle, providing automation for critical actions such as validations and state changes.
  • Examples and Illustrations: Wolgamott uses humorous analogies like Gandalf and Darth Vader to explain the difference between perceived magic and understanding core principles in programming. He gives practical programming scenarios to demonstrate how Rails’ features provide significant business value.

  • Conclusion and Takeaways: The overarching theme concludes with the emphasis that Rails isn't magic; rather, it's the rich feature set of Ruby that empowers developers. Participants are encouraged to embrace the tools at their disposal to enhance their coding practice.

Overall, Wolgamott aims to make Rails appear less daunting, advocating for a deeper understanding of its foundation in Ruby to harness its full potential effectively.

00:00:12.259 Thank you! I said hi.
00:00:18.660 Hey! Um, very cool. I've had a great time here today. I am so excited for you to be learning.
00:00:25.980 Before we get into it, like we talked about, if you'll go to railsconf tutorials.com, there's a setup section where we clone a repository that we're going to use in the workshop. Then it runs `bundle`, and based on the Wi-Fi today, it may take about 40 minutes to actually install everything.
00:00:37.800 So, if you'll start that now, while I give my little preamble here, it may be ready for you in about 40 minutes.
00:00:43.140 What we're going to do, as Jeff said, is I'm going to babble on here about Ruby for about 40 minutes or so, take a break, and then we'll do a workshop where we're going to create a little beeper application that sends texts and emails when errors are reported—all through the magic of Ruby. It will use the Twilio API, so if you want to set that up too, that may help things along a little later.
00:01:04.500 All right, so back to the idea that Rails is just Ruby. When I first saw Rails, I was like, 'Whoa!' I was literally astonished at how cool it was. I'd been doing software development for a while in the .NET space, and previously some Perl, and seeing Rails was just unbelievable.
00:01:21.900 It seemed crazy how magical it was, how much was built-in to make the developer happy. The more you learn about how all of this works together, the more you realize that Rails is a great collection of patterns and APIs. It got its entire ecosystem from the Ruby ecosystem, which is set up for maximum developer happiness.
00:01:36.119 The entire Rails ecosystem is basically one big hippie commune, and we're all making sure that we're happy. That's so empowering and so cool!
00:01:42.300 So what we're going to do today is look at a couple of different ways that the Ruby part of Rails helps make Rails, well, Rails.
00:01:51.660 There are aspects of Rails that just seem magical, and I keep using this word, 'magical,' as sort of a theme while attempting to teach the Ruby part of Rails. There are things that Rails can do where it becomes so easy for you to provide great value to your business and to the awesome websites you're creating.
00:02:11.220 You can easily log every page load that happens. For instance, go into a controller and log every time something happens—not necessarily to a log file, but you can create an access log for HIPAA applications, and this would be trivial to do in Rails. In other frameworks, it might not be so straightforward.
00:02:35.700 Consider the ability to send updates whenever a record is updated. You can transmit those updates to another service, allowing for a full-text search engine optimized for lexical pattern searching. Anytime something changes, you can send in those changes. This is pretty magical stuff, and I know, right now, we might be like, 'Oh, wow.' But the ability to do this really is game-changing.
00:02:50.820 The entire idea here is that it's not really magic; it's Ruby. But when you're first getting into it, it can feel a little magical, especially when stuff just works with a well-crafted API that listens to what you're doing. Sometimes you have someone who has been working on it for a couple of years, saying, 'Oh, you just do this,' and you're like, 'Are you really?'
00:03:30.660 Now, let's take a whimsical analogy. Do you think Gandalf thinks about what he's doing as magic? I'm not sure he does. He knows the commands for his staff or whatever, and it just works for him. In his mind, he's just using an API. Perhaps a better example might be Darth Vader. He has actual magic, listening to people's thoughts from halfway across the galaxy, seeing the past and future, and using mind powers to choke people.
00:03:51.060 To him, though, it might not be magic; he's just figured out the APIs of the midi-chlorians that are throughout his body. Possibly, we just need to understand the APIs of Rails and Ruby. I'm glad no one left after my disparaging comments about Gandalf the wizard. You can talk to me afterward if I hurt your feelings.
00:04:06.120 You guys are wizards, right? When businesspeople ask you to do things, they often come up and say, 'I have no idea how long this will take. It could be several weeks.' They don't even know, and by the time they're done explaining, you may have already built a prototype because it was just about implementing a plugin or gem or whatever.
00:04:22.920 To them, what you did seems just mind-blowing. But the reason all of this exists is so that we can create business value, which is the whole reason we get paid to do this. That's why we provide back to open source, and Rails helps us along the way.
00:04:41.220 A couple of different ways that Rails assists us that we will cover include blocks, before filters, callbacks, models, and inheritance. We'll look at inheritance specifically in a controller, but it all starts with the block.
00:05:00.780 So, some Rails developers were asking, 'What is it about Rails that makes it feel so... Railsy?' What's the one feature that really enables all of the rest? At first, I thought it would be something like `method_missing` or some other dynamic nature. Maybe it was Ruby's ability to have config variables without declaring them first, but no, it wasn't those.
00:05:20.230 It was blocks—the ability to send information in and change your program's behavior. We're going to spend some time diving into blocks. A block, in this context, is the part of code that exists between the `do` and the `end` keywords.
00:05:44.580 Inside the block, you have code that represents executable logic. This code is essentially a closure, something you send in to perform at other times. For example, if you open IRB and run a code snippet where you put 'YOLO', you’ll see it get printed out 10 times. That's valuable code right there!
00:06:07.860 You might have seen similar patterns in Rails templating. When looping over users, you will often use a block syntax. The block runs from `do` to `end`, taking each user as input and permitting you to produce outputs accordingly.
00:06:24.840 You might also see this where you're creating a user and passing a block into the `create` method, setting the user's properties in that context.
00:06:38.940 We're also able to loop over collections using enumerable functions like `map`, which will create a new array of the results. Blocks can also employ alternate syntax using curly braces for single lines of code. If the code spans multiple lines, stick with `do...end`; for single lines, prefer braces.
00:06:55.560 Once you start identifying blocks, you'll see that they are ubiquitous throughout Ruby code. They are present in config values, allowing the code to be executed later.
00:07:08.760 Every method in Ruby can implicitly receive a block, and while you don't have to do anything special for a block to be passed in, if you want to use the block you've received, you need to yield to it. Yielding to the block is most commonly seen in Rails applications within views.
00:07:22.920 In Rails, for instance, the application template yields to the specific template being called. So when you yield to the main view, you're allowing that block to execute.
00:07:39.240 You can also have parameters for blocks, but a little gotcha is that if you don't send enough parameters, you won’t get an error; it will just return `nil` instead.
00:07:57.660 A quick visualization of how it works is like this: for each argument sent, it comes to the local value parameters of the block. Imagine taking each pair from an array and inserting them into your block.
00:08:14.580 A few advanced tips: don't use `return` in your blocks unless you really want to, because that return may jump out of the invoking method instead of returning within it. It's unlikely that you would want to do this.
00:08:32.640 Instead, remember that Ruby itself provides implicit returns at the end of each method. So, think of the block’s last line as the return value you want, saving the need to use `return` explicitly.
00:08:51.720 Sometimes, you might need to execute a piece of code that could fail, and when it does, you still want to have it execute. Richard, who is here and just got married, created a gem called `river_retry`. You can set how many times you want to attempt re-running a block if it fails due to an exception.
00:09:08.880 In this setup, you specify how many times to retry, and if there's an exception within the network communication, it will re-attempt the defined number of times. This is an example of a human trick that Ruby handles gracefully, made possible through blocks.
00:09:22.560 Next, let’s talk about before filters, which occur in a controller. In our vocabulary, controllers comprise actions that appear like methods. Actions are interactions with the browser.
00:09:34.260 For instance, you might show a user, create a user, or list users with the index. You can apply before filters that execute code either before or after each of these interactions.
00:09:46.920 Before filters can halt execution, and this gives them even more power—if a before filter returns false or redirects, the actual code will not execute, thus allowing you to enforce certain conditions.
00:10:04.860 For example, when displaying or creating a user, you could check if the user has the rights to perform these actions. This also helps to dry up your code, as authorization can be managed uniformly between creating and editing.
00:10:25.080 You could easily have a before filter in your application that checks for user login and redirects to the login page if the user isn't authenticated. Here's an example of that in action.
00:10:38.760 We implemented a before filter that ensures users are logged in. If not, they'll be redirected to the login page. You could establish this filter for any action, ensuring that the user is authenticated before any record is fetched or displayed.
00:10:54.360 Often, instead of using block syntax, we set method names when applying before filters. So we declare a before filter, specify a method name, and the same functionality applies—this is a common practice.
00:11:12.360 Now, we can set this up in the application controller, thereby allowing any inheriting controllers to utilize it without repeatedly defining the same before filter. This approach secures every request in your application against unauthorized access.
00:11:28.680 Moreover, you also have the ability to skip certain before filters. For example, if you have a posts controller behind a paywall, but for a specified share token, you want to grant access, you can accomplish that using the skip_before_filter method.
00:11:43.320 This allows you to create a simple public and private controller structure, fostering a hierarchy throughout your application—ensuring that if your API controller is protected, it applies standards across all API requests.
00:12:00.960 Next, let's discuss callbacks. Last year at RailsConf in Austin, Texas, I gave a talk about why you should be cautious in using callbacks in your model applications. While they can be powerful, they can also lead to complications.
00:12:16.680 But for now, I want to focus on the powerful aspects of callbacks. They allow you to define code that executes later during the lifecycle of an Active Record.
00:12:32.040 For example, an obvious case might be to do something after a record is created, such as creating another record. I appreciate using callbacks like before validation or before save, where you can execute code just before a record is saved.
00:12:51.180 This capability is very cool. Some of the most common callbacks used include before validation, before save, after save, and after destroy.
00:13:06.840 Within these callbacks, you have the flexibility to insert your logic. For instance, with before save, if you set it to return false, it will halt the saving process. Meanwhile, in before validation, you can write code that helps a model pass its validations.
00:13:25.440 Another great use for before validation is setting default values—such as when a user hasn’t specified one.
00:13:43.380 Let me present you with two examples: one involves a common scenario—a user model, where we define an action to downcase email addresses before validations. You may wonder why one would downcase emails, particularly if using Postgres.
00:14:03.540 The issue arises when someone inputs an email with a capital letter—searches won't match, unless configured for case-insensitivity. In most cases, it’s simpler to just downcase all your emails when saving.
00:14:22.860 Before validations are helpful for formatting and setting default values; I strongly support their use. Another case often seen in the wild relates to full-text search indexing.
00:14:39.960 When you utilize something like Solr, you want to ensure that anytime a method is added or updated, it gets reflected in the index. Without callbacks, you might need to re-index your entire database regularly, leading to lagging or out-of-date records.
00:14:56.580 Instead, with callbacks, you can update the index in real-time whenever a model changes. This creates a consistent lifecycle that you can hook into seamlessly.
00:15:12.660 Using Sunspot, you call the `searchable` method and pass in a block, allowing full-text search configurations. Now, anytime your model is modified, it automatically handles updating the index.
00:15:27.420 To use it, you’d just call `post.search` with search terms, and Sunspot will manage the interaction with the Solr server to return results and maintain local data.
00:15:41.640 The Sunspot setup utilizes after-destroy callbacks, which automatically handle the removal from the index when a record is deleted. This functionality exemplifies how blocks make these processes efficient.
00:15:56.760 Now, let’s move on to the workshop segment. Does anyone have questions on anything we've discussed so far?
00:16:09.780 Yes?
00:16:15.900 The question pertains to passing data into blocks or closures. Generally, you'd yield with a specific value, which can go into it, akin to enumerating over an array. If you needed to implement closure-like behavior, you might need a lambda, which you actually call instead of yielding.
00:16:35.280 This allows maintaining access to outer variables and enabling monitoring during changes. However, regular blocks don't inherently work that way.
00:16:53.940 Can you differentiate between blocks, lambdas, and procs? Those distinctions can be tricky, but they are vital.
00:17:10.560 If you deal with callbacks, keep in mind that having many side effects tied to saving a model makes it complex to discern the sequence of operations occurring with each save. This increases the testing difficulty, as you have to account for those side effects in your tests.
00:17:32.520 You will have to decide whether to stub service calls or use fakes in your testing. In unrelated tests that save a record, you may need to manage whether the callback will trigger, adding a layer of complexity.
00:17:51.000 For example, if saving a model triggers calls to an external service, making testing for this process tight is crucial, but it branches out widely into your other tests.
00:18:08.820 Now, regarding your question about the critical nature of text messaging for the workshop—it's more of a cool feature. It's not compulsory, so don’t stress about it.
00:18:26.520 Let’s check if anyone faced issues cloning or bundling the repository.
00:18:43.080 When cloning, if you receive SSH key issues, it likely indicates that GitHub doesn't recognize your credentials. Switch to an HTTPS link for the repository; I can assist with this.
00:18:56.550 So, in terms of our schedule, we will take a five-minute break, after which we'll work on creating the Beeper program.
00:19:13.320 Think of the Beeper program as akin to a Honeybadger or AirBrake-like application that responds to errors with notifications. The repository is set to receive errors, and our aim today is to add functionalities for sending notifications.
00:19:34.680 For critical errors, we'll send text messages, while for warnings, we'll send emails to the developer on call.
00:19:48.480 Thank you!