├── a-minimalists-guide-to-vim.md └── understanding-require-in-ruby.md /a-minimalists-guide-to-vim.md: -------------------------------------------------------------------------------- 1 | A Minimalist's Guide to Vim 2 | =========================== 3 | #### Author: Eric Mathison 4 | #### Date: May 14, 2018 5 | #### Last edited: May 14, 2018 6 | 7 | 8 | People love to customize Vim. That's great to an extent. It's terrible when it means loosing some of the really great advantages of doing things "The Vim Way"®. By all means, try things out, mix it up, and see what works for you. This is the story my journey through customizing Vim, what I learned in the process, and why I've decided to go back to the basics. 9 | 10 | Get in, Get out 11 | --------------- 12 | Emacs users love to live in Emacs. This is not the Vim way. Vim is known for getting in and getting out. I've noticed a trend however of doing more and more from inside Vim. Examples include the ctrlp plugin (a fuzzy file finder), running tests from inside Vim, and even handling version control à la Fugitive (a plugin for git). This workflow is essentially treating Vim like Emacs. But if Emacs were a tank, Vim would be a dirtbike. As a Vim user, I prefer to let Vim do one thing and do it well—editing text. 13 | 14 | The Journey 15 | ----------- 16 | I remember watching someone use ctrlp for the first time. I was amazed at how fast they went from file to file—all with just a few keystrokes. I joined the bandwagon. After a while though it dawned on me that finding files wasn't really the domain of an editor. I thought, there must be a way to fuzzy match a file and simply pass it to Vim as in: `vi some/file.rb`. In fact there was! It’s called fzf (https://github.com/junegunn/fzf). At some point though, I realized if I wanted to go to the file I just edited I didn't really need any special plugins or fancy whizbangs. It's as simple as typing `vi` and then hitting `` twice. All my history is at the tip of my fingers. `` follows my steps backward and `` jumps instantly forward through anything I've been editing. Then again, with a shell like Fish that seems to know what file I want to edit before I do and gives file completion hints right out of the box, even this seems like too much typing sometimes. 17 | 18 | Learn Useful Defaults, Customize When Critical 19 | ---------------------------------------------- 20 | Being able to use the same Vim setup just about anywhere is pretty incredible. Exiting Vim is one of those critical places where customization is key though. I remap `q` and `w` to `ZQ` and `ZZ` respectively. So on my setup, to exit Vim without saving, I type `\q`. Two characters and I'm gone. I hate the shift key. Just think, `:q!` requires hitting shift twice! With another key awkwardly placed in between! `:wq` is a bit more reasonable so I often just stick with the default there but it really shouldn't take an eternity to open and close Vim. Get in, get the job done, and get out. That's the Vim way. 21 | -------------------------------------------------------------------------------- /understanding-require-in-ruby.md: -------------------------------------------------------------------------------- 1 | Understanding `require` and Friends in Ruby 2 | =========================================== 3 | #### Author: Eric Mathison 4 | #### Date: September 14, 2013 5 | #### Last edited: June 21, 2024 6 | 7 | Ruby's `require` method is a tool for referencing and executing code that is 8 | not actually contained in the current file. My initial attempts at using 9 | `require` left me a bit confused. Not until later did I realize that Ruby's 10 | `require` method sits atop something more organized and elegant than I had 11 | realized. It turns out that `require`'s main use case is generally not one off, 12 | relative references to other random Ruby files as I had expected. Instead, 13 | `require` is generally used to look in certain pre-determined directory 14 | locations for Ruby libraries. I had previously sort of assumed that a require 15 | in Ruby would be something like the relative references to an image in CSS or a 16 | reference to a JavaScript file in HTML. Not so. In fact, Ruby's `require` seems 17 | to have drawn several concepts from the UNIX environment. 18 | 19 | So How Does Ruby's `require` Work Anyway? 20 | --------------------------------------- 21 | The best way to think of `require` is in relation to the UNIX `$PATH` variable. 22 | Just by way of a refresher, the `$PATH` variable in UNIX contains a list of 23 | directories where executables can be found. So when you type the name of a 24 | program on any UNIX terminal, your computer is looking through the executable 25 | files in the directories specified in your `$PATH` variable. `require` does 26 | something very similar. When, for example, you write `require 'set'` at the top 27 | of your Ruby file, you are telling Ruby to look through a bunch of directories 28 | for a library called set.rb (Ruby's set library). 29 | 30 | So where does Ruby look for set.rb? Well, once again, Ruby has something very 31 | similar to UNIX's `$PATH` variable. It is the global variable `$LOAD_PATH` also 32 | sometimes known by it's ugly and undescriptive alias `$:` (which I don't suggest 33 | using by the way--short though it may be). It is an array of directory names 34 | where Ruby looks when it comes across a `require`. 35 | 36 | Here's where the analogy falls short however. The UNIX `$PATH` generally 37 | contains a list of bin directories while the Ruby `$LOAD_PATH` contains an array 38 | of lib directories. Well, what on earth are lib and bin directories and what 39 | difference does it make? The lib and bin directories are another Ruby concept 40 | which originally comes from UNIX. A bin directory is a place for standalone 41 | executables. The name bin is a reference to binary files (as opposed to plain 42 | text files) since before the days of ubiquitous scripting languages, executables 43 | needed to be compiled from source into a binary file. Ruby, of course, is an 44 | interpreted language and doesn't need to be compiled but the concept of 45 | standalone executables still applies. A lib directory on the other hand is where 46 | library code goes. This is the code you reference in other code. Referencing 47 | library code is the whole reason we need `require`s in the first place. 48 | 49 | When you require a library you are telling that code to be executed any time the 50 | file containing the `require` is executed. The required file is executed only 51 | once. Even if the require is repeated in the same file (why anyone would want to 52 | do this I don't know) it will be executed only once\*. This is because Ruby 53 | checks whether the `$LOADED_FEATURES` variable a.k.a `$"` (not to be confused 54 | with `$LOAD_PATH`) already contains the name of the required file before 55 | executing 56 | 57 | The really nice thing about the way `require` works in combination with the load 58 | path is that as long as a library is in the load path, there is no need to 59 | specify the full path or even to know where exactly it is located. You don't 60 | even need to put the '.rb' on the end since that is implicit. All you need to 61 | put is the extensionless name of the file. Personally, I think this makes for 62 | some very clean looking code. 63 | 64 | It is important to also realize that in your application, there is generally no 65 | need to add directories to the load path manually as this is the environment's 66 | job. I mentioned above that the `$LOAD_PATH` contains an array of lib directory 67 | paths. RubyGems will, for example, automatically add the lib directory of gems 68 | installed on your computer to the load path. Well, that's actually only mostly 69 | true. If you *actually* run a Ruby script that just outputs `$LOAD_PATH` without 70 | doing anything else, you won't see every single installed gem's load path 71 | listed. This is because RubyGems lazily loads Gem's lib directories. So if you 72 | want to see your gem's lib directory listed in the load path you have to 73 | actually require it first. But things work essentially the same as if every 74 | single gem's lib directory was on the load path. 75 | 76 | Slightly unrelated to the topic of this article but perhaps also interesting to 77 | note is that RubyGems will also add a gem's bin directory to the UNIX `$PATH` 78 | variable so that a gem's executables can be run from the terminal. 79 | 80 | Understanding `load` 81 | -------------------- 82 | The `load` method is very similar to `require`. The main differences is that it 83 | will run the referenced code as many times as `load` calls it. As I mentioned 84 | above, `require` only runs the first time. 85 | 86 | `load` must be given the '.rb' file extension because it won't be inferred like 87 | it was with `require`. 88 | 89 | All in all, I would say that `load` has a fairly small amount of usefulness. 90 | Probably it's main use case is re-running a file from a Ruby REPL (like pry or 91 | irb) after making some edits. It's also very helpful when you need to load ruby 92 | files that do not have a .rb extension since `require` will automatically look 93 | for files ending in .rb. This situation can occur when trying to load ruby 94 | script files or executables which tend not to have an extension. 95 | 96 | Understanding `require_relative` 97 | -------------------------------- 98 | `require_relative` is essentially what I had originally thought `require` would 99 | be used for. If you want to reference a file relative to another file, not 100 | treat it like a library, and bypass the load path, this is the tool for you. 101 | 102 | In order to understand the need for `require_relative`, we must understand a bit 103 | more about `require`. So far, the only use I've mentioned for `require` is 104 | executing code on the load path (code that would be considered a library). 105 | That's for good reason. That's what it is good for and you probably shouldn't be 106 | using `require` for anything else. 107 | 108 | In the past (Ruby 1.8 and earlier), if you wanted to do a one off `require` 109 | without managing the load path, the best way would have been to generate the 110 | full path to that file and pass it as an argument to `require`. It would look 111 | something like this: 112 | 113 | require File.expand_path('my_file', File.dirname(__FILE__)) 114 | 115 | `File.expand_path` gives the full path to the file specified in the first 116 | argument. Specifying the second argument essentially says, look for my\_file.rb 117 | relative to such and such directory. `File.dirname(__FILE__)` returns the 118 | directory path for the current file (that this line was written in). So put 119 | together, `require` is getting passed the full path to my\_file.rb which is the 120 | file sitting in the same directory in which this line was written. Another way 121 | of writing the same thing looks like this: 122 | 123 | require File.expand_path('../my_file', __FILE__) 124 | 125 | The difference here is that the "directory" we are passing in the second 126 | parameter isn't actually a directory. It is just the current file. Fortunately, 127 | `File.expand_path` doesn't care since theoretically, we could make a directory 128 | called `'current_file.rb'` strange as that would be. Assuming I'm running this 129 | line from my home directory, without the `'../'` before the file name in the 130 | first parameter, the string we are passing to `require` would look something 131 | like this: `'/home/eric/current_file.rb/myfile.rb'`. From `File.expand_path`'s 132 | perspective, adding the `'../'` brings us up a directory but from our 133 | perspective, it simply causes current\_file.rb to be removed from the path. So, 134 | with `'../'` back in place, the path would expand to `'/home/eric/my_file.rb'`. 135 | 136 | Let me back up and explain why passing `require` the full path to a file would 137 | even be necessary. When I write something like `require '../my_file.rb'`, that 138 | path is relative to the current working directory of the process executing this 139 | line NOT necessarily the file it was written in. That's important and it means 140 | that depending on what directory you are in when you run `ruby current_file.rb`, 141 | your code may or may not be able to find your relative reference to my\_file.rb. 142 | Yikes! 143 | 144 | Enter `require_relative` stage left. `require_relative` does essentially what 145 | the above two examples using `require` do except with the added benefit of a 146 | clean syntax. So instead of needing that massive monstrosity, all that 147 | `require_relative` needs to do is `require_relative 'myfile'` and my file will 148 | be referenced relative to the file containing that line (current\_file.rb in our 149 | example). 150 | 151 | Also note that even if you are running current\_file.rb from it's containing 152 | directory (so that the current working directory of the process is the same as 153 | the location of current\_file.rb), it is not possible to do something like 154 | `require 'myfile'` although `require './myfile'` would work. This is because 155 | since Ruby 1.9.2, the current working directory is no longer part of the load 156 | path. In the UNIX world, this is considered a good security practice since it 157 | avoids the issue of accidentally running an unexpected script by simply 158 | executing a program from a directory that just happens to have a file with the 159 | same name. Since `require_relative` is requiring relative to the current file 160 | instead of the current process, it doesn't have this security issue. That's one 161 | more reason to use `require_relative` for relative requires. 162 | 163 | One last note about `require_relative`: Have you ever noticed that using 164 | `require_relative` doesn't work on a Ruby REPL like pry? Think about it. If 165 | `require_relative` is requiring relative to a file, which file would that be in 166 | a REPL? Well, there isn't really a file that fits that bill. Your alternatives 167 | in this situation are to use `load` or `require`. If you use `require` though, 168 | make sure to remember the leading `'./'` or `'../'` and don't do this in 169 | production code!. And if you ever want to determine what the current working 170 | directory of your Ruby process is, you can always output `Dir.pwd`. 171 | 172 | Conclusion 173 | ---------- 174 | So, we have seen that `require`, `require_relative` and `load` all fulfill 175 | different use cases when used as intended. `require` is generally for 176 | referencing libraries, `require_relative` is for making one off local references 177 | within an application (typically deployed applications, not within libraries) 178 | and about all `load` is good for is re-loading a script in a REPL. Well, that's 179 | how I see it anyway :). 180 | --------------------------------------------------------------------------------