├── CONTRIBUTING.md ├── GitCommitsForNonGitUsers.md ├── OSX ├── BatchRenaming.md └── macController.md ├── README.md ├── bash └── bash_profile_vs_bashrc.md ├── docker ├── binding-to-0-0-0-0-in-rails.md └── fig-run-new-container.md ├── ember └── property-brace-expansion.md ├── git ├── grab-a-file-from-another-branch.md ├── osx-keychain.md ├── split-up-a-commit.md └── squashing-commits.md ├── haskell ├── ranges-and-enum.md ├── sectioning.md └── sorting-in-reverse-order.md ├── homebrew └── using_different_homebrew_formula_versions.md ├── html └── html5-tidy.md ├── java └── number-formatting.md ├── javascript ├── funWithFunctions.md ├── npm-scripts.md └── prototypingCharacterClasses.md ├── life └── everybody-is-learning.md ├── python ├── mutable_default_arguments.md └── setuptools_entry_points.md ├── rails ├── deep_munge.md ├── edge-callbacks-dont-break-on-false.md ├── empty-arrays-in-json-request.md ├── find_by_exceptions.md ├── find_controller_action_from_uri.md ├── simpleform-default-maxlength.md └── using-delayed-job-with-rails-4.2.md ├── ruby ├── all-but-the-first-element-from-array.md ├── array-last-limit.md ├── basic-object.md ├── currying.md ├── inject_vs_each_with_object.md ├── ncurses-with-pry.md ├── parallel-assignment.md ├── regex_literals.md ├── spliting-a-string-into-a-maximum-number-of-segments.md └── the-data-constant.md ├── security └── constant-time-comparison.md ├── testing └── capybara-all-does-not-return-array.md └── vim ├── custom-command.md ├── diffing-from-the-command-line.md ├── profiling.md ├── search-replace-multiple-files.md └── yanking-text-to-register.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When you learn something, 4 | add a Markdown file to 5 | this repo explaining it in concise terms. 6 | Place the file in a directory 7 | which best describes 8 | the content of the tip. 9 | Create a new directory if no existing one fits. 10 | 11 | Open a pull request for review. 12 | 13 | For help submitting, please review our [Git Commits for Non-Git Users](/GitCommitsForNonGitUsers.md) guide. 14 | 15 | After merging into master, 16 | [Buffer](https://bufferapp.com) a tweet from the 17 | [@upcase](https://twitter.com/upcase) account. 18 | 19 | 20 | ## Writing a good a TIL 21 | 22 | TIL's should be a focused and concise piece of knowledge that's interesting and 23 | worth sharing with others. 24 | 25 | Here's some guidelines on how to write a great TIL: 26 | 27 | * Avoid writing more than 60 lines of content. 28 | * Avoid writing more than 2 examples. 29 | * Avoid going into too much detail. 30 | * Avoid writing TIL's that explicitly violate [our guides]. 31 | 32 | If you find TIL straying from these guidelines consider narrowing the scope of 33 | your TIL or writing a blog post on the subject. 34 | 35 | [our guides]: https://github.com/thoughtbot/guides 36 | -------------------------------------------------------------------------------- /GitCommitsForNonGitUsers.md: -------------------------------------------------------------------------------- 1 | #Git Commits For Non-Git Users 2 | 3 | This is a guide to aid others not familiar with git to contribute to our TIL repo. 4 | 5 | ## FIRST TIME SETUP 6 | * copy clone to clipboard 7 | ![](http://images.thoughtbot.com/TIL/copyClone_s.jpg) 8 | * Run the following `commands` in your shell: `git clone ` 9 | 10 | ## TO SUBMIT 11 | * `git pull origin master` 12 | * `git checkout -b ` 13 | * add files/folders locally 14 | * `git add .` to add everything in cur dir 15 | * `git commit` 16 | * press `i` to enter insert mode, write title & message 17 | * `ESC :wq` to write-quit 18 | * `git push origin ` 19 | * Compare & Pull Request on website 20 | 21 | ## TO CHANGE 22 | * `git status` to see changed files in red 23 | * `git add .` 24 | * `git status` to see updated files in green 25 | * `git commit` ( -m "MESSAGE" to skip Vim) 26 | * `git push origin ` 27 | 28 | ## TO SQUASH 29 | * `git fetch origin` 30 | * `git rebase -i origin/master` 31 | * squash to 1 in vim; `:wq` 32 | * reword commit messages 33 | * `git push -f origin ` 34 | 35 | ## TO MERGE 36 | * `git log` to view the list of commits on the current branch 37 | * `git checkout master` 38 | * `git pull origin master` to be up to date 39 | * `git merge ` 40 | * `git push origin master` 41 | * Delete branch from web UI 42 | * `git branch -d ` to delete branch locally 43 | -------------------------------------------------------------------------------- /OSX/BatchRenaming.md: -------------------------------------------------------------------------------- 1 | # Batch Renaming in Mac OS 10.10 2 | 3 | Today I learned that OS 10.10 supports [batch renaming from 4 | finder](http://www.tekrevue.com/tip/batch-rename-files-os-x-yosemite/). It 5 | supports adding and replacing text, custom string formatting and incremental 6 | file numbering. 7 | -------------------------------------------------------------------------------- /OSX/macController.md: -------------------------------------------------------------------------------- 1 | #Mac Controller Support 2 | 3 | Attempting to play video games natively on OS X has always been a rough proposition due to lack of supported games and hardware; but for years Colin Munro allowed us to utilize a Windows Xbox360 controller through a [custom driver](http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver). 4 | 5 | Sadly, Yosemite kernel extension signing requirements broke Colin's last build; though fortunately the project has been [forked to GitHub](https://github.com/d235j/360Controller), and has since reimplemented full controller support, rumble, LED, & System Preferences prefpane functionality. Game on! 6 | 7 | ![](http://images.thoughtbot.com/TIL/xboxPrefPane.jpg) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Today I Learned 2 | 3 | We constantly learn new things. This is a repo to share those learnings. 4 | TILs are short Markdown documents (a few sentences + example code) explaining 5 | concepts, bits of syntax, commands, or tips we've recently learned. 6 | 7 | For new TILs, watch this repo or follow [@upcase] on Twitter. 8 | 9 | [@upcase]: https://twitter.com/upcase 10 | 11 | If you like this repo, 12 | you might also like 13 | [Upcase]'s programming exercises and videos. 14 | 15 | [Upcase]: https://upcase.com?utm_source=til 16 | 17 | License 18 | ------- 19 | 20 | © 2015 thoughtbot, inc. 21 | Distributed under the [Creative Commons Attribution License][license]. 22 | 23 | [license]: http://creativecommons.org/licenses/by/3.0/ 24 | 25 | Names and logos for thoughtbot are trademarks of thoughtbot, inc. 26 | -------------------------------------------------------------------------------- /bash/bash_profile_vs_bashrc.md: -------------------------------------------------------------------------------- 1 | # `.bash_profile` vs `.bashrc` 2 | 3 | `bash(1)` can be started in interactive mode or non-interactive mode. It can 4 | also act as a login shell or a non-login shell. 5 | 6 | `bash(1)` is started in interactive mode by your terminal emulator and can also 7 | be started in interactive mode like this: 8 | 9 | ```bash 10 | bash 11 | bash -i 12 | bash -ic 'echo Hello!' 13 | ``` 14 | 15 | When you run a script through `bash(1)` or if you start it with the `-c` option, 16 | it will run in non-interactive mode: 17 | 18 | ```bash 19 | bash script.sh 20 | bash -c 'echo Hello!' 21 | ``` 22 | 23 | `bash(1)` is instructed to act as a login shell when you first log in to your 24 | machine or when you start `bash(1)` with the `--login` or `-l` option. 25 | 26 | `.bashrc` is sourced on every start in interactive mode when `bash(1)` does not 27 | act as a login shell. 28 | 29 | `.bash_profile` is only sourced when `bash(1)` is started as an interactive 30 | login shell, or as a non-interactive shell with the `--login` option. 31 | 32 | This means that `.bash_profile` is great for commands that should run only once 33 | and `.bashrc` for commands that should run every time you start a new shell. 34 | 35 | For example, `PATH` customization should only happen once, since it is not an 36 | idempotent operation. Suppose something like this was in your `.bashrc`: 37 | 38 | export PATH="$PATH:/addition" 39 | 40 | Running these commands from a newly started interactive shell would produce the 41 | output below: 42 | 43 | ```bash 44 | bash 45 | bash 46 | echo "$PATH" 47 | /original_path:/addition:/addition:/addition 48 | ``` 49 | 50 | Setting `PATH` in `.bash_profile` alleviates this problem. 51 | -------------------------------------------------------------------------------- /docker/binding-to-0-0-0-0-in-rails.md: -------------------------------------------------------------------------------- 1 | # Binding to 0.0.0.0 in Rails 2 | 3 | On OS X, [boot2docker] is an installable VM host to run Docker locally (OS X 4 | doesn't natively support Linux Containers). In combination with [fig], it's 5 | pretty straightforward to get a Rails application running on [Docker]. 6 | 7 | [boot2docker]: http://boot2docker.io/ 8 | [fig]: http://www.fig.sh/ 9 | [docker]: https://www.docker.com/ 10 | 11 | To access the application, you'll visit `$(boot2docker ip):3000` (or 12 | whatever port your Rails application is running on) and things should work 13 | fine. However, I'd recently tried setting up Docker in a Rails app that was 14 | running WEBrick and wasn't able to access the application at all when running 15 | `rails server`. I'd previously used [Thin] (`thin start`) and hadn't run into 16 | this problem. 17 | 18 | [thin]: http://code.macournoyer.com/thin/ 19 | 20 | Trevor, one of my coworkers, pointed out the `--binding` flag for `rails 21 | server`, which needs to be set in order for the server to accept requests from 22 | any network interface: `rails server --binding 0.0.0.0 --port 3000`. Due to 23 | how boot2docker/VirtualBox work with network interfaces, binding to 0.0.0.0 24 | when running the server works, whereas binding to localhost (127.0.0.1) does 25 | not. 26 | 27 | For security reasons, be careful when binding to 0.0.0.0; anyone with 28 | your network IP address and port of the Rails app could interact with the app 29 | (say, over wi-fi at a coffee shop). 30 | -------------------------------------------------------------------------------- /docker/fig-run-new-container.md: -------------------------------------------------------------------------------- 1 | # `fig run` Runs Commands on New Containers 2 | 3 | In a project I've been working on that deploys with [Docker] and [Fig], we're 4 | using [Ragel] and [Racc] to build a parser and lexer; the Ruby files are 5 | generated and written to the filesystem with a rake task when running `fig up 6 | web`. 7 | 8 | [docker]: https://www.docker.com/ 9 | [fig]: http://www.fig.sh/ 10 | [ragel]: http://www.colm.net/open-source/ragel/ 11 | [racc]: https://github.com/tenderlove/racc 12 | 13 | However, running `fig run web rails c` was demonstrating weird behavior; the 14 | parser and lexer constants weren't defined in Ruby, and they weren't present 15 | on the filesystem either. 16 | 17 | After a bit of digging through [fig's CLI documentation][fig-cli], I found 18 | that `fig run` brings up new containers to manage one-off commands instead of 19 | connecting to the same running container. This means any changes to the 20 | filesystem (like generating a parser and lexer, or more commonly log files or 21 | compiled assets) are not available during `fig run`. 22 | 23 | [fig-cli]: http://www.fig.sh/cli.html 24 | -------------------------------------------------------------------------------- /ember/property-brace-expansion.md: -------------------------------------------------------------------------------- 1 | # Property Brace Expansion 2 | 3 | Say you want to observe multiple properties on a single object in a computed 4 | property: 5 | 6 | ```javascript 7 | name: function() { 8 | return this.get('person.firstName') + ' ' + this.get('person.lastName'); 9 | }.property('person.firstName', 'person.lastName') 10 | ``` 11 | 12 | As of Ember 1.4, you can use property brace expansion for an abbreviated syntax: 13 | 14 | ```javascript 15 | name: function() { 16 | return this.get('person.firstName') + ' ' + this.get('person.lastName'); 17 | }.property('person.{firstName,lastName}') 18 | ``` 19 | -------------------------------------------------------------------------------- /git/grab-a-file-from-another-branch.md: -------------------------------------------------------------------------------- 1 | #Use a file from another branch 2 | 3 | Sometimes you just need one file from another branch. Sure you could `git 4 | cherry-pick` but then you're dealing with commits. That sort of thing gets 5 | sticky fast; don't go there. 6 | 7 | The best way is to use your old pal `git checkout`. Just make sure you're 8 | on the branch you want to bring the file into and then checkout the file 9 | from its source branch. Here's the syntax. 10 | 11 | ``` 12 | $ git checkout my-awesome-source-branch the/path/to/yourfile.rad 13 | ``` 14 | 15 | That's it – enjoy. 16 | -------------------------------------------------------------------------------- /git/osx-keychain.md: -------------------------------------------------------------------------------- 1 | # Using git's osxkeychain helper to cache GitHub authentication 2 | 3 | Recently after reformatting my computer I've had to input my username/password 4 | every time I try to do something with GitHub via the command line. Today I took 5 | the time to finally figure out what was going on. 6 | 7 | Turns out that I had a newer version of git that behaves a little differently. 8 | Today I learned that you need to configure git to use this so it will stop 9 | nagging you. 10 | 11 | ## The Symptoms 12 | 13 | 1. You are asked for your username and password when you interact with 14 | an HTTPS GitHub remote. 15 | 2. It does not ask for your username and password when you interact with an SSH 16 | GitHub remote. 17 | 3. You're git version is 1.7.10 or newer. Run `git --version` to find out which 18 | version you have. 19 | 20 | ## The Cure 21 | 22 | You need to configure git to cache your username and password with the 23 | osxkeychain credential helper. 24 | 25 | GitHub's help pages describe how to do this [here](https://help.github.com/articles/caching-your-github-password-in-git/) 26 | 27 | -------------------------------------------------------------------------------- /git/split-up-a-commit.md: -------------------------------------------------------------------------------- 1 | # Split Up a Commit, Rewrite History 2 | 3 | When working on a branch with multiple commits, you can "go back in time" and revise previous commits any way you please. 4 | 5 | $ git rebase -i origin/master 6 | 7 | This command will prompt you inside of your `$VISUAL` with a series of commit SHAs and commit titles 8 | 9 | # ... 10 | pick ed1ff41 Move templates 11 | pick 274ac0e Move components & views 12 | # ... 13 | 14 | To split up `274ac0e`, replace `pick` with `edit` and save the buffer. 15 | 16 | # ... 17 | pick ed1ff41 Move templates 18 | edit 274ac0e Move components & views 19 | # ... 20 | 21 | You are now detached from the `HEAD` of your branch and "back in time". 22 | To split up the current commit (`274ac0e`): 23 | 24 | $ git reset HEAD~ 25 | 26 | This will unstage all files within the commit. 27 | Next, split up the commit any way you'd like. 28 | 29 | $ git add app/views 30 | $ git commit -m "Move views" 31 | $ git add app/components 32 | $ git commit -m "Move components" 33 | 34 | When you're finished, continue the rebase. 35 | 36 | $ git rebase --continue 37 | 38 | If you introduced merge conflicts down the line, you'll have to resolve them. 39 | If all went well, your branch's history will be re-written. 40 | 41 | $ git log origin/master.. 42 | 43 | # ... 44 | ed1ff41 Move templates 45 | 7b84a01 Move views 46 | 274ac0e Move components 47 | # ... 48 | 49 | Keep in mind that you might have to force push your branch to `origin`, 50 | depending on whether or not your revised commits have been pushed. 51 | 52 | $ git push origin my-branch-name --force 53 | -------------------------------------------------------------------------------- /git/squashing-commits.md: -------------------------------------------------------------------------------- 1 | # Two ways of squashing commits 2 | 3 | It is handy to squash down your commits before merging your PR with 4 | `my-new-cool-feature`. You can either squash them down by doing an interactive 5 | rebase like so: 6 | 7 | ```bash 8 | $ git checkout my-new-cool-feature 9 | $ git rebase -i master 10 | ``` 11 | 12 | This will open up your `$EDITOR` of choice and you are free to pick and choose 13 | which commits to squash together. 14 | 15 | This might be tedious if you have a big number of commits to squash together. 16 | Very tedious. TIL that you can use `git merge` to squash your commits, all in 17 | one go. 18 | 19 | ```bash 20 | $ git checkout master 21 | $ git merge --squash my-cool-new-feature 22 | ``` 23 | 24 | This will leave all of your changes staged on `master`, ready to be committed as 25 | one. 26 | -------------------------------------------------------------------------------- /haskell/ranges-and-enum.md: -------------------------------------------------------------------------------- 1 | # Ranges and Enum 2 | 3 | Ranges can be constructed from any instance of Haskell's `Enum` typeclass, 4 | including custom types that derive from `Enum`. For example, the custom `Day` 5 | type below: 6 | 7 | ```hs 8 | data Day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday deriving (Show, Enum) 9 | [Monday .. Friday] 10 | 11 | -- returns 12 | [Monday,Tuesday,Wednesday,Thursday,Friday] 13 | ``` 14 | -------------------------------------------------------------------------------- /haskell/sectioning.md: -------------------------------------------------------------------------------- 1 | # Sectioning 2 | 3 | You can partially apply an infix function by wrapping one argument and the 4 | function name in parentheses. When the returned function is called with an 5 | argument, Haskell will apply that argument to whichever side was left blank. 6 | This is known as [sectioning]. Sectioning is often used when converting to 7 | [point-free style] 8 | 9 | ```hs 10 | -- Infix function + 11 | f x = 3 + x 12 | 13 | -- Point-free style 14 | -- Haskell will apply the argument to the right side of + 15 | f = (3+) 16 | 17 | -- Point-free style 18 | -- Haskell will apply the argument to the left side of + 19 | -- Since addition is commutative, this is equivalent to the definition above 20 | f = (+3) 21 | ``` 22 | 23 | [sectioning]: https://www.haskell.org/haskellwiki/Section_of_an_infix_operator 24 | [point-free style]: https://www.haskell.org/haskellwiki/Pointfree 25 | -------------------------------------------------------------------------------- /haskell/sorting-in-reverse-order.md: -------------------------------------------------------------------------------- 1 | # Sorting in reverse order 2 | 3 | `Data.Ord` contains a newtype, `Down`, which can wrap any type that has an 4 | `Ord` instance, in order to provide a reversed `Ord` instance for that type. 5 | 6 | For example: 7 | 8 | ```hs 9 | Prelude> import Data.Ord (Down(..)) 10 | Prelude Data.Ord> :info Down 11 | newtype Down a = Down a -- Defined in ‘Data.Ord’ 12 | instance Ord a => Ord (Down a) -- Defined in ‘Data.Ord’ 13 | Prelude Data.Ord> Down 3 > Down 4 14 | True 15 | ``` 16 | 17 | This can be very convenient for reversing sort order: 18 | 19 | ```hs 20 | Prelude> import Data.Ord (Down(..), comparing) 21 | Prelude Data.Ord> import Data.List (sortBy) 22 | Prelude Data.Ord Data.List> sortBy (comparing Down) [1..10] 23 | [10,9,8,7,6,5,4,3,2,1] 24 | ``` 25 | -------------------------------------------------------------------------------- /homebrew/using_different_homebrew_formula_versions.md: -------------------------------------------------------------------------------- 1 | # Using different Homebrew formula versions 2 | 3 | Today, I was trying to run the executable from a gem and got the following error: 4 | 5 | ``` 6 | This installation of RMagick was configured with ImageMagick 6.8.9 but 7 | ImageMagick 6.9.0-3 is in use. (RuntimeError) 8 | ``` 9 | 10 | My first instinct was to uninstall ImageMagick 6.9.0 and then install 6.8.9 with 11 | Homebrew. Through The Google, I learned that Homebrew saves older formula 12 | versions. You can see which versions you have like this (notice the asterisk 13 | next to the version in use): 14 | 15 | ```bash 16 | % brew info imagemagick 17 | imagemagick: stable 6.9.0-3 (bottled), HEAD 18 | http://www.imagemagick.org 19 | /usr/local/Cellar/imagemagick/6.8.8-9 (1429 files, 21M) 20 | /usr/local/Cellar/imagemagick/6.8.9-1 (1432 files, 22M) 21 | /usr/local/Cellar/imagemagick/6.9.0-3 (1440 files, 22M) * 22 | ``` 23 | 24 | Since I already had 6.8.9 installed, I could set it as my active version like 25 | so: 26 | 27 | ```bash 28 | % brew switch imagemagick 6.8.9-9 29 | ``` 30 | 31 | Problem: solved. 32 | -------------------------------------------------------------------------------- /html/html5-tidy.md: -------------------------------------------------------------------------------- 1 | # Tidy with HTML5 support 2 | 3 | There is a tool called `tidy` which was originally written by [Dave 4 | Raggett][tidy] (in the late '90s), and is now [maintained by 5 | volunteers][tidy-sf] and the W3C. 6 | 7 | There is an experimental fork of `tidy` which is maintained by the HTML Tidy 8 | Advocacy Community Group which supports the modern HTML5 spec. 9 | 10 | This tool takes HTML/XML/XHTML as input and produces a valid version as its 11 | output. It also accepts flags which make it more useful as an error-checking 12 | lint tool, and does not re-write files. Example usage of `tidy`: 13 | 14 | `find tmp -name "*.html" -print -exec tidy -qe {} \;` 15 | 16 | Here's what's happening: 17 | 18 | * Run the `find` tool, tell find to look in the `tmp/` directory, and locate all 19 | files with an `html` file extension. 20 | * Tell `find` to print out the names of every file. 21 | * Tell `find` to execute a process and send the output (all the html file names) 22 | to that process. 23 | * Use `tidy` with options of `q` (quiet mode) and `e` (only show errors). 24 | 25 | The resulting output contains a list of all files in `tmp/`, along with any 26 | errors in the HTML of those files. 27 | 28 | [tidy]: http://www.w3.org/People/Raggett/tidy/ 29 | [tidy-sf]: http://tidy.sourceforge.net/ 30 | [experiment-html5]: http://www.htacg.org/tidy-html5/ 31 | -------------------------------------------------------------------------------- /java/number-formatting.md: -------------------------------------------------------------------------------- 1 | # NumberFormatting 2 | 3 | ## Assignment 4 | Format a number for a specific locale. For example, the number 12345.123 should be formatted as `12,345.12` in the USA locale, but `12.345,12` in the German locale. 5 | 6 | ## Solution 7 | ```java 8 | DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault()); 9 | 10 | currencyFormatter.setMaximumFractionDigits(2); 11 | currencyFormatter.setMinimumFractionDigits(2); 12 | 13 | System.out.println(currencyFormatter.format(12345.12)); 14 | ``` 15 | 16 | Depending on your default Locale the currencyFormatter will format the number the right way. 17 | 18 | ##### If you have a locale like `Locale.US` it will output: 19 | ```java 20 | 12,345.12 21 | ``` 22 | 23 | ##### Or if you have a locale like `Locale.GERMANY`: 24 | ```java 25 | 12.345,12 26 | ``` 27 | 28 | ### What about the Locale 29 | Using `Locale.getDefault()` allows you to get the System default, so it depends on your settings. You can test it for other Locale's by using fixed locale values like: `Locale.GERMAN`or `Locale.US` for USA. You also can find the Local according to the `language`/`country` by using `Locale(String language)` or `Locale(String language, String country)`. More details can be found here: [Documentation for Locale]. 30 | 31 | ### Executable Online Java Example: 32 | Here is an in-browser example that you can try: [Coding Ground Example] 33 | Steps to run: compile and execute. 34 | 35 | [Coding Ground Example]:http://www.tutorialspoint.com/compile_java_online.php?PID=0Bw_CjBb95KQMbHZ0NWc1OVRONkE 36 | [Documentation for Locale]:http://docs.oracle.com/javase/7/docs/api/java/util/Locale.html 37 | -------------------------------------------------------------------------------- /javascript/funWithFunctions.md: -------------------------------------------------------------------------------- 1 | ## Functional Expressions in D&D ## 2 | I've been having fun with functions while creating a JavaScript version of the 5th edition D&D character sheet. 3 | 4 | In recreating the character bonus table I got thru 47 lines of inline conditionals before the formula slapped me in the face: 5 | ![](http://images.thoughtbot.com/TIL/OG_s.jpg) 6 | 7 | 8 | Even in adding abilities to an array, I was still left with 6 variables and a declared function: 9 | 10 | ```javascript 11 | var abilities = [9, 10, 15, 12, 9, 19]; //The [str, dex, con, int, wis, chr] of character 12 | function abilityMod(score) { return Math.floor((score / 2) - 5); } 13 | var strMod = abilityMod(abilities[0]); 14 | var dexMod = abilityMod(abilities[1]); 15 | var conMod = abilityMod(abilities[2]); 16 | var intMod = abilityMod(abilities[3]); 17 | var wisMod = abilityMod(abilities[4]); 18 | var chrMod = abilityMod(abilities[5]); 19 | ``` 20 | 21 | Until I used an expression with arrays and `.map`: 22 | 23 | ```javascript 24 | var abilities = [9, 10, 15, 12, 9, 19]; 25 | var mod = abilities.map(function(score) { return Math.floor((score / 2) - 5); }); 26 | ``` -------------------------------------------------------------------------------- /javascript/npm-scripts.md: -------------------------------------------------------------------------------- 1 | # NPM won't run arbitrary scripts 2 | 3 | NPM packages can declare named commands in the `"scripts"` section of their 4 | `package.json`. NPM scripts are a useful way to run repetitive tasks necessary 5 | for maintaining the package. 6 | 7 | As an example, the [ember.js `package.json`][package.json] declares 8 | a [`start`][start] script to run a local web server, 9 | a [`test`][test] script to run the package's test suite, and 10 | a [`build`][build] script to transpile, concatenate, and minify the package. 11 | 12 | To execute the `start` script, run: 13 | 14 | $ npm start 15 | 16 | To execute the `test` script, run: 17 | 18 | $ npm test 19 | 20 | This will execute the [`pretest`][pretest] script before the `test` script. 21 | 22 | To execute the `build` script, you would probably expect to run: 23 | 24 | $ npm build # womp womp 25 | 26 | *This will not behave like `start` or `test`.* 27 | 28 | NPM only supports a [specific set of scripts and hooks][scripts], and `build` is 29 | not directly supported. 30 | 31 | To execute the `build` script, run: 32 | 33 | $ npm run-script build 34 | 35 | It is also important to note that a `prebuild` hook *would not* fire before the 36 | `build` script's execution. 37 | 38 | [package.json]: https://github.com/emberjs/ember.js/blob/48e115928bcb6b366a621370339354c44aad86b1/package.json 39 | [start]: https://github.com/emberjs/ember.js/blob/48e115928bcb6b366a621370339354c44aad86b1/package.json#L10 40 | [test]: https://github.com/emberjs/ember.js/blob/48e115928bcb6b366a621370339354c44aad86b1/package.json#L8 41 | [pretest]: https://github.com/emberjs/ember.js/blob/48e115928bcb6b366a621370339354c44aad86b1/package.json#L9 42 | [build]: https://github.com/emberjs/ember.js/blob/48e115928bcb6b366a621370339354c44aad86b1/package.json#L6 43 | [scripts]: https://docs.npmjs.com/misc/scripts 44 | -------------------------------------------------------------------------------- /javascript/prototypingCharacterClasses.md: -------------------------------------------------------------------------------- 1 | #Prototype Your (Character) Class# 2 | 3 | Continuing in [using Javascript to build D&D characters](https://github.com/thoughtbot/til/blob/master/javascript/funWithFunctions.md), I decided to use prototypes. 4 | 5 | ```javascript 6 | function Character (name, hpBonus, profession, hd, castingAbility) { 7 | this.name = name; 8 | this.profession = profession; 9 | this.hd = hd; 10 | this.hpBonus = hpBonus; 11 | this.lvl = 1; 12 | this.profBonus = 2; 13 | this.castingAbility = castingAbility; 14 | this.exp = 0; 15 | this.abilities = new Array(6); 16 | this.mod = this.abilities.map(function (score){ return Math.floor((score / 2) - 5); } ); 17 | this.ac = 10 + this.mod[1]; 18 | this.hp = this.hd + this.mod[2] + this.dr; 19 | this.spellSave = 8 + this.profBonus + this.mod[castingAbility]; 20 | this.spellAttack = this.profBonus + this.mod[castingAbility]; 21 | } 22 | ``` 23 | 24 | In using a prototype over an object we gain the ability to efficiently store identical functions common to all characters without bloating objects. 25 | 26 | ```javascript 27 | Character.prototype = { 28 | levelUp: function (){ 29 | this.lvl++; 30 | var conMod = this.mod[2]; 31 | var lvlHP = (this.lvl-1)*(((this.hd/2)+1) + conMod); 32 | this.hp = this.hd + conMod + lvlHP + (this.hpBonus * this.lvl); 33 | if ((this.lvl - 1) % 4 == 0 ) { 34 | this.profBonus++; 35 | this.spellSave = 8 + this.profBonus + this.mod[this.castingAbility]; 36 | this.spellAttack = this.profBonus + this.mod[this.castingAbility]; 37 | } 38 | }, 39 | add: function (paramater, input){ 40 | this.paramater.push(input); 41 | } 42 | }; 43 | ``` 44 | 45 | So I've added the main functionality of leveling up our character, as well the ability to add on items to an inventory, weapons list, or character attributes; should the user decide to add those optional values later. 46 | 47 | Running a quick check, passing in & leveling up my sorcerer, Mordai: 48 | 49 | ```javascript 50 | var abilities = [9, 10, 15, 12, 9, 19]; 51 | var Mordai = new Character("Mordai", 1, "Sorcerer", 6, 5); 52 | Mordai.levelUp(); 53 | console.log(Mordai); 54 | ``` 55 | 56 | I get back the same results as my hand-calculated values for ability bonuses, level, proficiency bonus, and hit points. 57 | 58 | ![](http://images.thoughtbot.com/TIL/mordaiLayout.jpg) 59 | 60 | -------------------------------------------------------------------------------- /life/everybody-is-learning.md: -------------------------------------------------------------------------------- 1 | # Everybody is learning 2 | 3 | Today I learned that no matter how much experience, skill, or education 4 | someone has, they are always learning nifty little things every day. 5 | 6 | It's a pretty great thing that I have learned today. 7 | -------------------------------------------------------------------------------- /python/mutable_default_arguments.md: -------------------------------------------------------------------------------- 1 | # Mutable default arguments 2 | 3 | __NOTE__: Information taken from [python guide](http://docs.python-guide.org/en/latest/writing/gotchas/) 4 | 5 | One of the most confusing moments for new developers is when they discover how 6 | Python treats default arguments in function definitions. 7 | 8 | Let's say you want to define a function that accepts a list as a parameter, and you 9 | want the default value of that list to be the empty list, so you write: 10 | 11 | ```python 12 | def append_to(element, to=[]): 13 | to.append(element) 14 | return to 15 | ``` 16 | 17 | If everything was okay, you would expect the following behavior: 18 | 19 | ``` 20 | my_list = append_to(12) 21 | print my_list 22 | 23 | my_other_list = append_to(42) 24 | print my_other_list 25 | ``` 26 | 27 | ``` 28 | [12] 29 | [42] 30 | ``` 31 | 32 | But what you get instead is: 33 | 34 | ``` 35 | [12] 36 | [12, 42] 37 | ``` 38 | 39 | A new list is created once when the function is defined, and the same list is used in each successive call. 40 | 41 | Python’s default arguments are evaluated once when the function is defined, instead of each time the function is called (like it is in say Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well. 42 | 43 | ### What you should do 44 | Create a new object each time the function is called, by using a default arg to signal that no argument was provided (`None` is often a good choice): 45 | 46 | ```python 47 | def append_to(element, to=None): 48 | if to is None: 49 | to = [] 50 | to.append(element) 51 | return to 52 | ``` -------------------------------------------------------------------------------- /python/setuptools_entry_points.md: -------------------------------------------------------------------------------- 1 | # Setuptools entry points 2 | When building a Python package, the most common way of exposing a 3 | command line interface (CLI) is to use the "scripts" keyword in 4 | ``setup.py``. 5 | 6 | ```python 7 | # file: setup.py 8 | from setuptools import setup 9 | 10 | setup( 11 | name='my_package', 12 | scripts=['scripts/my_cli'], 13 | ... 14 | ) 15 | ``` 16 | 17 | However, **entry points** represents an improved and cross-platform 18 | approach to accomplish the same goal. 19 | 20 | ```python 21 | # file: setup.py 22 | from setuptools import setup 23 | 24 | setup( 25 | name='my_package', 26 | entry_points={ 27 | 'console_scripts': [ 28 | 'my_cli': 'my_package.cli:main' 29 | ] 30 | }, 31 | ... 32 | ) 33 | ``` 34 | 35 | What's happens when the user installs the package is that ``pip`` will 36 | make sure that ``my_cli`` is available as an executable on the system. 37 | Once invoked, the ``main`` function of the ``my_package.cli`` module 38 | will be called. 39 | 40 | ```bash 41 | $ pip install my_package 42 | $ my_cli # the main function is called 43 | Usage: my_cli [OPTIONS] COMMAND [ARGS]... 44 | ``` 45 | 46 | The problem with the former approach is that it requires separating 47 | CLI related code into a isolated file outside the main package. With 48 | **entry points** it's possible to unify all source code under the same 49 | package directory. This makes testing significantly easier. 50 | 51 | --------------------- 52 | 53 | There's actually a lot more you can use entry points for. It is ideally 54 | suited to act as a simple way for third party plugins to hook into your 55 | application. A great example of such integration is employed by 56 | [pytest][pytest] for their excellent plugin architecture. 57 | 58 | You can also find out more in the [setuptools docs][setuptools]. 59 | 60 | 61 | [pytest]: http://pytest.org/latest/ 62 | [setuptools]: https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation 63 | -------------------------------------------------------------------------------- /rails/deep_munge.md: -------------------------------------------------------------------------------- 1 | # Deep munge 2 | 3 | Rails will automatically strip empty arrays and hashes from `params`. This is to 4 | fix security holes caused by the unintentional generation of SQL queries with 5 | `IS NULL` or `IN ('foo', NULL')`. 6 | 7 | For example, all of the following JSON: 8 | 9 | ```javascript 10 | { "foo": null } 11 | { "foo": [] } 12 | { "foo": [null] } 13 | { "foo": [null, null, ...] } 14 | ``` 15 | 16 | will be turned into this Ruby hash: 17 | 18 | ```ruby 19 | { foo: nil } 20 | ``` 21 | 22 | `null`s are also cleaned out of arrays. The following JSON: 23 | 24 | ```javascript 25 | { "foo": ["bar", null] } 26 | ``` 27 | 28 | is parsed to to: 29 | 30 | ```ruby 31 | { foo: ["bar"] } 32 | ``` 33 | 34 | Rails invokes a method called `deep_munge` to do this work. Check out the [rails 35 | security guide] for more details. 36 | 37 | [rails security guide]: 38 | http://guides.rubyonrails.org/security.html#unsafe-query-generation 39 | -------------------------------------------------------------------------------- /rails/edge-callbacks-dont-break-on-false.md: -------------------------------------------------------------------------------- 1 | # Callbacks in Edge Rails 2 | 3 | In Edge Rails, callbacks won't stop if you return `false`, you need to throw 4 | `:abort` . This prevents really subtle bugs where a method in a callback returns 5 | `false`, unintentionally breaking the callback chain. For example, the following 6 | would previously have halted the callback chain: 7 | 8 | ```ruby 9 | def unset_admin 10 | self.admin = false 11 | end 12 | ``` 13 | 14 | Check out the [pull request] on Rails to see the discussion around this feature. 15 | 16 | **Note:** This feature is currently slated be included as part of the Rails 5 17 | release. 18 | 19 | [pull request]: https://github.com/rails/rails/pull/17227 20 | -------------------------------------------------------------------------------- /rails/empty-arrays-in-json-request.md: -------------------------------------------------------------------------------- 1 | `Rack::Test` defaults to URL Encoding Parameters 2 | ================================================ 3 | 4 | By default, Rack's test helpers set the `Content-Type` header to 5 | `application/x-www-form-urlencoded`. 6 | 7 | The URL encoded representation of 8 | 9 | ```json 10 | { "tags": ["foo", "bar"] } 11 | ``` 12 | 13 | would be 14 | 15 | ``` 16 | ?tags[]=foo&tags[]=bar 17 | ``` 18 | 19 | This works as expected for non-empty arrays: 20 | 21 | ```ruby 22 | put "/api/v1/post/1", { 23 | post: { tags: ["foo"] } 24 | } 25 | ``` 26 | 27 | However, it isn't possible to represent `[]` as a URL encoded string. 28 | 29 | ```ruby 30 | put "/api/v1/post/1", { 31 | post: { tags: [] } 32 | } 33 | ``` 34 | 35 | would be invalidly encoded as: 36 | 37 | ``` 38 | ?tags[]= 39 | ``` 40 | 41 | As a result, Rack ignores the `tags` key, which would make the `post` key point 42 | to an empty hash, which Rack also ignores. 43 | 44 | To work around this issue: 45 | 46 | * transform the `params` hash to a [`JSON` string][rack-test] 47 | * append `.json` to the URL 48 | * explicitly set the `"Content-Type"` header to `"application/json"` 49 | 50 | ```ruby 51 | put "/api/v1/post/1.json", { 52 | post: { tags: [] } 53 | }.to_json, { "Content-Type" => "application.json" } 54 | ``` 55 | 56 | This pattern can be extracted to a helper: 57 | 58 | ```ruby 59 | def json_put(path, params, headers_or_env = {}) 60 | json_path = "#{path}.json" 61 | params_without_format = params.except(:format) 62 | headers = headers_or_env.reverse_merge("Content-Type" => "application/json") 63 | 64 | put(json_path, params_without_format.to_json, headers) 65 | end 66 | 67 | 68 | json_put "/api/v1/post/1", { 69 | post: { tags: [] } 70 | } 71 | ``` 72 | 73 | Coincidentally, Basecamp has a similar set of test helpers. 74 | 75 | [rack-test]: https://github.com/brynary/rack-test/blob/acdbee66fc765f15c2d3a1a372c368fe8ee0a49c/lib/rack/test.rb#L218-L228 76 | -------------------------------------------------------------------------------- /rails/find_by_exceptions.md: -------------------------------------------------------------------------------- 1 | ## Exceptions Raised by `find_by` vs. `find` 2 | 3 | I previously believed that the following were the same - the former being the more concise, and by extension making the latter overly verbose: 4 | 5 | ```ruby 6 | ObjectModel.find(3) # good 7 | ObjectModel.find_by(id: 3) # bad? 8 | ``` 9 | 10 | Today, one of my teammates ([@dleve123](https://github.com/dleve123)) pushed up a PR with the latter line. One of the finer points of `find_by` is that attempting to retrieve an id that doesn't exist will simply return `nil`. I now understand that the following is more accurate: 11 | 12 | ```ruby 13 | ObjectModel.find(3) # good 14 | ObjectModel.find_by!(id: 3) # bad! 15 | 16 | ObjectModel.find_by(id: 3) # good, when trying to avoid exceptions 17 | ``` 18 | 19 | `find_by!` will raise an exception and makes the first two essentially the same. It should be noted that the dynamic `find_by_[attribute]` methods follow the same convention, though they are [mildly deprecated](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Dynamic+attribute-based+finders). This also extends to all other uses of the `find_by` methods with attributes other than `id`: 20 | 21 | 22 | ```ruby 23 | ObjectModel.find_by!(name: "foo") # use when exceptions should be raised 24 | ObjectModel.find_by(name: "foo") # use when exceptions should be surpressed 25 | ``` 26 | -------------------------------------------------------------------------------- /rails/find_controller_action_from_uri.md: -------------------------------------------------------------------------------- 1 | # Find a controller and action from a URI string 2 | 3 | Got `GET /posts`, want to craft a `redirect_to` based off of that URI and some other parameters? 4 | 5 | Today I learned that you can extract out the controller and action for a particular route with the magical 6 | `ActionDispatch::Routing::RouteSet#recognize_path`, 7 | which can be called through `Rails.application.routes.recognize_path`. 8 | 9 | **Warning**: `#recognize_path` isn't part of Rails' user facing public API. 10 | Do **not** use in production - its behavior might change without notice. 11 | 12 | So given a routes file: 13 | 14 | ```ruby 15 | # config/routes.rb 16 | # ... 17 | resources :posts 18 | # ... 19 | ``` 20 | And jumping into the rails console: 21 | ```bash 22 | $ bundle exec rails console 23 | ``` 24 | Try out the following: 25 | ```ruby 26 | Rails.application.routes.recognize_path('/posts') #=> { controller: 'posts', action: 'index' } 27 | ``` 28 | 29 | I discovered this method via a failed refactoring, so I honestly don't have a great use-case for `#recognize_path`. 30 | 31 | Nevertheless, I think `#recognize_path` is an interesting, undocumented, and [huge][4_1_8_recognize_path_source] part `ActionDispatch::Routing::RouteSet`'s API! 32 | 33 | [4_1_8_recognize_path_source]:https://github.com/rails/rails/blob/v4.1.8/actionpack/lib/action_dispatch/routing/route_set.rb#L681-L719 34 | -------------------------------------------------------------------------------- /rails/simpleform-default-maxlength.md: -------------------------------------------------------------------------------- 1 | # Inferred `maxlength` in Simple Form 2 | 3 | The [Simple Form gem] gives us some advanced features built on top of Rails' 4 | form builder. One such feature is the ability to infer the `maxlength` attribute 5 | by reading the validations on an `ActiveRecord` model. This can be set by 6 | opening the simple form initializer and changing `b.optional :maxlength` to 7 | `b.use :maxlength`. This file is well documented with comments. 8 | 9 | ```ruby 10 | # config/initializers/simple_form.rb 11 | 12 | SimpleForm.setup do |config| 13 | config.wrappers :default, :class: input, 14 | hint_class: :field_with_hint, error_class: :field_with_errors do 15 | 16 | ## Optional extensions 17 | # They are disabled unless you pass `f.input EXTENSION_NAME => true` 18 | # to the input. If so, they will retrieve the values from the model 19 | # if any exists. If you want to enable any of those 20 | # extensions by default, you can change `b.optional` to `b.use`. 21 | 22 | # Calculates maxlength from length validations for string inputs 23 | b.optional :maxlength 24 | end 25 | end 26 | ``` 27 | 28 | [Simple Form gem]: https://github.com/plataformatec/simple_form 29 | -------------------------------------------------------------------------------- /rails/using-delayed-job-with-rails-4.2.md: -------------------------------------------------------------------------------- 1 | # Using Delayed::Job with Rails 4.2 2 | 3 | [Delayed::Job][dj] is a reliable way to manage tasks which need to be run 4 | asynchronously, like processing large files or sending emails. Prior to Rails 5 | 4.2, the common pattern to deliver emails asynchronously with Delayed::Job was 6 | by calling `.delay` prior to the method on the mailer: 7 | 8 | ```ruby 9 | # synchronous 10 | ScoreMailer.congratulate_user_for_high_score(user, high_score).deliver 11 | 12 | # asynchronous 13 | ScoreMailer.delay.congratulate_user_for_high_score(user, high_score) 14 | ``` 15 | 16 | In Rails 4.2, it becomes more natural with [ActiveJob]: 17 | 18 | ```ruby 19 | # synchronous 20 | ScoreMailer.congratulate_user_for_high_score(user, high_score).deliver_now 21 | 22 | # asynchronous 23 | ScoreMailer.congratulate_user_for_high_score(user, high_score).deliver_later 24 | ``` 25 | 26 | When upgrading Rails to 4.2 or introducing Delayed::Job on a 4.2 app, don't 27 | forget to set the ActiveJob's queueing backend correctly when using 28 | `#deliver_later`: 29 | 30 | ```ruby 31 | # config/application.rb 32 | module AppName 33 | class Application < Rails::Application 34 | # ... 35 | config.active_job.queue_adapter = :delayed_job 36 | end 37 | end 38 | ``` 39 | 40 | [activejob]: http://guides.rubyonrails.org/active_job_basics.html 41 | [dj]: https://github.com/collectiveidea/delayed_job 42 | -------------------------------------------------------------------------------- /ruby/all-but-the-first-element-from-array.md: -------------------------------------------------------------------------------- 1 | # Getting all but the first element from Ruby array 2 | 3 | When getting all but the first element from an array in Ruby, we have a few 4 | options. 5 | 6 | Given the following list: 7 | 8 | ```ruby 9 | list = [1,2,3,4] 10 | ``` 11 | 12 | ## Shift 13 | 14 | We could use [`shift`][shift docs], however it mutates the array. It also 15 | doesn't return the list so we need two lines to write this code: 16 | 17 | ```ruby 18 | list.shift 19 | # => 1 20 | rest_of_list = list 21 | # => [2,3,4] 22 | ``` 23 | 24 | ## Slice 25 | 26 | In the past I've used [`slice`][slice docs], but specifying indices or passing 27 | the length of an array is ugly and low-level: 28 | 29 | ```ruby 30 | rest_of_list = list[1..-1] 31 | # => [2,3,4] 32 | rest_of_list = list.slice(1, list.length) 33 | # => [2,3,4] 34 | 35 | list # is not modified 36 | # => [1,2,3,4] 37 | ``` 38 | 39 | ## Drop 40 | 41 | My new favorite is [`drop`][drop docs] which does not mutate and does not 42 | require ugly, low-level code: 43 | 44 | ```ruby 45 | list.drop(1) 46 | # => [2,3,4] 47 | 48 | list # is not modified 49 | # => [1,2,3,4] 50 | ``` 51 | 52 | An added benefit of`drop` is that it will always return an array, while `slice` 53 | will sometimes return `nil` 54 | 55 | ```ruby 56 | [].slice(1..-1) 57 | # => nil 58 | 59 | [].drop(1) 60 | # => [] 61 | ``` 62 | 63 | [shift docs]: http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-shift 64 | [slice docs]: http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-slice 65 | [drop docs]: http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-drop 66 | -------------------------------------------------------------------------------- /ruby/array-last-limit.md: -------------------------------------------------------------------------------- 1 | # Returning a fixed number of items from the tail of a list 2 | 3 | [`Array#last`][last docs] takes an argument to limit the number of items to return 4 | from the tail of a list. 5 | 6 | ```ruby 7 | > [1,2,3,4,5].last(2) 8 | # = > [4, 5] 9 | ``` 10 | 11 | [last docs]: (http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-last) 12 | -------------------------------------------------------------------------------- /ruby/basic-object.md: -------------------------------------------------------------------------------- 1 | # Basic Object 2 | 3 | Ruby has a `BasicObject` class which doesn't include Kernel methods and acts as 4 | the parent for all `Object`s. You can see the ancestry in practice via: 5 | 6 | ```ruby 7 | Object.ancestors # => [Object, Kernel, BasicObject] 8 | BasicObject.ancestors # => [BasicObject] 9 | ``` 10 | 11 | `BasicObject` thus has very few instance methods which would be inherited by a 12 | subclass: 13 | 14 | ```ruby 15 | BasicObject.instance_methods # => [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] 16 | Object.instance_methods.length # => 55 17 | ``` 18 | 19 | This is useful for delegators which would otherwise not delegate methods such as 20 | \#to_s. 21 | 22 | Example: 23 | 24 | ```ruby 25 | class ListDelegator 26 | def initialize(*list) 27 | @list = list 28 | end 29 | 30 | def method_missing(method, *args, &block) 31 | @list.map do |item| 32 | item.__send__(method, *args, &block) 33 | end 34 | end 35 | end 36 | 37 | class ListDelegatorBasic < BasicObject 38 | def initialize(*list) 39 | @list = list 40 | end 41 | 42 | def method_missing(method, *args, &block) 43 | @list.map do |item| 44 | item.__send__(method, *args, &block) 45 | end 46 | end 47 | end 48 | 49 | class Out 50 | def to_s 51 | "Out" 52 | end 53 | end 54 | 55 | ListDelegator.new(Out.new).to_s # => "#" 56 | ListDelegatorBasic.new(Out.new).to_s # => ["Out"] 57 | ``` 58 | -------------------------------------------------------------------------------- /ruby/currying.md: -------------------------------------------------------------------------------- 1 | # Currying in Ruby 2 | 3 | Ruby defines `curry` for `Method` and `Proc`, allowing procs to return partially 4 | applied procs when they get called with fewer than the required number of 5 | arguments. For example: 6 | 7 | ```ruby 8 | multiply = -> x,y { x * y }.curry 9 | #=> # 10 | multiply[2,3] 11 | #=> 6 12 | double = multiply[2] 13 | #=> # 14 | double[3] 15 | #=> 6 16 | ``` 17 | 18 | **Note:** While `Proc#curry` has been around since Ruby 1.9, `Method#curry` was 19 | only added in Ruby 2.2.0. For versions before 2.2.0, you will first need to 20 | convert your method object to a proc via `Method#to_proc`. 21 | 22 | Check out the [Ruby docs] for more details. 23 | 24 | [Ruby docs]: http://ruby-doc.org/core-2.2.0/Proc.html#method-i-curry 25 | -------------------------------------------------------------------------------- /ruby/inject_vs_each_with_object.md: -------------------------------------------------------------------------------- 1 | # Inject vs each_with_object 2 | 3 | ## Inject 4 | 5 | Inject takes the value of the block and passes it along. 6 | This causes a lot of errors like. 7 | 8 | ```ruby 9 | inject_array = ['A', 'B', 'C', 'D'] 10 | 11 | inject_array.inject({}) do |accumulator, value| 12 | accumulator[value] = value.downcase 13 | end 14 | 15 | Output: 'IndexError: string not matched' 16 | ``` 17 | 18 | The above code causes 'IndexError: string not matched' error. 19 | 20 | What you really wanted. 21 | 22 | ```ruby 23 | inject_array = ['A', 'B', 'C', 'D'] 24 | 25 | inject_array.inject({}) do |accumulator, value| 26 | accumulator[value] = value.downcase 27 | accumulator 28 | end 29 | 30 | Output: => {"A"=>"a", "B"=>"b", "C"=>"c", "D"=>"d"} 31 | ``` 32 | 33 | ## each_with_object 34 | 35 | each_with_object ignores the return value of the block and passes the initial object along. 36 | 37 | ```ruby 38 | array = ['A', 'B', 'C', 'D'] 39 | 40 | array.each_with_object({}) do |value, accumulator| 41 | accumulator[value] = value.downcase 42 | end 43 | 44 | Output: => {"A"=>"a", "B"=>"b", "C"=>"c", "D"=>"d"} 45 | ``` 46 | One more thing which you can notice is the order of arguments to the block for each of the functions. 47 | 48 | Inject takes the result/accumulator and then the iteratable value, whereas 'each_with_object' takes the value followed by the result/accumulator. 49 | -------------------------------------------------------------------------------- /ruby/ncurses-with-pry.md: -------------------------------------------------------------------------------- 1 | # Using pry and ncurses together 2 | 3 | Because of ncurse's visual mode you will not be able to use pry normally. 4 | The easiest way to get pry working is to do the following: 5 | 6 | ```ruby 7 | close_screen 8 | binding.pry 9 | refresh 10 | ``` 11 | 12 | [`close_screen`][close_screen docs] restores the non-visual mode which allows you to see the 13 | output of pry correctly. When you `exit` from pry, `refresh` will resume 14 | ncurse's visual mode. 15 | 16 | [close_screen docs]: http://ruby-doc.org/stdlib-2.0/libdoc/curses/rdoc/Curses.html#method-c-close_screen 17 | -------------------------------------------------------------------------------- /ruby/parallel-assignment.md: -------------------------------------------------------------------------------- 1 | # Parallel assignment 2 | 3 | Ruby allows us to assign multiple variables on the same line. This is also 4 | called parallel assignment. 5 | 6 | ```ruby 7 | a, b = 1, 2 8 | #=> [1, 2] 9 | a 10 | #=> 1 11 | b 12 | #=> 2 13 | ``` 14 | 15 | We can also use parallel assignment and the splat operator in combination to 16 | split the array into the head and tail. This is in particular useful if we want 17 | to [get all but the first element from an array](all-but-the-first-element-from-array.md). 18 | 19 | ```ruby 20 | list = [1,2,3,4] 21 | #=> [1,2,3,4] 22 | head, *tail = list 23 | #=> [1,2,3,4] 24 | head 25 | #=> 1 26 | tail 27 | #=> [2,3,4] 28 | 29 | list # is not modified 30 | #=> [1,2,3,4] 31 | ``` 32 | 33 | ### Empty arrays 34 | When using parallel assignment on an empty array, the tail will always return an 35 | array while the head will be `nil`. 36 | 37 | ```ruby 38 | head, *tail = [] 39 | #=> [] 40 | head 41 | #=> nil 42 | tail 43 | #=> [] 44 | ``` 45 | -------------------------------------------------------------------------------- /ruby/regex_literals.md: -------------------------------------------------------------------------------- 1 | # Regex Literals and URLs 2 | 3 | Regular expressions in Ruby are typically delineated by the `/` character. 4 | However, this forces you to escape `/` in your expression. 5 | 6 | I was recently using a regex to match certain URLs 7 | 8 | ```ruby 9 | /http:\/\/sub\.domain\.com\/path/ 10 | ``` 11 | 12 | A colleague pointed out that I could use the `%r{...}` notation and avoid 13 | escaping all those slashes. 14 | 15 | ```ruby 16 | %r{http://sub\.domain\.com/path} 17 | ``` 18 | 19 | Much cleaner! 20 | -------------------------------------------------------------------------------- /ruby/spliting-a-string-into-a-maximum-number-of-segments.md: -------------------------------------------------------------------------------- 1 | # Spliting a string into a maximum number of segments 2 | 3 | [`String#split`][split docs] takes an argument to limit the number of returned 4 | matches. Once the limit is reached, the rest of the string is returned as one 5 | match even if it contains more delimiters. 6 | 7 | For example, say we are parsing a string whose first two lines are always 8 | headers and the rest is the body: 9 | 10 | ```ruby 11 | text = <<-TEXT 12 | header1 = value 13 | header2 = value 14 | the body 15 | keeps going 16 | on over 17 | multiple lines 18 | TEXT 19 | ``` 20 | 21 | A simple `split` on newlines would create an array with each line as an 22 | individual element: 23 | 24 | ```ruby 25 | text.split("\n") 26 | # => ["header1 = value", 27 | # "header2 = value", 28 | # "the body", 29 | # "keeps going", 30 | # "on over", 31 | # "multiple lines"] 32 | ``` 33 | 34 | Since we know there are two headers and a body, we can tell `split` to stop 35 | splitting once we have three segments: 36 | 37 | ```ruby 38 | text.split("\n", 3) 39 | # => ["header1 = value", 40 | # "header2 = value", 41 | # "the body\nkeeps going\non over\nmultiple lines"] 42 | ``` 43 | 44 | [split docs]: http://www.ruby-doc.org/core-2.2.0/String.html#method-i-split 45 | -------------------------------------------------------------------------------- /ruby/the-data-constant.md: -------------------------------------------------------------------------------- 1 | # The `DATA` constant 2 | 3 | The `DATA` constant in Ruby allows us to access the text at the end of our file 4 | listed after the `__END__` block. This can be surprisingly useful, for instance 5 | if we need to extract information from a rather large data blob. 6 | 7 | Imagine a scenario where we need to extract the user names from a SQL statement. 8 | 9 | ```ruby 10 | puts DATA.read.gsub("ALTER USER ", "").gsub(/IDENTIFIED BY.+/, "") 11 | 12 | __END__ 13 | ALTER USER Annette IDENTIFIED BY 'Annette'; 14 | ALTER USER Warren IDENTIFIED BY 'Warren'; 15 | ALTER USER Anthony IDENTIFIED BY 'Anthony '; 16 | ALTER USER Preston IDENTIFIED BY 'Preston'; 17 | ALTER USER Kelly IDENTIFIED BY 'Kelly '; 18 | ALTER USER Taylor IDENTIFIED BY 'Taylor'; 19 | ALTER USER Stiller IDENTIFIED BY 'Stiller'; 20 | ALTER USER Dennis IDENTIFIED BY 'Dennis'; 21 | ALTER USER Schwart IDENTIFIED BY 'Schwart'; 22 | ``` 23 | 24 | Executing the file will print this: 25 | 26 | ``` 27 | Annette 28 | Warren 29 | Anthony 30 | Preston 31 | Kelly 32 | Taylor 33 | Stiller 34 | Dennis 35 | Schwart 36 | ``` 37 | 38 | Since `DATA` is simply just a virtual `File` object within our file, we can also 39 | pass the `DATA` variable (without `#read`) to methods that accept a `File`. 40 | 41 | ```ruby 42 | require "json" 43 | 44 | puts JSON.load(DATA) 45 | 46 | __END__ 47 | { 48 | "records": [ 49 | { 50 | "artist":"Iggy Pop", 51 | "title":"Lust for Life" 52 | }, 53 | { 54 | "artist":"Television", 55 | "title":"Marquee Moon" 56 | }, 57 | { 58 | "artist":"Talking Heads", 59 | "title":"Talking Heads: 77" 60 | } 61 | ] 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /security/constant-time-comparison.md: -------------------------------------------------------------------------------- 1 | # Constant time comparison 2 | 3 | Using `==` to compare sensitive hashes leaves you vulnerable to timing attacks. 4 | This is because `==` returns `false` as soon as it finds two characters that 5 | don't match. An attacker can make many requests with different values and 6 | compare times to figure out how many characters were correct (the shorter the 7 | response, the fewer correct characters). 8 | 9 | The solution to this problem is to use a constant-time comparison algorithm. 10 | This ensures that the method will always take the same amount of time, 11 | regardless of how similar the hashes are. In Ruby, you can use 12 | [`Rack::Utils.secure_compare`] or 13 | [`ActiveSupport::SecurityUtils.secure_compare`]. 14 | 15 | For more information, check out this excellent [blog post]. 16 | 17 | [`Rack::Utils.secure_compare`]: 18 | http://www.rubydoc.info/github/rack/rack/Rack/Utils#secure_compare-class_method 19 | [`ActiveSupport::SecurityUtils.secure_compare`]: 20 | http://api.rubyonrails.org/classes/ActiveSupport/SecurityUtils.html#method-c-secure_compare 21 | [blog post]: http://codahale.com/a-lesson-in-timing-attacks/ 22 | -------------------------------------------------------------------------------- /testing/capybara-all-does-not-return-array.md: -------------------------------------------------------------------------------- 1 | # Capybara `all` does not return an array 2 | 3 | Although it looks like it returns an `Array`, Capybara's `all` finder actually 4 | returns a `Capybara::Result`. This object includes `Enumerable` and responds to 5 | many of the most used methods on `Array` such as `[]`. 6 | 7 | Given the following HTML: 8 | 9 | ```html 10 | 11 |

Some content

12 |

Other content

13 |

Final content

14 | 15 | ``` 16 | 17 | The following really looks like we are dealing with an array: 18 | 19 | ```ruby 20 | paragraphs = all("p") 21 | # => [,,] 22 | 23 | paragraphs[1] 24 | # => 25 | 26 | paragraphs.map(&:text) 27 | # => ["Some content", "Other content", "Final Content"] 28 | ``` 29 | 30 | However, if I try to use some of the `Array` monkey patches provided by 31 | `ActiveSupport`: 32 | 33 | ```ruby 34 | paragraphs.second 35 | # => NoMethodError: undefined method `second' for Capybara::Result 36 | 37 | paragraphs.class 38 | # => Capybara::Result 39 | ``` 40 | -------------------------------------------------------------------------------- /vim/custom-command.md: -------------------------------------------------------------------------------- 1 | # Custom commands 2 | 3 | Custom commands in Vim are defined via the `command` command. As I learn new 4 | things throughout the week, I like to write them down in a `TIL.md` file. I 5 | found myself constantly running `:tabe ~/Documents/TIL.md` to open my file in a 6 | new tab. To streamline the process, I added the following to my `.vimrc`: 7 | 8 | ```vimscript 9 | command TIL tabe~/Document/TIL.md 10 | ``` 11 | 12 | Now, whenever I want to write down something I've learned I can just run `:TIL`. 13 | 14 | User-defined commands _must_ start with a uppercase letter. 15 | 16 | More details in `:help command`, or check out the [online vim docs]. 17 | 18 | [online vim docs]: http://vimdoc.sourceforge.net/htmldoc/map.html#:command 19 | -------------------------------------------------------------------------------- /vim/diffing-from-the-command-line.md: -------------------------------------------------------------------------------- 1 | # Easy file diffing 2 | 3 | Vim comes with its own diff viewer. It can be launched from the command-line 4 | with: 5 | 6 | ```bash 7 | vim -d file1 file2 8 | # or 9 | vimdiff file1 file2 10 | ``` 11 | 12 | You can also get a diff from within Vim by opening two files in 13 | splits and running `:diffthis`. 14 | 15 | More details in `:help vimdiff`, or check out the [online docs]. 16 | 17 | [online docs]: http://vimdoc.sourceforge.net/htmldoc/diff.html#vimdiff 18 | -------------------------------------------------------------------------------- /vim/profiling.md: -------------------------------------------------------------------------------- 1 | # Vim Profiling 2 | 3 | I recently encountered a situation where Vim was taking an *excruciatingly* long 4 | time to launch. From some manual testing, I was able to isolate the problem to a 5 | particular directory, but I wasn't sure what was causing it. I then discovered 6 | Vim ships with profiling tools that would tell me how much time was spent in 7 | each of the functions that ran during startup. See the [official docs] for more 8 | info. 9 | 10 | I'll start with the shell command I ended up running: 11 | 12 | ```sh 13 | vim -c 'profile start vim.log' -c 'profile func *' -c 'e config/routes.rb' -c 'q' 14 | ``` 15 | 16 | The `-c` option tells Vim to execute the given command after loading the first 17 | file (in this case the empty buffer), and will execute multiple `-c` options 18 | sequentially. 19 | 20 | To break it down: 21 | 22 | * `-c 'profile start vim.log'` starts the profiler, logging results to the 23 | vim.log file. 24 | * `-c 'profile func *'` enables profiling of functions matching the given 25 | pattern. All functions, in this case. 26 | * `-c 'e config/routes.rb'` opens the routes file. This was arbitrary for my 27 | purposes, as opening any file in the Rails application was slow. 28 | * `-c 'q'` quits. 29 | 30 | The `vim.log` file has a lot of detail about the functions that were executed. 31 | Here's a short one that was near the top for me. 32 | 33 | ```text 34 | FUNCTION fugitive#is_git_dir() 35 | Called 18 times 36 | Total time: 0.000396 37 | Self time: 0.000233 38 | 39 | count total (s) self (s) 40 | 18 0.000271 0.000108 let path = s:sub(a:path, '[\/]$', '') . '/' 41 | 18 0.000107 return isdirectory(path.'objects') && isdirectory(path.'refs') && getfsize(path.'HEAD') > 10 42 | 43 | ``` 44 | 45 | That's interesting, for sure, but the good stuff is at the bottom of the file, 46 | where functions are sorted by execution time. Here's my top offender. 47 | 48 | ```text 49 | count total (s) self (s) function 50 | 1 2.203751 0.000457 rails#buffer_syntax() 51 | ``` 52 | 53 | [official docs]: http://vimdoc.sourceforge.net/htmldoc/repeat.html#profiling 54 | -------------------------------------------------------------------------------- /vim/search-replace-multiple-files.md: -------------------------------------------------------------------------------- 1 | # Search & Replace in multiple files 2 | 3 | I recently had to replace static files path in multiple files from a project 4 | I were working on, after boggling my mind trying to do it with 5 | [sed](http://en.wikipedia.org/wiki/Sed), I gave up and looked up how to do it 6 | using VIM, I was sure there was a way. 7 | 8 | When VIM is started, you can specify multiple files to open as buffers from the 9 | terminal: 10 | 11 | ```bash 12 | vim *.html 13 | ``` 14 | 15 | This will open all html files on the current directory as buffers. 16 | * You can list the buffers using `:ls` 17 | * You can add a buffer using `:badd ` 18 | * You can close a buffer using `:bdelete ` 19 | 20 | Now you can run commands on all open buffers: 21 | 22 | ```vimscript 23 | :bufdo 24 | ``` 25 | 26 | Searching all instances of **foo** and replacing with **bar**: 27 | 28 | ```vimscript 29 | :bufdo %s/foo/bar/ge 30 | ``` 31 | 32 | **Notice**: the **e** on the replace command tells vim to ignore errors, 33 | otherwise vim would print an error on each file that doesn't have a match for 34 | **foo** 35 | 36 | You can now open the buffers (`:buffer `) and verify that the 37 | text was replaced. 38 | 39 | But this command only replaced the text, we need to save the files to persist 40 | changes: 41 | 42 | You can either run another **bufdo** with the **update** command to save the 43 | files: 44 | 45 | ```vimscript 46 | :bufdo update 47 | ``` 48 | 49 | Or you can pipe it on the first command: 50 | 51 | ```vimscript 52 | :bufdo %s/foo/bar/g | update 53 | ``` 54 | 55 | And that's it! 56 | -------------------------------------------------------------------------------- /vim/yanking-text-to-register.md: -------------------------------------------------------------------------------- 1 | # Yanking text to register 2 | 3 | Yanking and deleting text will save the text to the same unnamed register. Every 4 | time you delete a word, your yanked word will be overwritten. This caused me 5 | endless amounts of frustration when I accidentally deleted a word and had to 6 | remember what I yanked earlier. 7 | 8 | I learned that you can specify a register to save your yanked word to by 9 | prepending your yank command with `"a`. Where `a` is a register. There are a 10 | number of different registers which do different things. If you want to learn 11 | more read VIM's [register 12 | documentation](http://vimdoc.sourceforge.net/htmldoc/change.html#registers). 13 | 14 | An example usage is: 15 | 16 | `"ayw` 17 | 18 | This will save the yanked word to the register `a`. After deleting various 19 | things in your file you can always paste your yanked word by: 20 | 21 | `"ap` 22 | 23 | You can view the contents of all registers via the `:registers` command. 24 | 25 | Even after deleting various words in your file, your yanked word will always be 26 | in register `a`. The VIM wiki has more details on [Replacing a word with yanked 27 | text](http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text). 28 | --------------------------------------------------------------------------------