{"version":"https://jsonfeed.org/version/1","title":"Hashrocket - Hashrocket Projects Posts","home_page_url":"https://hashrocket.com/blog","feed_url":"https://hashrocket.com/blog/tags/hashrocket-projects.json","author":{"name":"Hashrocket","url":"https://hashrocket.com/","avatar":"https://hashrocket.com/favicon-228.png"},"items":[{"id":"https://hashrocket.com/blog/posts/open-source-time-at-hashrocket","url":"https://hashrocket.com/blog/posts/open-source-time-at-hashrocket","title":"Open Source Time at Hashrocket","content_html":"It's Friday afternoon, my brain cells are fried, my stomach is full and it's time for Hashrocket's most cherished employment perk. That time when we can open  whatever editor, on whatever operating system, on whatever computer, with whatever keyboard and work on whatever we want. Open source time. \n\nWe call it open source time, but don't get it twisted, it's not time to work on open source software, but instead it's the _time itself_ which is open sourced. You can source it any way you want, openly.  And no, I'm not really sure what that means.  All I know is that my mind is free to _stretch_.  I can crack open the code to Phoenix, I can write a weird blog post and I can scratch that programmer itch that's been itching ever since I found out about `useMemo` on Monday.  That combined with an itch to make colorful squares move across a web browser _at different speeds_.  That combined with a wholly necessary need to find out why my vim plugins won't let me navigate around an Elixir project as fast as I want and a realization that I don't have the latest node version.\r\n\r\nSo I crack open github and think about all the better ways that I could find out what the latest version of node is, like, shouldn't there be an alert system for that?  And I read the node changelog, and I look up for the millionth time how to install a plugin using `asdf`.  Woah, can I hook up asdf plugin updating to `xargs` with the `-P` flag so I can update all my dev tools using every core of my processor?\r\n\r\nMaybe I got something done, maybe I didn't, but I itched and stretched and had fun exploring the technical world.  I got to exercise a different part of my programmer brain instead of trying to jam out one... last... feature for the client during what is typically the least productive and most bug heavy time of the week.  Doing this makes me a better programmer.  This makes me a better programmer for the following Monday and doing this consistently every Friday makes me a better programmer for the following year.\r\n\r\nOver time, you find that not only is your programmer self rejuvenated but you actually amass a fair number of interesting experiments.  Not all of them are ready to show off, to either the full internet or a limited number of people, but some are.  You can check out a small sample of our open source time projects at our [concepts](https://concepts.hashrocket.com) website.  As developers, we're multifaceted and it's great to be reminded that not only can we developer with efficiency and quality for our clients but we can also be creative, whimsical and curious. \r\n\r\nWhether it's creative fulfillment, tool sharpening, free discussion about hard problems, or whatever else that might happen when you have a computer in front of you and smart people around you, open source time is one of the things that makes me tick as a programmer and a gratifying employment perk that allows me to start the following Monday fresh and ready to once again provide the greatest possible value for my client.\r\n\r\nImage via \u003ca style=\"background-color:black;color:white;text-decoration:none;padding:4px 6px;font-family:-apple-system, BlinkMacSystemFont, \u0026quot;San Francisco\u0026quot;, \u0026quot;Helvetica Neue\u0026quot;, Helvetica, Ubuntu, Roboto, Noto, \u0026quot;Segoe UI\u0026quot;, Arial, sans-serif;font-size:12px;font-weight:bold;line-height:1.2;display:inline-block;border-radius:3px\" href=\"https://unsplash.com/@zacharylink?utm_medium=referral\u0026amp;utm_campaign=photographer-credit\u0026amp;utm_content=creditBadge\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Download free do whatever you want high-resolution photos from Zachary Peterson\"\u003e\u003cspan style=\"display:inline-block;padding:2px 3px\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" style=\"height:12px;width:auto;position:relative;vertical-align:middle;top:-2px;fill:white\" viewBox=\"0 0 32 32\"\u003e\u003ctitle\u003eunsplash-logo\u003c/title\u003e\u003cpath d=\"M10 9V0h12v9H10zm12 5h10v18H0V14h10v9h12v-9z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/span\u003e\u003cspan style=\"display:inline-block;padding:2px 3px\"\u003eZachary Peterson\u003c/span\u003e\u003c/a\u003e","content_text":"It's Friday afternoon, my brain cells are fried, my stomach is full and it's time for Hashrocket's most cherished employment perk. That time when we can open  whatever editor, on whatever operating system, on whatever computer, with whatever keyboard and work on whatever we want. Open source time. \n\nWe call it open source time, but don't get it twisted, it's not time to work on open source software, but instead it's the time itself which is open sourced. You can source it any way you want, openly.  And no, I'm not really sure what that means.  All I know is that my mind is free to stretch.  I can crack open the code to Phoenix, I can write a weird blog post and I can scratch that programmer itch that's been itching ever since I found out about useMemo on Monday.  That combined with an itch to make colorful squares move across a web browser at different speeds.  That combined with a wholly necessary need to find out why my vim plugins won't let me navigate around an Elixir project as fast as I want and a realization that I don't have the latest node version.\n\nSo I crack open github and think about all the better ways that I could find out what the latest version of node is, like, shouldn't there be an alert system for that?  And I read the node changelog, and I look up for the millionth time how to install a plugin using asdf.  Woah, can I hook up asdf plugin updating to xargs with the -P flag so I can update all my dev tools using every core of my processor?\n\nMaybe I got something done, maybe I didn't, but I itched and stretched and had fun exploring the technical world.  I got to exercise a different part of my programmer brain instead of trying to jam out one... last... feature for the client during what is typically the least productive and most bug heavy time of the week.  Doing this makes me a better programmer.  This makes me a better programmer for the following Monday and doing this consistently every Friday makes me a better programmer for the following year.\n\nOver time, you find that not only is your programmer self rejuvenated but you actually amass a fair number of interesting experiments.  Not all of them are ready to show off, to either the full internet or a limited number of people, but some are.  You can check out a small sample of our open source time projects at our concepts website.  As developers, we're multifaceted and it's great to be reminded that not only can we developer with efficiency and quality for our clients but we can also be creative, whimsical and curious. \n\nWhether it's creative fulfillment, tool sharpening, free discussion about hard problems, or whatever else that might happen when you have a computer in front of you and smart people around you, open source time is one of the things that makes me tick as a programmer and a gratifying employment perk that allows me to start the following Monday fresh and ready to once again provide the greatest possible value for my client.\n\nImage via unsplash-logoZachary Peterson\n","summary":"It's Friday afternoon, my brain cells are fried, my stomach is full and it's time for Hashrocket's most cherished employment perk. That time when we can open  whatever editor, on whatever operating system, on whatever computer, with whatever keyboard and work on whatever we want. Open source time. \n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/485/zachary-peterson-pB4bgMgcgWI-unsplash5.jpg","date_published":"2019-07-09T09:00:00-04:00","data_modified":"2019-07-09T14:37:27-04:00","author":{"name":"Chris Erin","url":"https://hashrocket.com/team/chris-erin","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/84/chris-erin.jpg"},"tags":["Hashrocket Projects","Open Source"]},{"id":"https://hashrocket.com/blog/posts/like-attack-postmortem","url":"https://hashrocket.com/blog/posts/like-attack-postmortem","title":"Incident Report: Like Attack","content_html":"On May 13th, til.hashrocket.com (TIL) experienced an attack. This attack had the effect of overstating the relative amount of affection that the users of TIL felt towards the posts on the front page of TIL. While most of our developers will bask in the glow of any and all affection, either automated or not, the unanticipated scale of affection combined with the notifications that our slack channel receives on relatively small increments of \"likes\" both chafed at our sense of truth and also served as a Denial of Chat (DOC) attack in our main chat channel. The root cause of this attack was a script making requests from a computer in Dearborn, Michigan written by an author who had discovered that there is no limit to the amount of liking that can be expressed on TIL through clicking and post requests.\n\n## Timeframe\r\n\r\n* May 13th 5:47 AM America/Chicago *First Evidence of Attack* - The Hashrocket General channel received a notification that post [Values clause in a select statement](http://til.hashrocket.com/posts/jzvk1aii5j-values-clause-in-a-select-statement) had 10 likes, subsequent to that notification, the channel received _another_ notification that post [Simulate componentDidMount with a useEffect](http://til.hashrocket.com/posts/rtievmxslv-simulate-componentdidmount-with-a-useeffect) also had 10 likes\r\n* May 13th 6:02 AM America/Chicago *TIL Slackbot Integration Removed* - To stop the DOC attack, the only employee working at this time removed the slack integration.\r\n* May 13th 6:30 PM America/Chicago *Like Functionality Taken Down* - Without anyone to address this issue until after billing hours, and with no way to block the requests, the decision was made to disable the like functionality and to restore a backup database from Sunday May 12th.\r\n* May 22nd 9:00 AM America/Chicago *Like Functionality Restored* - After crowdsourcing a hivemind solution we were able to implement a reasonable limit to our like functionality without having to severely restrain users that are truly thankful for the posts that we write.  Like functionality was down for a total of 207 hours.\r\n\r\n## Root Cause\r\n\r\nEver since the inception of TIL we've wanted to allow users to express appreciation without the usual internet barriers.  We don't think a user should have to sign-in to our platform just to \"Like\" a post, nor do we want to build sign-in functionality.  This no-sign-in-for-appreciation functionality is at odds with most of the internet, which views the desire to casually interact with a system as a chance to harvest an email address, the harvesting of such being just one of many ways to monetize your behavior.\r\n\r\nAs such, we placed no restrictions on how much you could like a post on the backend.  In the past, we've had co-workers who demonstrated how this could be taking advantage of by writing a shell script utilizing `curl` to post to the \"Like\" endpoint until their post was the most liked and at the top of the \"Most Liked Posts\" list on the [stats page](https://til.hashrocket.com/statistics).  These co-workers always had the good manners to reverse the untruthful and automated likes.\r\n\r\nOn the front-end we restrict \"likes\" by storing the liked posts as cookies.  When the user comes back to the site, we reference the cookie through JavaScript to determine if the user has liked a post before, and render the \"like\" in the \"liked\" state.  When in the \"liked\" state the user is not able to re-\"like\" that post unless they \"unlike\" it first.  When first implemented this feature, we stored each hash of a liked posts in one cookie.  Cookies however have a character limit, and some power users of TIL (it was me, your author, a power user) ran into that limit while expressing enthusiasm for their co-workers' posts.  Subsequently we switched to one cookie per \"liked\" post.\r\n\r\nWe've always known that without a hard server restriction someone could write a script to indiscriminately, callously and maliciously \"like\" posts.  What we did not know until the morning of May 13th, was that someone would actually do this.  The script was actively loading the page and clicking the button.  We know this because our Google Analytics spiked during that time period and in particular showed a spike of traffic from an ip address in Dearborn, Michigan.  Without loading an entire web page, the Google Analytics script would not be requested. \r\n\r\nWe are not ruling out that this could have been the indiscriminate work of a web crawler, but another curious and lazy feature of this attack was to only like posts on the first page.  There are 50 posts on the front page, and only those posts were exposed to the excessive affection.  We think that it is unlikely that a web crawler would not move on to the second page.\r\n\r\n## Resolution and Recovery\r\n\r\nWe take periodic database backups. This is a free feature of our Heroku supported database.  We were able to restore the data to a state that was prior to the attack without losing any posts.  This enabled us to get back to a state where all of our posts had the same number of likes that we had before the attack.\r\n\r\nWe also made the decision that we wouldn't restore the \"Like\" functionality if it would allow for the same disruptive behaviour.  The \"Like\" feature is beloved in our organization. For a little bit, we considered removing it for good, and perhaps relying on Twitter or other social media for our endorphonic feedback. Eventually we determined that we wanted users to express appreciation on their terms and not on the terms of third-party gigantic negativity infested platforms.\r\n\r\nOur solution was to place a soft rate limit on the \"Like\" functionality.  TIL is an Elixir app which offers some nice in-memory data stores like GenServers and we took advantage of that functionality to create a [custom rate limiter](https://github.com/hashrocket/tilex/blob/master/lib/tilex/rate_limiter.ex).\r\n\r\n## Conclusion\r\n\r\nIn the end, this was a slightly annoying, slightly amusing incident that exposed some purposely-left holes in our application that hadn't been exploited in four years.  We were able to turn it into something positive by using it as an opportunity to write a simple rate limiter, increasing the scope of TIL as an example application for Elixir and Phoenix.\r\n\r\nThank you for bearing with us and please remember to like a TIL post if you think it deserves recognition!\r\n","content_text":"On May 13th, til.hashrocket.com (TIL) experienced an attack. This attack had the effect of overstating the relative amount of affection that the users of TIL felt towards the posts on the front page of TIL. While most of our developers will bask in the glow of any and all affection, either automated or not, the unanticipated scale of affection combined with the notifications that our slack channel receives on relatively small increments of \"likes\" both chafed at our sense of truth and also served as a Denial of Chat (DOC) attack in our main chat channel. The root cause of this attack was a script making requests from a computer in Dearborn, Michigan written by an author who had discovered that there is no limit to the amount of liking that can be expressed on TIL through clicking and post requests.\nTimeframe\n\n\nMay 13th 5:47 AM America/Chicago First Evidence of Attack - The Hashrocket General channel received a notification that post Values clause in a select statement had 10 likes, subsequent to that notification, the channel received another notification that post Simulate componentDidMount with a useEffect also had 10 likes\nMay 13th 6:02 AM America/Chicago TIL Slackbot Integration Removed - To stop the DOC attack, the only employee working at this time removed the slack integration.\nMay 13th 6:30 PM America/Chicago Like Functionality Taken Down - Without anyone to address this issue until after billing hours, and with no way to block the requests, the decision was made to disable the like functionality and to restore a backup database from Sunday May 12th.\nMay 22nd 9:00 AM America/Chicago Like Functionality Restored - After crowdsourcing a hivemind solution we were able to implement a reasonable limit to our like functionality without having to severely restrain users that are truly thankful for the posts that we write.  Like functionality was down for a total of 207 hours.\n\nRoot Cause\n\nEver since the inception of TIL we've wanted to allow users to express appreciation without the usual internet barriers.  We don't think a user should have to sign-in to our platform just to \"Like\" a post, nor do we want to build sign-in functionality.  This no-sign-in-for-appreciation functionality is at odds with most of the internet, which views the desire to casually interact with a system as a chance to harvest an email address, the harvesting of such being just one of many ways to monetize your behavior.\n\nAs such, we placed no restrictions on how much you could like a post on the backend.  In the past, we've had co-workers who demonstrated how this could be taking advantage of by writing a shell script utilizing curl to post to the \"Like\" endpoint until their post was the most liked and at the top of the \"Most Liked Posts\" list on the stats page.  These co-workers always had the good manners to reverse the untruthful and automated likes.\n\nOn the front-end we restrict \"likes\" by storing the liked posts as cookies.  When the user comes back to the site, we reference the cookie through JavaScript to determine if the user has liked a post before, and render the \"like\" in the \"liked\" state.  When in the \"liked\" state the user is not able to re-\"like\" that post unless they \"unlike\" it first.  When first implemented this feature, we stored each hash of a liked posts in one cookie.  Cookies however have a character limit, and some power users of TIL (it was me, your author, a power user) ran into that limit while expressing enthusiasm for their co-workers' posts.  Subsequently we switched to one cookie per \"liked\" post.\n\nWe've always known that without a hard server restriction someone could write a script to indiscriminately, callously and maliciously \"like\" posts.  What we did not know until the morning of May 13th, was that someone would actually do this.  The script was actively loading the page and clicking the button.  We know this because our Google Analytics spiked during that time period and in particular showed a spike of traffic from an ip address in Dearborn, Michigan.  Without loading an entire web page, the Google Analytics script would not be requested. \n\nWe are not ruling out that this could have been the indiscriminate work of a web crawler, but another curious and lazy feature of this attack was to only like posts on the first page.  There are 50 posts on the front page, and only those posts were exposed to the excessive affection.  We think that it is unlikely that a web crawler would not move on to the second page.\nResolution and Recovery\n\nWe take periodic database backups. This is a free feature of our Heroku supported database.  We were able to restore the data to a state that was prior to the attack without losing any posts.  This enabled us to get back to a state where all of our posts had the same number of likes that we had before the attack.\n\nWe also made the decision that we wouldn't restore the \"Like\" functionality if it would allow for the same disruptive behaviour.  The \"Like\" feature is beloved in our organization. For a little bit, we considered removing it for good, and perhaps relying on Twitter or other social media for our endorphonic feedback. Eventually we determined that we wanted users to express appreciation on their terms and not on the terms of third-party gigantic negativity infested platforms.\n\nOur solution was to place a soft rate limit on the \"Like\" functionality.  TIL is an Elixir app which offers some nice in-memory data stores like GenServers and we took advantage of that functionality to create a custom rate limiter.\nConclusion\n\nIn the end, this was a slightly annoying, slightly amusing incident that exposed some purposely-left holes in our application that hadn't been exploited in four years.  We were able to turn it into something positive by using it as an opportunity to write a simple rate limiter, increasing the scope of TIL as an example application for Elixir and Phoenix.\n\nThank you for bearing with us and please remember to like a TIL post if you think it deserves recognition!\n","summary":"On May 13th, til.hashrocket.com (TIL) experienced an attack. This attack had the effect of overstating the relative amount of affection that the users of TIL felt towards the posts on the front page of TIL. While most of our developers will bask in the glow of any and all affection, either automated or not, the unanticipated scale of affection combined with the notifications that our slack channel receives on relatively small increments of \"likes\" both chafed at our sense of truth and also served as a Denial of Chat (DOC) attack in our main chat channel. The root cause of this attack was a script making requests from a computer in Dearborn, Michigan written by an author who had discovered that there is no limit to the amount of liking that can be expressed on TIL through clicking and post requests.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/482/image__1_.png","date_published":"2019-06-11T09:00:00-04:00","data_modified":"2019-06-04T10:53:42-04:00","author":{"name":"Chris Erin","url":"https://hashrocket.com/team/chris-erin","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/84/chris-erin.jpg"},"tags":["Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/2000-today-i-learned-posts","url":"https://hashrocket.com/blog/posts/2000-today-i-learned-posts","title":"2000 Today I Learned posts","content_html":"2000 TILs is a landmark but is just a small window into what we do at Hashrocket every day.\r\n\n\n# Two Thousand\r\n\r\nThis week, we published the 2000th post to our daily learning site, [Today I Learned](https://til.hashrocket.com). The [statistics page](https://til.hashrocket.com/statistics) gives a sense of the scope and scale of this ever-evolving project. It is the result of continual small contributions by the entire Hashrocket team.\r\n\r\nTwo thousand TILs began on April 13th, 2015. Springtime: a great time of year to begin something new. We've averaged a bit under two posts a day since starting to document these things in a digital, shareable way. Of course, before we had TIL as a platform there was a fair amount of non-shareable, non-documented learning. Okay, a \"fair amount\" is an understatement; Hashrocket's entire history has been about teaching and learning and craftsmanship and sharing. You can't be a great developer without obsessing over all the small ways that code can be written more elegantly and efficiently, and Hashrocket has seen more than a handful of great developers grace the keyboards and pairing stations of our two main offices.\r\n\r\nWeb development was once just text, tags, and the network, but every year since the early nineties has seen higher expectations for what a website should be. Our eyes recoil at 1995's [Space Jam](http://www.warnerbros.com/archive/spacejam/movie/jam.htm) or Bob Dole's 1996 Campaign [Web Site](http://www.dolekemp96.org/main.htm). In 2006, creating a website had become prohibitively expensive for small organizations. Creating the expansive websites of that era took big teams of developers working with seemingly insane managerial overhead and software that was most definitely not free. Hashrocket's conceit in 2008 was that great developers using smart open source software (Ruby on Rails) and subtracting that managerial overhead would bring great websites to life for anybody with an idea.\r\n\r\nThere is not a website built in 2008 that would come close to meeting expectations today. There's been at least five generations of JavaScript technologies since then! Security and performance requirements have multiplied, data sizes have gone from GB to TB, and of course the number of screen sizes that must be accommodated has grown as the screen sizes themselves (and bandwidth) have shrunk.\r\n\r\nHashrocket's advantage in 2008 was retaining a set of developers that were at the cutting edge of web development, wanting to stay there, and setting up structures that promoted learning and expanding the craft of web development. From [bookclubs](https://vimeo.com/9512003) in 2010 to internal [conferences](https://github.com/jgdavey/sqltricks) in 2012, to [mentoring](https://www.codeplatoon.org/code-platoon-week-four-sql-and-working-with-databases/) in 2018, the developers at Hashrocket have continually pursued the active structures that facilitate sharing and learning. Today it's our definitive strength that we learn together and share what we learn. Every Friday we have Show 'n Tell, and of course we pair.\r\n\r\nPairing is continual positive reinforcement of sharing what you know. There is an inherent joy in showing somebody something new, and that in and of itself can drive you to explore further each of the endlessly deep technologies that we use on a daily basis.\r\n\r\nFrom that perspective, 2000 posts in Today I Learned is really not all that impressive. It could easily be 5000, or, if every little detail that each of us has internalized over the last three years were documented it would easily be 10,000. TIL serves as a small window into our company and represents very well our collective interests and joint journey in becoming ever better web devs.\r\n","content_text":"2000 TILs is a landmark but is just a small window into what we do at Hashrocket every day.\nTwo Thousand\n\nThis week, we published the 2000th post to our daily learning site, Today I Learned. The statistics page gives a sense of the scope and scale of this ever-evolving project. It is the result of continual small contributions by the entire Hashrocket team.\n\nTwo thousand TILs began on April 13th, 2015. Springtime: a great time of year to begin something new. We've averaged a bit under two posts a day since starting to document these things in a digital, shareable way. Of course, before we had TIL as a platform there was a fair amount of non-shareable, non-documented learning. Okay, a \"fair amount\" is an understatement; Hashrocket's entire history has been about teaching and learning and craftsmanship and sharing. You can't be a great developer without obsessing over all the small ways that code can be written more elegantly and efficiently, and Hashrocket has seen more than a handful of great developers grace the keyboards and pairing stations of our two main offices.\n\nWeb development was once just text, tags, and the network, but every year since the early nineties has seen higher expectations for what a website should be. Our eyes recoil at 1995's Space Jam or Bob Dole's 1996 Campaign Web Site. In 2006, creating a website had become prohibitively expensive for small organizations. Creating the expansive websites of that era took big teams of developers working with seemingly insane managerial overhead and software that was most definitely not free. Hashrocket's conceit in 2008 was that great developers using smart open source software (Ruby on Rails) and subtracting that managerial overhead would bring great websites to life for anybody with an idea.\n\nThere is not a website built in 2008 that would come close to meeting expectations today. There's been at least five generations of JavaScript technologies since then! Security and performance requirements have multiplied, data sizes have gone from GB to TB, and of course the number of screen sizes that must be accommodated has grown as the screen sizes themselves (and bandwidth) have shrunk.\n\nHashrocket's advantage in 2008 was retaining a set of developers that were at the cutting edge of web development, wanting to stay there, and setting up structures that promoted learning and expanding the craft of web development. From bookclubs in 2010 to internal conferences in 2012, to mentoring in 2018, the developers at Hashrocket have continually pursued the active structures that facilitate sharing and learning. Today it's our definitive strength that we learn together and share what we learn. Every Friday we have Show 'n Tell, and of course we pair.\n\nPairing is continual positive reinforcement of sharing what you know. There is an inherent joy in showing somebody something new, and that in and of itself can drive you to explore further each of the endlessly deep technologies that we use on a daily basis.\n\nFrom that perspective, 2000 posts in Today I Learned is really not all that impressive. It could easily be 5000, or, if every little detail that each of us has internalized over the last three years were documented it would easily be 10,000. TIL serves as a small window into our company and represents very well our collective interests and joint journey in becoming ever better web devs.\n","summary":"2000 TILs is a landmark but is just a small window into what we do at Hashrocket every day.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/353/blog_card.png","date_published":"2019-05-07T09:00:00-04:00","data_modified":"2019-05-01T16:35:06-04:00","author":{"name":"Chris Erin","url":"https://hashrocket.com/team/chris-erin","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/84/chris-erin.jpg"},"tags":["Community","Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/today-i-learned-2018-year-in-review","url":"https://hashrocket.com/blog/posts/today-i-learned-2018-year-in-review","title":"Today I Learned 2018: Year In Review","content_html":"Today I Learned is an [open-source](https://github.com/hashrocket/tilex) Elixir Phoenix project by Hashrocket. One of the fun things about January is being inspired to look back at the past year. This blog revisits some of the top trends and posts in [Today I Learned](https://til.hashrocket.com/) of 2018.\n\nIn 2018, we at Hashrocket posted **379** TILs. On average, we collectively were learning something new every day!\r\n\r\nOur top-two most popular posts of the year were both **[#elixir](https://til.hashrocket.com/elixir)** posts:\r\n\r\n- [Parameter Filtering in Elixir Phoenix Logs](https://til.hashrocket.com/posts/rtx2mhxn3y-parameter-filtering-in-elixir-phoenix-logs)\r\n- [Your slowest Elixir Tests](https://til.hashrocket.com/posts/1nenrfasdp-your-slowest-elixir-tests)\r\n\r\nThe three topics that we posted TILs about most often were:\r\n\r\n 1. [#javascript](https://til.hashrocket.com/javascript) (**56** posts)\r\n 2. [#react](https://til.hashrocket.com/react) (**52** posts)\r\n 3. [#reasonml](https://til.hashrocket.com/reasonml) (**44** posts)\r\n\r\nA huge portion of our work this year involved React and JavaScript so it is no surprise that we were learning a lot in those areas! Here are the top posts from each of those categories:\r\n\r\n- [Share SCSS Variables with Javascript](https://til.hashrocket.com/posts/sxbrscjuqu-share-scss-variables-with-javascript)\r\n- [create-react-app Has A Default Test Setup File](https://til.hashrocket.com/posts/hzqwty5ykx-create-react-app-has-a-default-test-setup-file)\r\n- [Format The Current ReasonML File Within Vim](https://til.hashrocket.com/posts/unuvmuspbp-format-the-current-reasonml-file-within-vim)\r\n\r\nOur top two most loved channels were the same as above, but **[#command-line](https://til.hashrocket.com/command-line)** squeezed onto the podium as the number three most loved topic. Everyone loves a good command line trick! This end-of-year post was the most-loved command line TIL of 2018:\r\n\r\n- [Easily delete a long word in terminal](https://til.hashrocket.com/posts/jpn9vlahfe-easily-delete-a-long-word-in-terminal)\r\n\r\nIn order to come up with the 2018 stats, I had to learn how to write some Postgres queries. Of course, it is only appropriate that I posted about what I learned in a TIL. You can read it here (and find out who had the on-average most-loved TILs of 2018):\r\n\r\n- [First Postgres Queries: a Join and an Alias](https://til.hashrocket.com/posts/ihqvzp4ivx-first-postgres-queries-a-join-and-an-alias)\r\n\r\nAs interesting as it is to look back on all the things we learned in 2018, it is even more exciting to consider the year ahead. Will we see a uptick in Elixir posts? Will we discover even more Vim tricks? Our goal is to keep learning new things every day, and to open up new areas of exploration. Here's to TIL in 2019!\r\n\r\n---\r\nPhoto by \u003ca style=\"background-color:black;color:white;text-decoration:none;padding:4px 6px;font-family:-apple-system, BlinkMacSystemFont, \u0026quot;San Francisco\u0026quot;, \u0026quot;Helvetica Neue\u0026quot;, Helvetica, Ubuntu, Roboto, Noto, \u0026quot;Segoe UI\u0026quot;, Arial, sans-serif;font-size:12px;font-weight:bold;line-height:1.2;display:inline-block;border-radius:3px\" href=\"https://unsplash.com/@ahmadossayli?utm_medium=referral\u0026amp;utm_campaign=photographer-credit\u0026amp;utm_content=creditBadge\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Download free do whatever you want high-resolution photos from Ahmad Ossayli\"\u003e\u003cspan style=\"display:inline-block;padding:2px 3px\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" style=\"height:12px;width:auto;position:relative;vertical-align:middle;top:-2px;fill:white\" viewBox=\"0 0 32 32\"\u003e\u003ctitle\u003eunsplash-logo\u003c/title\u003e\u003cpath d=\"M10 9V0h12v9H10zm12 5h10v18H0V14h10v9h12v-9z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/span\u003e\u003cspan style=\"display:inline-block;padding:2px 3px\"\u003eAhmad Ossayli\u003c/span\u003e\u003c/a\u003e from [Unsplash](https://unsplash.com/)\r\n","content_text":"Today I Learned is an open-source Elixir Phoenix project by Hashrocket. One of the fun things about January is being inspired to look back at the past year. This blog revisits some of the top trends and posts in Today I Learned of 2018.\n\nIn 2018, we at Hashrocket posted 379 TILs. On average, we collectively were learning something new every day!\n\nOur top-two most popular posts of the year were both #elixir posts:\n\n\nParameter Filtering in Elixir Phoenix Logs\nYour slowest Elixir Tests\n\n\nThe three topics that we posted TILs about most often were:\n\n\n#javascript (56 posts)\n#react (52 posts)\n#reasonml (44 posts)\n\n\nA huge portion of our work this year involved React and JavaScript so it is no surprise that we were learning a lot in those areas! Here are the top posts from each of those categories:\n\n\nShare SCSS Variables with Javascript\ncreate-react-app Has A Default Test Setup File\nFormat The Current ReasonML File Within Vim\n\n\nOur top two most loved channels were the same as above, but #command-line squeezed onto the podium as the number three most loved topic. Everyone loves a good command line trick! This end-of-year post was the most-loved command line TIL of 2018:\n\n\nEasily delete a long word in terminal\n\n\nIn order to come up with the 2018 stats, I had to learn how to write some Postgres queries. Of course, it is only appropriate that I posted about what I learned in a TIL. You can read it here (and find out who had the on-average most-loved TILs of 2018):\n\n\nFirst Postgres Queries: a Join and an Alias\n\n\nAs interesting as it is to look back on all the things we learned in 2018, it is even more exciting to consider the year ahead. Will we see a uptick in Elixir posts? Will we discover even more Vim tricks? Our goal is to keep learning new things every day, and to open up new areas of exploration. Here's to TIL in 2019!\n\n\n\nPhoto by unsplash-logoAhmad Ossayli from Unsplash\n","summary":"Today I Learned is an open-source Elixir Phoenix project by Hashrocket. One of the fun things about January is being inspired to look back at the past year. This blog revisits some of the top trends and posts in Today I Learned of 2018.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/452/ahmad-ossayli-395625-unsplash2.jpg","date_published":"2019-01-15T09:00:00-05:00","data_modified":"2019-05-21T14:42:09-04:00","author":{"name":"Suzanne Erin","url":"https://hashrocket.com/team/suzanne-erin","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/101/suzanne_erin.jpg"},"tags":["Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/today-i-learned-in-phoenix","url":"https://hashrocket.com/blog/posts/today-i-learned-in-phoenix","title":"Today I Learned in Phoenix","content_html":"The Phoenix port of Today I Learned, [Tilex](https://til.hashrocket.com/), is live.\n\n[Today I Learned](https://til.hashrocket.com) began as a Ruby on Rails application.\r\nWe [open-sourced](https://hashrocket.com/blog/posts/open-sourcing-today-i-learned) the code after launch and have maintained it for over two\r\nyears. Our mission:\r\n\r\n\u003e Today I Learned is an open-source project by Hashrocket that exists to\r\n\u003e catalogue the sharing \u0026 accumulation of knowledge as it happens day-to-day.\r\n\u003e Posts have a 200-word limit, and posting is open to any Rocketeer as well as\r\n\u003e selected friends of Hashrocket. We hope you enjoy learning along with us.\r\n\r\nToday, we are moving forward with an Elixir/Phoenix port of the project.\r\nHere's a little more about the project, focusing on the work, technology, some\r\nobservations, the people behind it, and the future.\r\n\r\n### Work\r\n\r\nThis project began over two years ago as my\r\nHashrocket apprentice project. Here's the [launch\r\nannouncement](/blog/posts/introducing-today-i-learned) from that time.\r\n\r\nWe [open-sourced](/blog/posts/open-sourcing-today-i-learned) the Ruby on Rails\r\napplication in February 2016. A handful of forks are in production,\r\ndocumented in the [usage\r\nguide](https://github.com/hashrocket/hr-til/blob/master/USAGE.md).\r\n\r\nWhy port this application to Elixir? My curiosity in Elixir\r\ndeepened after reading _Seven More Languages in Seven Weeks_ by Bruce Tate,\r\nFred Daoud, Jack Moffitt, and Ian Dees, which features Elixir.\r\nElixir's unique _raison d'être_– a Rubyist's quest for a language that sidestepped\r\nsome of the limitations of the Ruby language– resonated with me.\r\nMany on our team have grown to love Elixir, and we wanted a project that featured\r\nit.\r\n\r\nIn October 2016 we made our initial commit to the port. The\r\nname, Tilex, came from the Elixir convention of adding 'ex' to everything. And\r\nso, Tilex ('TIL' + 'ex') was born.\r\n\r\n### Technology\r\n\r\nWe created our application using Phoenix 1.2 (since upgraded to 1.3) and set to work.\r\n\r\nFor project management, we chose to use a [Github\r\nproject](https://github.com/hashrocket/tilex/projects/1).\r\nGithub Projects is a great choice for a simple project. A key\r\nadvantage over a tool like Trello or Pivotal Tracker is that it's already\r\nintegrated with your repository.\r\n\r\nFor hosting we chose Heroku. Setup was not as simple as launching a Ruby on\r\nRails application, but was still pretty straightforward.\r\n\r\nWe've been running our tests with Travis CI, including a\r\n[Credo](https://github.com/rrrene/credo) integration, and have used [AppSignal](https://appsignal.com/)\r\nfor error monitoring.\r\n\r\n### Observations\r\n\r\nHere are few of my personal observations as a member of this team.\r\n\r\nFirst, Elixir is a pleasure to write and maintain. The language mixes some of\r\nthe best ideas from Ruby with an outstanding foundation in Erlang. The combination of\r\nthe joy of Ruby idioms, functional programming, and features such as pattern matching,\r\nis truly unique.\r\n\r\nAlso noteworthy: we didn't write as many tests for Tilex. I credit a mix of\r\nexperience and bravado earned by having written almost this entire application\r\nbefore. Precompiled languages catch a lot of issues in development,\r\ngiving us a sense of confidence when deciding whether to test.\r\n\r\nAs noted by many others, Elixir's tooling is not as polished as Ruby's, but\r\nit's improving all the time. As we built the application, we got to watch it\r\nget better.\r\n\r\nThis was a learning experience, and here are few posts I wrote along the\r\nway:\r\n\r\n- [Integration Testing Phoenix With\r\n  Wallaby](/blog/posts/integration-testing-phoenix-with-wallaby)\r\n- [Titled URL Slugs in Phoenix](/blog/posts/titled-url-slugs-in-phoenix)\r\n\r\nThe Today I Learned [elixir channel](https://til.hashrocket.com/elixir) is itself loaded\r\nwith small discoveries we made during the process.\r\n\r\n### People\r\n\r\nThe following people committed to the Tilex release:\r\n\r\n- Brian Dunn\r\n- Chris Erin\r\n- Cody Roberts\r\n- Dorian Karter\r\n- Jake Worth\r\n- Josh Branchaud\r\n- Lexin Gong\r\n- Taylor Mock\r\n- Vidal Ekechukwu\r\n\r\nThanks as well to Cameron Daigle, who created the design. We also appreciate\r\nthe [Rails app\r\ncontributors](https://github.com/hashrocket/hr-til/graphs/contributors); many\r\nof the features we recreated were built by them. Also, my thanks to\r\nHashrocket for the paid open-source time which made this possible.\r\n\r\nMost importantly, thank you to my coworkers, who have built this site\r\ninto something amazing. Today I Learned is nothing without the posts. I learn\r\nsomething from our feed every day.\r\n\r\n### Future\r\n\r\nHere's how we plan to celebrate this release.\r\n\r\nFirst, more work! As of this writing, we have a handful of [open\r\nissues](https://github.com/hashrocket/tilex/issues) on Github. Interested in contributing? Check out our [contributing page](https://github.com/hashrocket/tilex/blob/master/CONTRIBUTING.md) for more information about getting started.\r\n\r\nI'd also like to do some benchmarking. Is there a performance or resource advantage to this\r\nplatform? How does our churn compare, and how easy will it be to maintain? I'm curious about these questions.\r\n\r\nAs for the Rails application: can we maintain a codebase we don't use? For now,\r\nI plan to update the documentation of that project to indicate that it's not\r\nthe deployed version of Today I Learned, and then work on a plan for the\r\nfuture.\r\n\r\nPlease enjoy the new Elixir/Phoenix version of Today I Learned, hit us up on\r\n[Github](https://github.com/hashrocket/tilex) or\r\n[Twitter](https://twitter.com/hashrockettil), and keep learning every day.\r\n\r\n---\r\n\r\nCover photo by \u003ca style=\"background-color:black;color:white;text-decoration:none;padding:4px 6px;font-family:-apple-system, BlinkMacSystemFont, \u0026quot;San Francisco\u0026quot;, \u0026quot;Helvetica Neue\u0026quot;, Helvetica, Ubuntu, Roboto, Noto, \u0026quot;Segoe UI\u0026quot;, Arial, sans-serif;font-size:12px;font-weight:bold;line-height:1.2;display:inline-block;border-radius:3px;\" href=\"https://unsplash.com/@jonathanbean?utm_medium=referral\u0026amp;utm_campaign=photographer-credit\u0026amp;utm_content=creditBadge\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Download free do whatever you want high-resolution photos from Jonathan Bean\"\u003e\u003cspan style=\"display:inline-block;padding:2px 3px;\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" style=\"height:12px;width:auto;position:relative;vertical-align:middle;top:-1px;fill:white;\" viewBox=\"0 0 32 32\"\u003e\u003ctitle\u003e\u003c/title\u003e\u003cpath d=\"M20.8 18.1c0 2.7-2.2 4.8-4.8 4.8s-4.8-2.1-4.8-4.8c0-2.7 2.2-4.8 4.8-4.8 2.7.1 4.8 2.2 4.8 4.8zm11.2-7.4v14.9c0 2.3-1.9 4.3-4.3 4.3h-23.4c-2.4 0-4.3-1.9-4.3-4.3v-15c0-2.3 1.9-4.3 4.3-4.3h3.7l.8-2.3c.4-1.1 1.7-2 2.9-2h8.6c1.2 0 2.5.9 2.9 2l.8 2.4h3.7c2.4 0 4.3 1.9 4.3 4.3zm-8.6 7.5c0-4.1-3.3-7.5-7.5-7.5-4.1 0-7.5 3.4-7.5 7.5s3.3 7.5 7.5 7.5c4.2-.1 7.5-3.4 7.5-7.5z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/span\u003e\u003cspan style=\"display:inline-block;padding:2px 3px;\"\u003eJonathan Bean\u003c/span\u003e\u003c/a\u003e on Unsplash.com","content_text":"The Phoenix port of Today I Learned, Tilex, is live.\n\nToday I Learned began as a Ruby on Rails application.\nWe open-sourced the code after launch and have maintained it for over two\nyears. Our mission:\n\n\nToday I Learned is an open-source project by Hashrocket that exists to\ncatalogue the sharing \u0026amp; accumulation of knowledge as it happens day-to-day.\nPosts have a 200-word limit, and posting is open to any Rocketeer as well as\nselected friends of Hashrocket. We hope you enjoy learning along with us.\n\n\nToday, we are moving forward with an Elixir/Phoenix port of the project.\nHere's a little more about the project, focusing on the work, technology, some\nobservations, the people behind it, and the future.\nWork\n\nThis project began over two years ago as my\nHashrocket apprentice project. Here's the launch\nannouncement from that time.\n\nWe open-sourced the Ruby on Rails\napplication in February 2016. A handful of forks are in production,\ndocumented in the usage\nguide.\n\nWhy port this application to Elixir? My curiosity in Elixir\ndeepened after reading Seven More Languages in Seven Weeks by Bruce Tate,\nFred Daoud, Jack Moffitt, and Ian Dees, which features Elixir.\nElixir's unique raison d'être– a Rubyist's quest for a language that sidestepped\nsome of the limitations of the Ruby language– resonated with me.\nMany on our team have grown to love Elixir, and we wanted a project that featured\nit.\n\nIn October 2016 we made our initial commit to the port. The\nname, Tilex, came from the Elixir convention of adding 'ex' to everything. And\nso, Tilex ('TIL' + 'ex') was born.\nTechnology\n\nWe created our application using Phoenix 1.2 (since upgraded to 1.3) and set to work.\n\nFor project management, we chose to use a Github\nproject.\nGithub Projects is a great choice for a simple project. A key\nadvantage over a tool like Trello or Pivotal Tracker is that it's already\nintegrated with your repository.\n\nFor hosting we chose Heroku. Setup was not as simple as launching a Ruby on\nRails application, but was still pretty straightforward.\n\nWe've been running our tests with Travis CI, including a\nCredo integration, and have used AppSignal\nfor error monitoring.\nObservations\n\nHere are few of my personal observations as a member of this team.\n\nFirst, Elixir is a pleasure to write and maintain. The language mixes some of\nthe best ideas from Ruby with an outstanding foundation in Erlang. The combination of\nthe joy of Ruby idioms, functional programming, and features such as pattern matching,\nis truly unique.\n\nAlso noteworthy: we didn't write as many tests for Tilex. I credit a mix of\nexperience and bravado earned by having written almost this entire application\nbefore. Precompiled languages catch a lot of issues in development,\ngiving us a sense of confidence when deciding whether to test.\n\nAs noted by many others, Elixir's tooling is not as polished as Ruby's, but\nit's improving all the time. As we built the application, we got to watch it\nget better.\n\nThis was a learning experience, and here are few posts I wrote along the\nway:\n\n\nIntegration Testing Phoenix With\nWallaby\nTitled URL Slugs in Phoenix\n\n\nThe Today I Learned elixir channel is itself loaded\nwith small discoveries we made during the process.\nPeople\n\nThe following people committed to the Tilex release:\n\n\nBrian Dunn\nChris Erin\nCody Roberts\nDorian Karter\nJake Worth\nJosh Branchaud\nLexin Gong\nTaylor Mock\nVidal Ekechukwu\n\n\nThanks as well to Cameron Daigle, who created the design. We also appreciate\nthe Rails app\ncontributors; many\nof the features we recreated were built by them. Also, my thanks to\nHashrocket for the paid open-source time which made this possible.\n\nMost importantly, thank you to my coworkers, who have built this site\ninto something amazing. Today I Learned is nothing without the posts. I learn\nsomething from our feed every day.\nFuture\n\nHere's how we plan to celebrate this release.\n\nFirst, more work! As of this writing, we have a handful of open\nissues on Github. Interested in contributing? Check out our contributing page for more information about getting started.\n\nI'd also like to do some benchmarking. Is there a performance or resource advantage to this\nplatform? How does our churn compare, and how easy will it be to maintain? I'm curious about these questions.\n\nAs for the Rails application: can we maintain a codebase we don't use? For now,\nI plan to update the documentation of that project to indicate that it's not\nthe deployed version of Today I Learned, and then work on a plan for the\nfuture.\n\nPlease enjoy the new Elixir/Phoenix version of Today I Learned, hit us up on\nGithub or\nTwitter, and keep learning every day.\n\n\n\nCover photo by Jonathan Bean on Unsplash.com\n","summary":"The Phoenix port of Today I Learned, Tilex, is live.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/426/jonathan-bean-284904.jpg","date_published":"2017-09-05T09:00:00-04:00","data_modified":"2020-02-06T23:32:21-05:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Elixir","Phoenix","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/exploring-hashrockets-vimbundle-vim-hashrocket","url":"https://hashrocket.com/blog/posts/exploring-hashrockets-vimbundle-vim-hashrocket","title":"Vim Hashrocket","content_html":"Hashrocket committed to Vim early in our history, and it's been a crucial decision. When we set up a new development machine, we\r\ninstall the [Dotmatrix](https://github.com/hashrocket/dotmatrix), a library of\r\nconfigurations that includes our favorite, must-have Vim plugins. This blog focuses on [Vim Hashrocket](https://github.com/hashrocket/vim-hashrocket/).\n\n### Vim Hashrocket\r\n\r\n[Vim Hashrocket](https://github.com/hashrocket/vim-hashrocket/) is a collection\r\nof settings our team shares. Spend enough time\r\nwriting code with Vim on a shared machine, and you'll find that the Vim configuration\r\nfile in the root directory (`.vimrc`) swells to hundreds of lines,\r\nas each developer adds their own favorite settings. Vim Hashrocket codifies that into a plugin. It's a neatly organized\r\njunk drawer that reflects many of our evolving goals as a development team.\r\n\r\nHere are a few noteworthy settings in the 227-LOC `hashrocket.vim` plugin.\r\n\r\n### NotRocket\r\n\r\n`:NotRocket` (line 36) is one of those incantations that makes Vim users feel like\r\nmagicians. NotRocket substitutes pre-Ruby 1.9 hashrockets (`=\u003e`) for Ruby\r\n1.9-and-after colons (`:`).  Both are supported in modern versions of\r\nRuby, but many people prefer the colon, and whichever you choose, consistency\r\nis a worthy goal. `:NotRocket` helps us standardize legacy code.\r\n\r\n### Rails and Gem Projections\r\n\r\nLines 62-144 define a series of projections for use with\r\n[Projectionist.vim](https://github.com/tpope/vim-projectionist). What are\r\nprojections? These are command-mode commands like `:Econtroller users`, which\r\nhelps you navigate to a `UsersController` or provides a boilerplate file if it does not exist.\r\n\r\nWe start by extending the existing projections provided in other libraries, adding\r\na `presenter` projection to support the Presenter pattern. Next, we define a series\r\nof `rails_gem_projections`– projections that leverage [Bundler.vim](https://github.com/tpope/vim-bundler/) to\r\nadd projections based on the contents of your Rails `Gemfile`. Using the gem Cucumber?\r\nYou'll get an `:Efeature` command. Factory Girl? `:Efactory`. These commonsense\r\nmappings save time.\r\n\r\n### Mappings\r\n\r\n`hashrocket.vim` continues with a series of great copy-and-paste mappings, including mappings to copy to\r\nend of line, copy to system clipboard, and copy a whole file to system clipboard.\r\n\r\nLines 162 and 163 add two insert-mode mappings I love: `bpry` and `ipry`, which extend to `require 'pry'; binding.pry;` and `require IEx; IEx.pry;` respectively. We use these to require and bind leading debuggers for Ruby and Elixir.\r\n\r\nLines 190 to 207 add the command `:UnusedSteps`, which identifies unused Cucumber step definitions in your integration test\r\nsuite. This command is useful for cleanup on a large test-driven application.\r\n\r\nWe also turn spell checking on as a default in Git commit messages, with:\r\n\r\n```viml\r\nautocmd FileType gitcommit              setlocal spell\r\n```\r\n\r\nOne mapping I like a lot was contributed by Josh Branchaud, on line 223:\r\n\r\n```viml\r\nautocmd FileType help nnoremap q :q\u003ccr\u003e\r\n```\r\n\r\nThis lets us quit Vim help pages with `q` in normal mode (no semicolon), the same way you\r\ncan quit other terminal programs.\r\n\r\nHere are two more excellent mappings from lines 224 and 225:\r\n\r\n```viml\r\nautocmd FileType ruby nmap \u003cbuffer\u003e \u003cleader\u003ebt \u003cPlug\u003eBlockToggle\r\nautocmd BufRead *_spec.rb map \u003cbuffer\u003e \u003cleader\u003el \u003cPlug\u003eExtractRspecLet\r\n```\r\n\r\nThe first mapping gives us easy access to the features of\r\n[vim-blockle](https://github.com/jgdavey/vim-blockle), which swaps Ruby blocks\r\nwritten in the curly braces syntax (`{}`) to the do-end syntax (`do end`), and\r\nvice versa. When to use one or the other is mostly subjective, and with this\r\nmapping, we can rapidly compare each choice.\r\n\r\nThe second mapping calls the `:ExtractRspecLet` from the\r\n[vim-weefactor](https://github.com/jgdavey/vim-weefactor) plugin, swapping\r\nlocal variables defined in an RSpec examples for `let` blocks:\r\n\r\n```ruby\r\n# spec/application_spec.rb\r\n\r\nuser = FactoryGirl.create(:user) # =\u003e :ExtractRspecLet\r\nlet(:user) { FactoryGirl.create(:user)\r\n```\r\n\r\nAgain, this choice can be subjective, and with this mapping and the underlying\r\nlibrary, we get to compare each option with one command.\r\n\r\nThe last mapping in the file is a blockbuster. If you're editing an SQL file in\r\na Tmux session, run `\u003cleader\u003et` from normal mode, and your file will be read\r\ninto the session and window of your choice:\r\n\r\n```viml\r\nautocmd FileType sql nmap \u003cbuffer\u003e \u003cleader\u003et :\u003cC-U\u003ew \\| call Send_to_Tmux(\"\\\\i \".expand(\"%\").\"\\n\")\u003cCR\u003e\r\n```\r\n\r\nStart a `psql` session, and you've got a fast way to iterate on an SQL statement from Vim. The command even writes the file for you before sending it to the window.\r\n\r\n### Conclusion\r\n\r\nHow does this apply to you? Consider writing your own Vim plugin that captures\r\nyour favorite settings, install Vim Hashrocket to write code the way we do, or\r\ninstall the Dotmatrix for this and many other settings. Not every person on our\r\nour team has all of these plugins on their personal machines, but the shared\r\ntooling is vital when we start collaborating.\r\n\r\nNo exploration of a Hashrocket Vim plugin would be complete without thanking\r\n[Tim Pope](https://github.com/tpope), a Rocketeer who built many of these libraries, as well as all the contributors who have\r\nmade them better over the years.\r\n\r\nIf you're in Chicago, stop by [Vim\r\nChicago](https://www.meetup.com/Vim-Chicago/) to talk plugins and more. Likewise, the 'Today I Learned' [#vim channel](https://til.hashrocket.com/vim) contains\r\nhundreds of our favorite tips and tricks to leverage this classic editor.\r\n\r\nStay tuned as I continue to explore the Hashrocket Vimbundle in future posts.\r\n\r\n\u003csup\u003ePhoto Credit: Barn Images, https://unsplash.com/photos/t5YUoHW6zRo. Accessed 15 April 2017.\u003c/sup\u003e","content_text":"Hashrocket committed to Vim early in our history, and it's been a crucial decision. When we set up a new development machine, we\ninstall the Dotmatrix, a library of\nconfigurations that includes our favorite, must-have Vim plugins. This blog focuses on Vim Hashrocket.\nVim Hashrocket\n\nVim Hashrocket is a collection\nof settings our team shares. Spend enough time\nwriting code with Vim on a shared machine, and you'll find that the Vim configuration\nfile in the root directory (.vimrc) swells to hundreds of lines,\nas each developer adds their own favorite settings. Vim Hashrocket codifies that into a plugin. It's a neatly organized\njunk drawer that reflects many of our evolving goals as a development team.\n\nHere are a few noteworthy settings in the 227-LOC hashrocket.vim plugin.\nNotRocket\n\n:NotRocket (line 36) is one of those incantations that makes Vim users feel like\nmagicians. NotRocket substitutes pre-Ruby 1.9 hashrockets (=\u0026gt;) for Ruby\n1.9-and-after colons (:).  Both are supported in modern versions of\nRuby, but many people prefer the colon, and whichever you choose, consistency\nis a worthy goal. :NotRocket helps us standardize legacy code.\nRails and Gem Projections\n\nLines 62-144 define a series of projections for use with\nProjectionist.vim. What are\nprojections? These are command-mode commands like :Econtroller users, which\nhelps you navigate to a UsersController or provides a boilerplate file if it does not exist.\n\nWe start by extending the existing projections provided in other libraries, adding\na presenter projection to support the Presenter pattern. Next, we define a series\nof rails_gem_projections– projections that leverage Bundler.vim to\nadd projections based on the contents of your Rails Gemfile. Using the gem Cucumber?\nYou'll get an :Efeature command. Factory Girl? :Efactory. These commonsense\nmappings save time.\nMappings\n\nhashrocket.vim continues with a series of great copy-and-paste mappings, including mappings to copy to\nend of line, copy to system clipboard, and copy a whole file to system clipboard.\n\nLines 162 and 163 add two insert-mode mappings I love: bpry and ipry, which extend to require 'pry'; binding.pry; and require IEx; IEx.pry; respectively. We use these to require and bind leading debuggers for Ruby and Elixir.\n\nLines 190 to 207 add the command :UnusedSteps, which identifies unused Cucumber step definitions in your integration test\nsuite. This command is useful for cleanup on a large test-driven application.\n\nWe also turn spell checking on as a default in Git commit messages, with:\nautocmd FileType gitcommit              setlocal spell\n\nOne mapping I like a lot was contributed by Josh Branchaud, on line 223:\nautocmd FileType help nnoremap q :q\u0026lt;cr\u0026gt;\n\nThis lets us quit Vim help pages with q in normal mode (no semicolon), the same way you\ncan quit other terminal programs.\n\nHere are two more excellent mappings from lines 224 and 225:\nautocmd FileType ruby nmap \u0026lt;buffer\u0026gt; \u0026lt;leader\u0026gt;bt \u0026lt;Plug\u0026gt;BlockToggle\nautocmd BufRead *_spec.rb map \u0026lt;buffer\u0026gt; \u0026lt;leader\u0026gt;l \u0026lt;Plug\u0026gt;ExtractRspecLet\n\nThe first mapping gives us easy access to the features of\nvim-blockle, which swaps Ruby blocks\nwritten in the curly braces syntax ({}) to the do-end syntax (do end), and\nvice versa. When to use one or the other is mostly subjective, and with this\nmapping, we can rapidly compare each choice.\n\nThe second mapping calls the :ExtractRspecLet from the\nvim-weefactor plugin, swapping\nlocal variables defined in an RSpec examples for let blocks:\n# spec/application_spec.rb\n\nuser = FactoryGirl.create(:user) # =\u0026gt; :ExtractRspecLet\nlet(:user) { FactoryGirl.create(:user)\n\nAgain, this choice can be subjective, and with this mapping and the underlying\nlibrary, we get to compare each option with one command.\n\nThe last mapping in the file is a blockbuster. If you're editing an SQL file in\na Tmux session, run \u0026lt;leader\u0026gt;t from normal mode, and your file will be read\ninto the session and window of your choice:\nautocmd FileType sql nmap \u0026lt;buffer\u0026gt; \u0026lt;leader\u0026gt;t :\u0026lt;C-U\u0026gt;w \\| call Send_to_Tmux(\"\\\\i \".expand(\"%\").\"\\n\")\u0026lt;CR\u0026gt;\n\nStart a psql session, and you've got a fast way to iterate on an SQL statement from Vim. The command even writes the file for you before sending it to the window.\nConclusion\n\nHow does this apply to you? Consider writing your own Vim plugin that captures\nyour favorite settings, install Vim Hashrocket to write code the way we do, or\ninstall the Dotmatrix for this and many other settings. Not every person on our\nour team has all of these plugins on their personal machines, but the shared\ntooling is vital when we start collaborating.\n\nNo exploration of a Hashrocket Vim plugin would be complete without thanking\nTim Pope, a Rocketeer who built many of these libraries, as well as all the contributors who have\nmade them better over the years.\n\nIf you're in Chicago, stop by Vim\nChicago to talk plugins and more. Likewise, the 'Today I Learned' #vim channel contains\nhundreds of our favorite tips and tricks to leverage this classic editor.\n\nStay tuned as I continue to explore the Hashrocket Vimbundle in future posts.\n\nPhoto Credit: Barn Images, https://unsplash.com/photos/t5YUoHW6zRo. Accessed 15 April 2017.\n","summary":"Hashrocket committed to Vim early in our history, and it's been a crucial decision. When we set up a new development machine, we\ninstall the Dotmatrix, a library of\nconfigurations that includes our favorite, must-have Vim plugins. This blog focuses on Vim Hashrocket.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/411/barn-images-12223.jpg","date_published":"2017-04-20T09:00:00-04:00","data_modified":"2019-01-31T16:34:42-05:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Vim","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/best-of-til-year-one-rails","url":"https://hashrocket.com/blog/posts/best-of-til-year-one-rails","title":"Best of TIL Year One: Rails","content_html":"Here are some of the top Rails posts from [Today I Learned](https://til.hashrocket.com).\n\nMy goal with this series is to highlight some of the top posts from\r\nthe first year of [Today I Learned](https://til.hashrocket.com). Today we'll\r\nlook at Rails, our fifth-most active channel.\r\n\r\nHashrocket was one of the first Ruby on Rails consultancies, and Rails is still very\r\nimportant to our business. Many of our projects are Rails applications, and we strive to maximize\r\nthis ever-evolving framework to meet client needs. Today I Learned is itself\r\nwritten in Rails ([source](https://github.com/hashrocket/hr-til)); some of these posts came directly from working on it.\r\n\r\nHere are the top five most liked Rails posts, in order, from the first year of\r\nToday I Learned.\r\n\r\nEnjoy!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/e1036d0f13-rails-sandbox-\"\u003eRails Sandbox 🏖 (Dillon Hafer)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nWhen you are working with a complicated database structure, and find yourself needing to debug a complex or dangerous (delete) action, you might be hesitant to experiment. Keep experimenting! Don't want to setup all that data again? No worries. You can use a sandbox:\r\n\r\n```\r\n$ rails c -s\r\n```\r\n\r\n```\r\nUsage: rails console [environment] [options]\r\n  -s, --sandbox      Rollback database modifications on exit.\r\n```\r\n\r\nThe sandbox flag will keep all database changes in a database transaction when you start the rails console and automatically issue a rollback when you quit the console.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/ad62bdd157-truncate-almost-all-tables\"\u003eTruncate Almost All Tables (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nThe\r\n[`database_cleaner`](https://github.com/DatabaseCleaner/database_cleaner)\r\ngem is a handy way to make sure you have a consistent database context for\r\neach test example or suite. One `database_cleaner` strategy that can be used\r\nis the `truncation` strategy. This truncates the data from all the tables by\r\ndefault. This is not ideal for *fixed* tables that contain domain-specific\r\ndata because you end up having to do way more test setup than should be\r\nnecessary. Fortunately, specific tables can be excepted by the truncation\r\nstrategy using the `except` option.\r\n\r\nFor instance, if we have a standard set of roles for users of our\r\napplication, we can except that table from truncation with a line like the\r\nfollowing in our `rails_helper.rb` file:\r\n\r\n```ruby\r\nDatabaseCleaner.strategy = :truncation, {:except =\u0026gt; %w[roles]}\r\n```\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/53fa4e867f-activerecord-subselects\"\u003eActiveRecord subselects (Micah Woods)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nSo you want to find all the rocketeers who wrote blog posts in a date range.\r\n\r\n```ruby\r\nBlog::Post.where(published_at: 15.years.ago..4.years.ago).includes(:rocketeer).map(\u0026amp;:rocketeer)\r\n  # Blog::Post Load (0.6ms)  SELECT \"blog_posts\".* FROM \"blog_posts\"\r\n  #   WHERE (\"blog_posts\".\"published_at\" BETWEEN '2000-06-12 14:40:06.429288' AND '2011-06-12 14:40:06.429498')\r\n  # Rocketeer Load (0.7ms)  SELECT \"rocketeers\".* FROM \"rocketeers\"\r\n  #   WHERE \"rocketeers\".\"id\" IN (12, 13, 14, 16)  ORDER BY \"rocketeers\".\"name\"\r\n```\r\n\r\nBut you want to do it in one query!\r\n\r\n```ruby\r\nRocketeer.where(\r\n  id: Blog::Post.where(published_at: 15.years.ago..4.years.ago).select(:rocketeer_id)\r\n)\r\n  # Rocketeer Load (0.9ms)  SELECT \"rocketeers\".* FROM \"rocketeers\"\r\n  #   WHERE \"rocketeers\".\"id\" IN (\r\n  #     SELECT \"blog_posts\".\"rocketeer_id\" FROM \"blog_posts\"\r\n  #       WHERE (\"blog_posts\".\"published_at\" BETWEEN '2000-06-12 14:42:20.005077' AND '2011-06-12 14:42:20.005317'))  ORDER BY \"rocketeers\".\"name\"\r\n```\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/272be7efc8-interact-with-rails-via-runner\"\u003eInteract with Rails via Runner (Jake Worth)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nThe `rails runner` feature of the Ruby on Rails command line interface is pretty awesome.\r\n\r\nThe documentation states:\r\n\r\n\u003e `runner` runs Ruby code in the context of Rails non-interactively.\r\n\r\nUse it like the `ruby` command to execute Ruby code in the context of your Rails environment. Take this file:\r\n\r\n```ruby\r\n# rails_runner_in_action.rb\r\nputs Developer.count # 5\r\nputs Post.count # 40\r\nputs Channel.count # 17\r\n```\r\n\r\nAnd run it with:\r\n\r\n```sh\r\n$ rails runner rails_runner_in_action.rb\r\n5\r\n40\r\n17\r\n```\r\n\r\nIt also runs Ruby code right in the terminal, so this works (`rails r` is an alias):\r\n\r\n```sh\r\n$ rails r \"puts Developer.count\"\r\n5\r\n```\r\n\r\nhttp://guides.rubyonrails.org/command_line.html#rails-runner\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/ef629b4101-return-an-empty-active-record-collection\"\u003eReturn an Empty Active Record Collection (Micah Cooper)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nYou can use `.none`  in a scope to short circuit the query in the event you don't have all the data.\r\n\r\nImagine this query but the `project_type` on a `Project` is `nil`\r\n\r\n```ruby\r\nclass User\r\n\r\n  scope :active -\u003e { where(archived: nil }\r\n\r\n  scope :by_project, -\u003e (project) do\r\n    return none unless project.type.present?\r\n    where(project_guid: project.guid, role: project.type)\r\n  end\r\n\r\nend\r\n```\r\n\r\nJust return `none`.\r\n\r\nThe cool thing about this is it's chainable. So you can still do something like:\r\n\r\n```ruby\r\nproject = Project.new(project_type: nil)\r\n\r\nUser.by_project(project).active\r\n```\r\n\r\n### Conclusion\r\n\r\nThanks to [Dillon](https://twitter.com/dillonhafer), [Josh](https://twitter.com/jbrancha), [Micah Woods](https://twitter.com/mwoods79), and [Micah Cooper](https://twitter.com/mrmicahcooper) for these posts.\r\n\r\nToday I Learned had a spike in traffic near the beginning of the year, and\r\nthese posts are mostly from that time. But there's a lot of great Rails tips\r\nfrom earlier. See them all here:\r\n\r\nhttps://til.hashrocket.com/rails\r\n\r\nThanks for reading this series of posts, and keep learning every day.\r\n\r\n---\r\n\r\n_This blog post is part five of a series; here's part\r\n[one](https://hashrocket.com/blog/posts/best-of-til-year-one-vim),\r\n[two](https://hashrocket.com/blog/posts/best-of-til-year-one-sql),\r\n[three](https://hashrocket.com/blog/posts/best-of-til-year-one-ruby), and\r\n[four](https://hashrocket.com/blog/posts/best-of-til-year-one-command-line)._","content_text":"Here are some of the top Rails posts from Today I Learned.\n\nMy goal with this series is to highlight some of the top posts from\nthe first year of Today I Learned. Today we'll\nlook at Rails, our fifth-most active channel.\n\nHashrocket was one of the first Ruby on Rails consultancies, and Rails is still very\nimportant to our business. Many of our projects are Rails applications, and we strive to maximize\nthis ever-evolving framework to meet client needs. Today I Learned is itself\nwritten in Rails (source); some of these posts came directly from working on it.\n\nHere are the top five most liked Rails posts, in order, from the first year of\nToday I Learned.\n\nEnjoy!\n\nRails Sandbox 🏖 (Dillon Hafer)\n\nWhen you are working with a complicated database structure, and find yourself needing to debug a complex or dangerous (delete) action, you might be hesitant to experiment. Keep experimenting! Don't want to setup all that data again? No worries. You can use a sandbox:\n$ rails c -s\nUsage: rails console [environment] [options]\n  -s, --sandbox      Rollback database modifications on exit.\n\nThe sandbox flag will keep all database changes in a database transaction when you start the rails console and automatically issue a rollback when you quit the console.\n\nTruncate Almost All Tables (Josh Branchaud)\n\nThe\ndatabase_cleaner\ngem is a handy way to make sure you have a consistent database context for\neach test example or suite. One database_cleaner strategy that can be used\nis the truncation strategy. This truncates the data from all the tables by\ndefault. This is not ideal for fixed tables that contain domain-specific\ndata because you end up having to do way more test setup than should be\nnecessary. Fortunately, specific tables can be excepted by the truncation\nstrategy using the except option.\n\nFor instance, if we have a standard set of roles for users of our\napplication, we can except that table from truncation with a line like the\nfollowing in our rails_helper.rb file:\nDatabaseCleaner.strategy = :truncation, {:except =\u0026amp;gt; %w[roles]}\n\nActiveRecord subselects (Micah Woods)\n\nSo you want to find all the rocketeers who wrote blog posts in a date range.\nBlog::Post.where(published_at: 15.years.ago..4.years.ago).includes(:rocketeer).map(\u0026amp;amp;:rocketeer)\n  # Blog::Post Load (0.6ms)  SELECT \"blog_posts\".* FROM \"blog_posts\"\n  #   WHERE (\"blog_posts\".\"published_at\" BETWEEN '2000-06-12 14:40:06.429288' AND '2011-06-12 14:40:06.429498')\n  # Rocketeer Load (0.7ms)  SELECT \"rocketeers\".* FROM \"rocketeers\"\n  #   WHERE \"rocketeers\".\"id\" IN (12, 13, 14, 16)  ORDER BY \"rocketeers\".\"name\"\n\nBut you want to do it in one query!\nRocketeer.where(\n  id: Blog::Post.where(published_at: 15.years.ago..4.years.ago).select(:rocketeer_id)\n)\n  # Rocketeer Load (0.9ms)  SELECT \"rocketeers\".* FROM \"rocketeers\"\n  #   WHERE \"rocketeers\".\"id\" IN (\n  #     SELECT \"blog_posts\".\"rocketeer_id\" FROM \"blog_posts\"\n  #       WHERE (\"blog_posts\".\"published_at\" BETWEEN '2000-06-12 14:42:20.005077' AND '2011-06-12 14:42:20.005317'))  ORDER BY \"rocketeers\".\"name\"\n\nInteract with Rails via Runner (Jake Worth)\n\nThe rails runner feature of the Ruby on Rails command line interface is pretty awesome.\n\nThe documentation states:\n\n\nrunner runs Ruby code in the context of Rails non-interactively.\n\n\nUse it like the ruby command to execute Ruby code in the context of your Rails environment. Take this file:\n# rails_runner_in_action.rb\nputs Developer.count # 5\nputs Post.count # 40\nputs Channel.count # 17\n\nAnd run it with:\n$ rails runner rails_runner_in_action.rb\n5\n40\n17\n\nIt also runs Ruby code right in the terminal, so this works (rails r is an alias):\n$ rails r \"puts Developer.count\"\n5\n\nhttp://guides.rubyonrails.org/command_line.html#rails-runner\n\nReturn an Empty Active Record Collection (Micah Cooper)\n\nYou can use .none  in a scope to short circuit the query in the event you don't have all the data.\n\nImagine this query but the project_type on a Project is nil\nclass User\n\n  scope :active -\u0026gt; { where(archived: nil }\n\n  scope :by_project, -\u0026gt; (project) do\n    return none unless project.type.present?\n    where(project_guid: project.guid, role: project.type)\n  end\n\nend\n\nJust return none.\n\nThe cool thing about this is it's chainable. So you can still do something like:\nproject = Project.new(project_type: nil)\n\nUser.by_project(project).active\nConclusion\n\nThanks to Dillon, Josh, Micah Woods, and Micah Cooper for these posts.\n\nToday I Learned had a spike in traffic near the beginning of the year, and\nthese posts are mostly from that time. But there's a lot of great Rails tips\nfrom earlier. See them all here:\n\nhttps://til.hashrocket.com/rails\n\nThanks for reading this series of posts, and keep learning every day.\n\n\n\nThis blog post is part five of a series; here's part\none,\ntwo,\nthree, and\nfour.\n","summary":"Here are some of the top Rails posts from Today I Learned.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/309/best_of_til.png","date_published":"2016-07-12T09:00:00-04:00","data_modified":"2025-10-10T15:39:10-04:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Ruby","Ruby on Rails","Development","Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/best-of-til-year-one-command-line","url":"https://hashrocket.com/blog/posts/best-of-til-year-one-command-line","title":"Best of TIL Year One: Command Line","content_html":"Here are some of the top command line posts from [Today I Learned](https://til.hashrocket.com).\n\nMy goal with this series is to pause and highlight some of the top posts from\r\nthe first year of [Today I Learned](https://til.hashrocket.com). Today we'll\r\nlook at Command Line, our fourth-most active channel.\r\n\r\nAt Hashrocket, our developers pair every day using Vim and Tmux, sometimes remotely, so command-line proficiency is\r\na must. The [Dotmatrix](https://github.com/hashrocket/dotmatrix) is one of\r\nseveral projects we maintain to maximize our terminal environment.\r\n\r\nHere are the top five most liked command line posts, in order, from the first year of\r\nToday I Learned.\r\n\r\nEnjoy!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/44a4b95cdd-homebrew-is-eating-up-your-harddrive\"\u003eHomebrew is eating up your harddrive (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you've been using Homebrew on your Mac (if you have a Mac you really should) you may not be aware that every time you upgrade your brew formulas using `brew update \u0026\u0026 brew upgrade` Homebrew is leaving behind a copy of the old versions.\r\n\r\nWith package updates becoming available daily you may end up with gigabytes of space being wasted away on old package versions.\r\n\r\nTo see how much space the old versions are using run `brew cleanup -n`. When I ran that command I got:\r\n\r\n\u003e ==\u003e This operation would free approximately 9.2G of disk space.\r\n\r\nHoly cannoli!\r\n\r\nIf you feel like reclaiming that diskspace just run the command again without the `-n`: `brew cleanup`.\r\n\r\nEnjoy space! 🚀\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/78788d18bd-last-argument-of-the-last-command\"\u003eLast Argument Of The Last Command (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nYou can use `!$` as a way to reference the last argument in the last\r\ncommand. This makes for an easy shortcut when you want to switch out\r\ncommands for the same long file name. For instance, if you just ran `cat` on\r\na file to see its contents\r\n\r\n```bash\r\n$ cat /Users/jbranchaud/.ssh/config\r\n```\r\n\r\nand now you want to edit that file. You can just pass `!$` to the `vim`\r\ncommand:\r\n\r\n```bash\r\n$ vim !$\r\n```\r\n\r\nHit enter or tab to get the full command:\r\n\r\n```bash\r\n$ vim /Users/jbranchaud/.ssh/config\r\n```\r\n\r\nh/t Dorian Karter\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/1cca7dab17-rename-the-current-tmux-session\"\u003eRename The Current tmux Session (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you've created an unnamed tmux session or you no longer like the original\r\nname, you can open a prompt to change it by hitting\r\n\r\n```\r\n\u003cprefix\u003e$\r\n```\r\n\r\nReplace the existing name with the desired name and hit enter.\r\n\r\nh/t Dorian Karter\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/86bb271d15-never-leave-the-home-row-in-bash\"\u003eNever leave the home row in bash (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nTo edit a command in bash you often need to jump around in the line and revert to using the arrow keys. As a vim/emacs user this becomes a bit of a clumsy non-ergonomic movement, here are some shortcuts to help you keep your fingers on the home row. If you are an emacs user these are going to look familiar.\r\n\r\n- `ctrl-p` - previous command entered\r\n- `ctrl-n` - next command entered\r\n- `ctrl-a` - jump to BOL\r\n- `ctrl-e` - jump to EOL\r\n- `alt-b` - jump word forward\r\n- `alt-f` - jump word backwards\r\n- `alt-b` - jump character forward\r\n- `alt-f` - jump character backwards\r\n\r\nIf these shortcuts don't work try running `set -o emacs`\r\n\r\nAlternatively you can turn on vi mode in your shell by calling `set -o vi`, which you can add to your `.zshrc` or add `set editing-mode vi` to your `.inputrc`. After setting this you can enter normal mode by hitting escape and use vi motions to edit/move.\r\n\r\nYour shell just got upgraded. 💪💻\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/cf3e18f9fc-check-if-a-ruby-gem-is-installed-from-bash-script\"\u003eCheck if a #ruby gem is installed from bash script (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you are adding customizations to your zshrc, such as adding auto completion for a certain gem, you want to make sure that the gem is installed before performing any action.\r\n\r\nThe `gem list [gemname] -i` command returns a boolean representing whether a gem is installed or not.\r\n\r\n```bash\r\nif `gem list lunchy -i`; then \r\n  echo \"Lunchy gem is installed!\"; \r\n  # do some configuration here\r\nfi\r\n```\r\n\r\nIf you wish to be more granular you can check whether a specific version is installed by adding the `--version [version]` flag.\r\n\r\n```bash\r\nif `gem list lunchy -i --version 0.10.4`; then \r\n  echo \"Lunchy v0.10.4 is installed!\"; \r\n  # do some configuration here\r\nfi\r\n```\r\n\r\n### Conclusion\r\n\r\nThanks to [Dorian](https://twitter.com/dorian_escplan) and [Josh](https://twitter.com/jbrancha) for these posts.\r\n\r\nToday I Learned had a spike in traffic near the beginning of the year, and\r\nthese posts are mostly from that time. But there's a lot of great Command Line tips\r\nfrom earlier. See them all here:\r\n\r\nhttps://til.hashrocket.com/command-line\r\n\r\nKeep refining those commands, and learning every day.\r\n\r\n---\r\n\r\n_This blog post is part four of a series; here's part\r\n[one](https://hashrocket.com/blog/posts/best-of-til-year-one-vim),\r\n[two](https://hashrocket.com/blog/posts/best-of-til-year-one-sql), and\r\n[three](https://hashrocket.com/blog/posts/best-of-til-year-one-ruby). Next, we\r\nwill look at the top Rails posts from year one._","content_text":"Here are some of the top command line posts from Today I Learned.\n\nMy goal with this series is to pause and highlight some of the top posts from\nthe first year of Today I Learned. Today we'll\nlook at Command Line, our fourth-most active channel.\n\nAt Hashrocket, our developers pair every day using Vim and Tmux, sometimes remotely, so command-line proficiency is\na must. The Dotmatrix is one of\nseveral projects we maintain to maximize our terminal environment.\n\nHere are the top five most liked command line posts, in order, from the first year of\nToday I Learned.\n\nEnjoy!\n\nHomebrew is eating up your harddrive (Dorian Karter)\n\nIf you've been using Homebrew on your Mac (if you have a Mac you really should) you may not be aware that every time you upgrade your brew formulas using brew update \u0026amp;\u0026amp; brew upgrade Homebrew is leaving behind a copy of the old versions.\n\nWith package updates becoming available daily you may end up with gigabytes of space being wasted away on old package versions.\n\nTo see how much space the old versions are using run brew cleanup -n. When I ran that command I got:\n\n\n==\u0026gt; This operation would free approximately 9.2G of disk space.\n\n\nHoly cannoli!\n\nIf you feel like reclaiming that diskspace just run the command again without the -n: brew cleanup.\n\nEnjoy space! 🚀\n\nLast Argument Of The Last Command (Josh Branchaud)\n\nYou can use !$ as a way to reference the last argument in the last\ncommand. This makes for an easy shortcut when you want to switch out\ncommands for the same long file name. For instance, if you just ran cat on\na file to see its contents\n$ cat /Users/jbranchaud/.ssh/config\n\nand now you want to edit that file. You can just pass !$ to the vim\ncommand:\n$ vim !$\n\nHit enter or tab to get the full command:\n$ vim /Users/jbranchaud/.ssh/config\n\nh/t Dorian Karter\n\nRename The Current tmux Session (Josh Branchaud)\n\nIf you've created an unnamed tmux session or you no longer like the original\nname, you can open a prompt to change it by hitting\n\u0026lt;prefix\u0026gt;$\n\nReplace the existing name with the desired name and hit enter.\n\nh/t Dorian Karter\n\nNever leave the home row in bash (Dorian Karter)\n\nTo edit a command in bash you often need to jump around in the line and revert to using the arrow keys. As a vim/emacs user this becomes a bit of a clumsy non-ergonomic movement, here are some shortcuts to help you keep your fingers on the home row. If you are an emacs user these are going to look familiar.\n\n\nctrl-p - previous command entered\nctrl-n - next command entered\nctrl-a - jump to BOL\nctrl-e - jump to EOL\nalt-b - jump word forward\nalt-f - jump word backwards\nalt-b - jump character forward\nalt-f - jump character backwards\n\n\nIf these shortcuts don't work try running set -o emacs\n\nAlternatively you can turn on vi mode in your shell by calling set -o vi, which you can add to your .zshrc or add set editing-mode vi to your .inputrc. After setting this you can enter normal mode by hitting escape and use vi motions to edit/move.\n\nYour shell just got upgraded. 💪💻\n\nCheck if a #ruby gem is installed from bash script (Dorian Karter)\n\nIf you are adding customizations to your zshrc, such as adding auto completion for a certain gem, you want to make sure that the gem is installed before performing any action.\n\nThe gem list [gemname] -i command returns a boolean representing whether a gem is installed or not.\nif `gem list lunchy -i`; then \n  echo \"Lunchy gem is installed!\"; \n  # do some configuration here\nfi\n\nIf you wish to be more granular you can check whether a specific version is installed by adding the --version [version] flag.\nif `gem list lunchy -i --version 0.10.4`; then \n  echo \"Lunchy v0.10.4 is installed!\"; \n  # do some configuration here\nfi\nConclusion\n\nThanks to Dorian and Josh for these posts.\n\nToday I Learned had a spike in traffic near the beginning of the year, and\nthese posts are mostly from that time. But there's a lot of great Command Line tips\nfrom earlier. See them all here:\n\nhttps://til.hashrocket.com/command-line\n\nKeep refining those commands, and learning every day.\n\n\n\nThis blog post is part four of a series; here's part\none,\ntwo, and\nthree. Next, we\nwill look at the top Rails posts from year one.\n","summary":"Here are some of the top command line posts from Today I Learned.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/308/best_of_til.png","date_published":"2016-07-05T09:00:00-04:00","data_modified":"2016-07-05T09:10:29-04:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Development","Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/best-of-til-year-one-ruby","url":"https://hashrocket.com/blog/posts/best-of-til-year-one-ruby","title":"Best of TIL Year One: Ruby","content_html":"Here are some of the top Ruby posts from [Today I Learned](https://til.hashrocket.com).\n\nMy goal with this series is to pause and highlight some of the top posts from\r\nthe first year of [Today I Learned](https://til.hashrocket.com). Today we'll look at Ruby, our third-most active channel.\r\n\r\nHashrocket invested early in Ruby, and it remains the _lingua franca_ of our company.\r\nThough many of us enjoy hacking on JavaScript, Elixir, Go, Clojure, and other languages, Ruby is still\r\na well-worn and trusty tool. We travel to Rails Conf and Ruby Conf\r\neach year, and host our own annual Ruby conference in St. Augustine. There's a cache at Hashrocket to an elegant line of Ruby, because it's a language we all know well.\r\n\r\nHere are the top five most liked Ruby posts, in order, from the first year of Today I Learned.\r\n\r\nEnjoy!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/ae6f6b9742-ruby-string-mutability\"\u003eRuby String Mutability (Vinicius Negrisolo)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nUntil Ruby 3 we need to explicitly call the method `freeze` on literal strings, so they become immutable. And, if you have a lot of literal strings in a file, this will be very repetitive and verbose. In order to let our code cleaner there is a magic comment that can be added in the top of each file.\r\n\r\n**the magic:**\r\n\r\n```ruby\r\n# frozen_string_literal: true\r\n```\r\n\r\nAnd it is done, all literal string are frozen now :)\r\n\r\n**example:**\r\n\r\n```ruby\r\nclass Unfrozen\r\n  def foo\r\n    'bar'\r\n  end\r\nend\r\n```\r\n\r\n```ruby\r\nclass StringFrozen\r\n  def foo\r\n    'bar'.freeze\r\n  end\r\nend\r\n```\r\n\r\n```ruby\r\n# frozen_string_literal: true\r\nclass ClassFrozen\r\n  def foo\r\n    'bar'\r\n  end\r\nend\r\n```\r\n\r\nTo test that:\r\n\r\n```ruby\r\nrequire 'spec_helper'\r\n\r\ndescribe 'Ruby String Mutability' do\r\n  it 'validates string mutability' do\r\n    expect(Unfrozen.new.foo.frozen?). to be false\r\n    expect(StringFrozen.new.foo.frozen?). to be true\r\n    expect(ClassFrozen.new.foo.frozen?). to be true\r\n  end\r\nend\r\n```\r\n\r\n```shell\r\nRandomized with seed 51265\r\n.\r\n\r\nFinished in 0.00179 seconds (files took 0.45396 seconds to load)\r\n1 example, 0 failures\r\n```\r\n\r\n\\o/\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/0f1dad0572-ruby-retry-where-you-been\"\u003eRuby Retry- Where you been? (Micah Cooper)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nFor some reason, I never knew about ruby's `retry` keyword. The more you know...\r\n\r\n```ruby\r\ndef api_request\r\n  TwitterWrapper.make_request # Throws a ServiceUnavailabe(506)- Server overloaded\r\n rescue ServiceUnavailable =\u003e error\r\n    retries = retries.to_i + 1 # Increment a retry counter\r\n    retries \u003c 5 ? retry : raise(error) # run the method again until \"retries is exceeded\"\r\n    # notice the local variable \"retries\" is persisted through retries\r\nend\r\n```\r\n\r\nYou could put a sleep in there if you wanted to wait a certain amount of time before retrying.\r\n\r\nh/t Vinicius Negrisolo\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/573b9ca030-percent-notation\"\u003ePercent Notation (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nRuby has many uses for the `%` character. One of the more obscure uses is as\r\na notion for custom delimited strings. Use the percent notation with a\r\nnon-alphanumeric character to surround a string.\r\n\r\n```ruby\r\n\u0026gt; %=Jurassic Park=\r\n=\u0026gt; \"Jurassic Park\"\r\n\u0026gt; % Ghostbusters \r\n=\u0026gt; \"Ghostbusters\"\r\n```\r\n\r\nIt even works with balanced characters\r\n\r\n```ruby\r\n\u0026gt; %(The Goonies)\r\n=\u0026gt; \"The Goonies\"\r\n```\r\n\r\nThis is useful for defining a string that has both types of quotes\r\n\r\n```ruby\r\n\u0026gt; %[That'll be the \"day\"]\r\n=\u0026gt; \"That'll be the \\\"day\\\"\"\r\n```\r\n\r\nIt's also useful for creating horribly obfuscated code\r\n\r\n```ruby\r\n\u0026gt; %=what===%?what?\r\n=\u0026gt; true\r\n```\r\n\r\nh/t [Josh Davey](https://twitter.com/joshuadavey/status/615613617099046912)\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/2dab9b4db4-ruby-array-shortcuts-and-method\"\u003eRuby array shortcuts - \"\u0026:\" and \"\u0026method\" (Vinicius Negrisolo)\u003c/a\u003e\u003c/h3\u003e\r\n\r\n**Call a method on every items with `\u0026:`**\r\n\r\nSo this:\r\n\r\n```ruby\r\n[:foo, :bar].each do |item|\r\n  item.to_s\r\nend\r\n```\r\n\r\nCan be reduced to:\r\n\r\n```ruby\r\n[:foo, :bar].each(\u0026:to_s)\r\n```\r\n\r\nBut, what if you want to call a method for each item in an array, and this item should be a parameter for this method?\r\n\r\n**Call a method with every items as a parameter with `\u0026method`**\r\n\r\nSo this:\r\n\r\n```ruby\r\n[:foo, :bar].each do |item|\r\n  puts(item)\r\nend\r\n```\r\n\r\nCan be reduced to:\r\n\r\n```ruby\r\n[:foo, :bar].each(\u0026method(:puts))\r\n```\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/98b07904e2-a-high-level-view-of-rspec-tests\"\u003eA high level view of RSpec tests (Chris Erin)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nTest files in ruby/rspec can grow to gigantic soul crushing sizes, which makes it hard to really get a sense of what tests are in the file and where.  This is troublesome when trying to determine a sensible place to add a new test to the already gigantic file.\r\n\r\nTo get a better sense of the structure of the file you can combine the `dry-run` and `format` options for readable, hierarchical documentation in a small amount of time.  \r\n\r\n```sh\r\n$ rspec -fdoc --dry-run specs/my_massive_test_file_spec.rb\r\n``` \r\n\r\n### Conclusion\r\n\r\nThanks to Vinicius, Micah, Josh, and Chris for these posts.\r\n\r\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great Ruby tips from earlier. See them all here:\r\n\r\nhttps://til.hashrocket.com/ruby\r\n\r\nKeep instantiating those objects, and learning every day.\r\n\r\n---\r\n\r\n_This blog post is part three of a series; here's part [one](https://hashrocket.com/blog/posts/best-of-til-year-one-vim) and [two](https://hashrocket.com/blog/posts/best-of-til-year-one-sql). Next, we will look at the top command line posts from year one._","content_text":"Here are some of the top Ruby posts from Today I Learned.\n\nMy goal with this series is to pause and highlight some of the top posts from\nthe first year of Today I Learned. Today we'll look at Ruby, our third-most active channel.\n\nHashrocket invested early in Ruby, and it remains the lingua franca of our company.\nThough many of us enjoy hacking on JavaScript, Elixir, Go, Clojure, and other languages, Ruby is still\na well-worn and trusty tool. We travel to Rails Conf and Ruby Conf\neach year, and host our own annual Ruby conference in St. Augustine. There's a cache at Hashrocket to an elegant line of Ruby, because it's a language we all know well.\n\nHere are the top five most liked Ruby posts, in order, from the first year of Today I Learned.\n\nEnjoy!\n\nRuby String Mutability (Vinicius Negrisolo)\n\nUntil Ruby 3 we need to explicitly call the method freeze on literal strings, so they become immutable. And, if you have a lot of literal strings in a file, this will be very repetitive and verbose. In order to let our code cleaner there is a magic comment that can be added in the top of each file.\n\nthe magic:\n# frozen_string_literal: true\n\nAnd it is done, all literal string are frozen now :)\n\nexample:\nclass Unfrozen\n  def foo\n    'bar'\n  end\nend\nclass StringFrozen\n  def foo\n    'bar'.freeze\n  end\nend\n# frozen_string_literal: true\nclass ClassFrozen\n  def foo\n    'bar'\n  end\nend\n\nTo test that:\nrequire 'spec_helper'\n\ndescribe 'Ruby String Mutability' do\n  it 'validates string mutability' do\n    expect(Unfrozen.new.foo.frozen?). to be false\n    expect(StringFrozen.new.foo.frozen?). to be true\n    expect(ClassFrozen.new.foo.frozen?). to be true\n  end\nend\nRandomized with seed 51265\n.\n\nFinished in 0.00179 seconds (files took 0.45396 seconds to load)\n1 example, 0 failures\n\n\\o/\n\nRuby Retry- Where you been? (Micah Cooper)\n\nFor some reason, I never knew about ruby's retry keyword. The more you know...\ndef api_request\n  TwitterWrapper.make_request # Throws a ServiceUnavailabe(506)- Server overloaded\n rescue ServiceUnavailable =\u0026gt; error\n    retries = retries.to_i + 1 # Increment a retry counter\n    retries \u0026lt; 5 ? retry : raise(error) # run the method again until \"retries is exceeded\"\n    # notice the local variable \"retries\" is persisted through retries\nend\n\nYou could put a sleep in there if you wanted to wait a certain amount of time before retrying.\n\nh/t Vinicius Negrisolo\n\nPercent Notation (Josh Branchaud)\n\nRuby has many uses for the % character. One of the more obscure uses is as\na notion for custom delimited strings. Use the percent notation with a\nnon-alphanumeric character to surround a string.\n\u0026amp;gt; %=Jurassic Park=\n=\u0026amp;gt; \"Jurassic Park\"\n\u0026amp;gt; % Ghostbusters \n=\u0026amp;gt; \"Ghostbusters\"\n\nIt even works with balanced characters\n\u0026amp;gt; %(The Goonies)\n=\u0026amp;gt; \"The Goonies\"\n\nThis is useful for defining a string that has both types of quotes\n\u0026amp;gt; %[That'll be the \"day\"]\n=\u0026amp;gt; \"That'll be the \\\"day\\\"\"\n\nIt's also useful for creating horribly obfuscated code\n\u0026amp;gt; %=what===%?what?\n=\u0026amp;gt; true\n\nh/t Josh Davey\n\nRuby array shortcuts - \"\u0026amp;:\" and \"\u0026amp;method\" (Vinicius Negrisolo)\n\nCall a method on every items with \u0026amp;:\n\nSo this:\n[:foo, :bar].each do |item|\n  item.to_s\nend\n\nCan be reduced to:\n[:foo, :bar].each(\u0026amp;:to_s)\n\nBut, what if you want to call a method for each item in an array, and this item should be a parameter for this method?\n\nCall a method with every items as a parameter with \u0026amp;method\n\nSo this:\n[:foo, :bar].each do |item|\n  puts(item)\nend\n\nCan be reduced to:\n[:foo, :bar].each(\u0026amp;method(:puts))\n\nA high level view of RSpec tests (Chris Erin)\n\nTest files in ruby/rspec can grow to gigantic soul crushing sizes, which makes it hard to really get a sense of what tests are in the file and where.  This is troublesome when trying to determine a sensible place to add a new test to the already gigantic file.\n\nTo get a better sense of the structure of the file you can combine the dry-run and format options for readable, hierarchical documentation in a small amount of time.  \n$ rspec -fdoc --dry-run specs/my_massive_test_file_spec.rb\nConclusion\n\nThanks to Vinicius, Micah, Josh, and Chris for these posts.\n\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great Ruby tips from earlier. See them all here:\n\nhttps://til.hashrocket.com/ruby\n\nKeep instantiating those objects, and learning every day.\n\n\n\nThis blog post is part three of a series; here's part one and two. Next, we will look at the top command line posts from year one.\n","summary":"Here are some of the top Ruby posts from Today I Learned.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/306/best_of_til.png","date_published":"2016-06-28T09:00:00-04:00","data_modified":"2016-06-28T09:11:54-04:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Development","Today I Learned","Hashrocket Projects","Ruby"]},{"id":"https://hashrocket.com/blog/posts/best-of-til-year-one-sql","url":"https://hashrocket.com/blog/posts/best-of-til-year-one-sql","title":"Best of TIL Year One: SQL","content_html":"Here are some of the top SQL posts from [Today I Learned](https://til.hashrocket.com).\n\nMy goal with this series is to pause and highlight some of the top posts from\r\nthe first year of [Today I Learned](https://til.hashrocket.com). Today we'll look at SQL, our second-most active channel.\r\n\r\nDatabases matter to Hashrocket. 'Your database will be\r\nmulti-tenant' is a common axiom. We feel that a\r\nrobust database, with precise constraints, capable of standing alone \r\nfrom any framework, is crucial to the long-term success of a project.\r\nSQL mastery is a badge of honor here.\r\n\r\nHere are the top five most liked SQL posts, in order, from the first year of Today I Learned.\r\n\r\nEnjoy!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/75fa841555-watch-for-database-changes-on-postgresql\"\u003eWatch for database changes on #PostgreSQL (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you are trying to debug multi-threaded environments or a really fast job queue you might need to \"watch\" a table for changes.\r\n\r\nIn `psql` use the `\\watch` command like so:\r\n\r\n```sql\r\n\\watch 1 \"select * from job_queue\";\r\n```\r\n\r\nThis will run the query every 1 second (you can change the second argument if you need it slower) and display the result as well as past results.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/cdb313f4f8-quickly-see-the-contents-of-a-table-in-postgresql\"\u003eQuickly see the contents of a table in #PostgreSQL (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nNext time you want to see the contents of a table in Postgres' CLI don't type the whole:\r\n\r\n```sql\r\nselect * from name_of_table;\r\n```\r\n\r\nJust use:\r\n\r\n```sql\r\ntable name_of_table;\r\n```\r\n\r\nh/t Josh Branchaud\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/9c43748955-be-aware-postgres-rounds\"\u003eBe aware! Postgres rounds. (Chris Erin)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nYesterday, my pair and I created a test that calculated a value and compared that to the value of a calculation in the code we were testing.  This worked out great except for one hitch, we were asserting about the derived value after it had been inserted into the database.  What we didn't count on is that Postgres rounds.  Check this out:\r\n\r\n```sql\r\ncreate table money (amount numeric(4, 2));\r\ninsert into money (amount) values (10.342) returning amount;\r\n amount\r\n--------\r\n  10.34\r\n\r\ninsert into money (amount) values (10.347) returning amount;\r\n amount\r\n--------\r\n  10.35\r\n```\r\n\r\nPostgres rounds!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/9457e5c358-using-expressions-in-indexes-with-postgresql\"\u003eUsing Expressions In Indexes With PostgreSQL (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nThough we usually see column names by themselves when defining an index, it\r\nis also possible to create an index with an expression.\r\n\r\nLet's say I have a `users` table with an `email` column. Then I may end up\r\ncreating an index like this\r\n\r\n```sql\r\ncreate index email_idx on users (email);\r\n```\r\n\r\nIf I always perform queries on the `email` column with the `lower()`\r\nfunction, like this\r\n\r\n```sql\r\nselect * from users where lower(email) = lower('some@email.com');\r\n```\r\n\r\nthen I will want to also create an index with that full expression --\r\n`lower(email)`\r\n\r\nI can do this with a statement like the following\r\n\r\n```sql\r\ncreate index lower_email_idx on users (lower(email));\r\n```\r\n\r\nWithout an index that uses the full `lower(email)` expression, `select`\r\nstatements like the one above will be forced to do full sequential scans\r\ninstead of indexed scans.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/4c6456b1d0-types-and-type-casting-in-postgresql\"\u003eTypes and type casting in #PostgreSQL (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nTo see the type of column or any entity in PostgreSQL use `pg_typeof`. Here's an example:\r\n\r\n```sql\r\nselect pg_typeof(array['thing']);\r\n\r\n-- OUTPUT:\r\n\r\n-- pg_typeof\r\n-- ---------\r\n-- text[]\r\n```\r\n\r\nTo cast to another type use the `::` operator:\r\n\r\n```sql\r\nselect pg_typeof(array['thing']::varchar[]);\r\n\r\n-- OUTPUT:\r\n\r\n--      pg_typeof\r\n-- -------------------\r\n-- character varying[]\r\n```\r\n\r\nh/t Josh Branchaud\r\n\r\n### Conclusion\r\n\r\nThanks to Dorian, Chris, and Josh for those posts.\r\n\r\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great SQL tips from earlier. See them all here:\r\n\r\nhttps://til.hashrocket.com/sql\r\n\r\nWant more SQL tips from Hashrocket? Check out our newest production, [PG Casts](https://www.pgcasts.com/).\r\n\r\nKeep committing that data, and learning every day.\r\n\r\n---\r\n\r\n_This blog post is part two of a series; here's part [one](https://hashrocket.com/blog/posts/best-of-til-year-one-vim). Next, we will look at the top Ruby posts from year one._","content_text":"Here are some of the top SQL posts from Today I Learned.\n\nMy goal with this series is to pause and highlight some of the top posts from\nthe first year of Today I Learned. Today we'll look at SQL, our second-most active channel.\n\nDatabases matter to Hashrocket. 'Your database will be\nmulti-tenant' is a common axiom. We feel that a\nrobust database, with precise constraints, capable of standing alone \nfrom any framework, is crucial to the long-term success of a project.\nSQL mastery is a badge of honor here.\n\nHere are the top five most liked SQL posts, in order, from the first year of Today I Learned.\n\nEnjoy!\n\nWatch for database changes on #PostgreSQL (Dorian Karter)\n\nIf you are trying to debug multi-threaded environments or a really fast job queue you might need to \"watch\" a table for changes.\n\nIn psql use the \\watch command like so:\n\\watch 1 \"select * from job_queue\";\n\nThis will run the query every 1 second (you can change the second argument if you need it slower) and display the result as well as past results.\n\nQuickly see the contents of a table in #PostgreSQL (Dorian Karter)\n\nNext time you want to see the contents of a table in Postgres' CLI don't type the whole:\nselect * from name_of_table;\n\nJust use:\ntable name_of_table;\n\nh/t Josh Branchaud\n\nBe aware! Postgres rounds. (Chris Erin)\n\nYesterday, my pair and I created a test that calculated a value and compared that to the value of a calculation in the code we were testing.  This worked out great except for one hitch, we were asserting about the derived value after it had been inserted into the database.  What we didn't count on is that Postgres rounds.  Check this out:\ncreate table money (amount numeric(4, 2));\ninsert into money (amount) values (10.342) returning amount;\n amount\n--------\n  10.34\n\ninsert into money (amount) values (10.347) returning amount;\n amount\n--------\n  10.35\n\nPostgres rounds!\n\nUsing Expressions In Indexes With PostgreSQL (Josh Branchaud)\n\nThough we usually see column names by themselves when defining an index, it\nis also possible to create an index with an expression.\n\nLet's say I have a users table with an email column. Then I may end up\ncreating an index like this\ncreate index email_idx on users (email);\n\nIf I always perform queries on the email column with the lower()\nfunction, like this\nselect * from users where lower(email) = lower('some@email.com');\n\nthen I will want to also create an index with that full expression --\nlower(email)\n\nI can do this with a statement like the following\ncreate index lower_email_idx on users (lower(email));\n\nWithout an index that uses the full lower(email) expression, select\nstatements like the one above will be forced to do full sequential scans\ninstead of indexed scans.\n\nTypes and type casting in #PostgreSQL (Dorian Karter)\n\nTo see the type of column or any entity in PostgreSQL use pg_typeof. Here's an example:\nselect pg_typeof(array['thing']);\n\n-- OUTPUT:\n\n-- pg_typeof\n-- ---------\n-- text[]\n\nTo cast to another type use the :: operator:\nselect pg_typeof(array['thing']::varchar[]);\n\n-- OUTPUT:\n\n--      pg_typeof\n-- -------------------\n-- character varying[]\n\nh/t Josh Branchaud\nConclusion\n\nThanks to Dorian, Chris, and Josh for those posts.\n\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great SQL tips from earlier. See them all here:\n\nhttps://til.hashrocket.com/sql\n\nWant more SQL tips from Hashrocket? Check out our newest production, PG Casts.\n\nKeep committing that data, and learning every day.\n\n\n\nThis blog post is part two of a series; here's part one. Next, we will look at the top Ruby posts from year one.\n","summary":"Here are some of the top SQL posts from Today I Learned.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/305/best_of_til.png","date_published":"2016-06-21T09:00:00-04:00","data_modified":"2016-06-21T09:11:47-04:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Development","Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/introducing-pgcasts","url":"https://hashrocket.com/blog/posts/introducing-pgcasts","title":"Introducing PG Casts","content_html":"We are excited to share our latest project, [PG Casts](https://www.pgcasts.com), with the world.\n\nAt Hashrocket, we love PostgreSQL.\r\n\r\nPostgres is the relational database of choice for Hashrocket projects. We like it because it's free, well supported, and very friendly to developers. Postgres offers advanced features, outstanding data integrity guarantees, and competitive performance.\r\n\r\nHashrocket has invested in this tool and all of our developers seek mastery of it. We love nothing more than helping our clients take full advantage of Postgres.\r\n\r\nIn order to share our Postgres expertise with everyone else, we are introducing [PG Casts](https://www.pgcasts.com).\r\n\r\nPG Casts are short, free weekly screencasts covering beginner to advanced level tips and tricks for getting the most out of a Postgres database.\r\n\r\nThis project is a collaboration between Rocketeers across the company. Look for new screencast announcements on Twitter ([@postgresqlcasts](https://twitter.com/postgresqlcasts)).\r\n\r\nMay your data be valid, and your queries performant.\r\n\r\n\u003clink href=\"//cdn-images.mailchimp.com/embedcode/classic-10_7.css\" rel=\"stylesheet\" type=\"text/css\"\u003e\r\n\u003cdiv id=\"mc_embed_signup\" style=\"background: #d7f2f0; max-width: 400px; padding: 10px 20px;\"\u003e\r\n\u003cform action=\"//hashrocket.us9.list-manage.com/subscribe/post?u=4583afaf45051a63fac08d435\u0026amp;id=ac338d7c2a\" method=\"post\" id=\"mc-embedded-subscribe-form\" name=\"mc-embedded-subscribe-form\" class=\"validate\" target=\"_blank\" style=\"padding: 0 0 10px 0;\" novalidate\u003e\r\n    \u003cdiv id=\"mc_embed_signup_scroll\"\u003e\r\n\t\u003ch3\u003eStay Up-to-date with PG Casts News!\u003c/h3\u003e\r\n\u003cdiv class=\"mc-field-group\" style=\"width: auto;\"\u003e\r\n\t\u003clabel for=\"mce-EMAIL\"\u003eEmail Address \u003c/label\u003e\r\n\t\u003cinput type=\"email\" value=\"\" name=\"EMAIL\" class=\"required email\" id=\"mce-EMAIL\"\u003e\r\n\u003c/div\u003e\r\n\t\u003cdiv id=\"mce-responses\" class=\"clear\"\u003e\r\n\t\t\u003cdiv class=\"response\" id=\"mce-error-response\" style=\"display:none\"\u003e\u003c/div\u003e\r\n\t\t\u003cdiv class=\"response\" id=\"mce-success-response\" style=\"display:none\"\u003e\u003c/div\u003e\r\n\t\u003c/div\u003e\r\n\u003cdiv style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"\u003e\u003cinput type=\"text\" name=\"b_4583afaf45051a63fac08d435_ac338d7c2a\" tabindex=\"-1\" value=\"\"\u003e\u003c/div\u003e\r\n\u003cdiv class=\"clear\"\u003e\u003cinput type=\"submit\" value=\"Subscribe\" name=\"subscribe\" id=\"mc-embedded-subscribe\" class=\"button\" style=\"border-radius: 0; background: #b31b1f; color: #fff;\"\u003e\u003c/div\u003e\r\n    \u003c/div\u003e\r\n\u003c/form\u003e\r\n\u003c/div\u003e","content_text":"We are excited to share our latest project, PG Casts, with the world.\n\nAt Hashrocket, we love PostgreSQL.\n\nPostgres is the relational database of choice for Hashrocket projects. We like it because it's free, well supported, and very friendly to developers. Postgres offers advanced features, outstanding data integrity guarantees, and competitive performance.\n\nHashrocket has invested in this tool and all of our developers seek mastery of it. We love nothing more than helping our clients take full advantage of Postgres.\n\nIn order to share our Postgres expertise with everyone else, we are introducing PG Casts.\n\nPG Casts are short, free weekly screencasts covering beginner to advanced level tips and tricks for getting the most out of a Postgres database.\n\nThis project is a collaboration between Rocketeers across the company. Look for new screencast announcements on Twitter (@postgresqlcasts).\n\nMay your data be valid, and your queries performant.\n\n\n\n\n    \n    Stay Up-to-date with PG Casts News!\n\n    Email Address \n    \n\n    \n        \n        \n    \n\n\n    \n\n\n","summary":"We are excited to share our latest project, PG Casts, with the world.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/300/pg_casts.png","date_published":"2016-06-16T09:00:00-04:00","data_modified":"2016-06-16T09:12:00-04:00","author":{"name":"Josh Branchaud","url":"https://hashrocket.com/team/josh-branchaud","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/88/josh-branchaud.jpg"},"tags":["Company News","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/best-of-til-year-one-vim","url":"https://hashrocket.com/blog/posts/best-of-til-year-one-vim","title":"Best of TIL Year One: Vim","content_html":"Here are some of the top Vim posts from [Today I Learned](https://til.hashrocket.com).\n\n[Today I Learned](https://til.hashrocket.com) is now over a year old.\r\n\r\nThe participation from my coworkers has been inspiring, rocketing our posts\r\ncount to over 750. The enthusiasm from fans of the\r\nsite has been encouraging, on Twitter, Hacker News, and elsewhere. We\r\n[open-sourced](https://github.com/hashrocket/hr-til) the codebase earlier this\r\nyear and have gotten issues and pull requests, as well as several clones in\r\nproduction. It's been awesome.\r\n\r\nTIL content is like a river; if you haven't posted today, your content gets lost\r\nin the stream. That's why I'd like to pause and highlight some of the\r\ntop posts from the first year of Today I Learned.\r\n\r\nBeyond a chance to reflect, I hope we can all benefit from the hard-won epiphanies of Rocketeers\r\nat work. Leverage the head-banging of others!\r\n\r\nWe'll start with Vim, our first and most active channel. Below are the top five\r\nmost liked Vim posts, in order, from the first year of Today I Learned.\r\n\r\nEnjoy!\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/e8915e62c0-highlight-markdown-fenced-code-syntax-in-vim\"\u003eHighlight #Markdown Fenced Code Syntax in #Vim (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nUp until now I was editing all my blog posts in Atom for lack of markdown fenced code block highlighting in Vim. Atom supported it out of the box. As it turns out Vim can do that too, out of the box!\r\n\r\nIf you are running a recent version of Vim (mine at time of writing 7.4.9910) you can setup highlighting for fenced code blocks in markdown.\r\n\r\nOpen your .vimrc and add the following line:\r\n\r\n```viml\r\nlet g:markdown_fenced_languages = ['html', 'vim', 'ruby', 'python', 'bash=sh']\r\n```\r\n\r\nYou can customize it to your liking and add more languages. \r\n\r\n\u0026gt; Note: Not all languages are supported but you can try and see if they work. To see a list of languages you have installed on Mac (with Vim installed by Homebrew) run `ls -l /usr/local/Cellar/vim/7.4.1190/share/vim/vim74/syntax`\r\n\r\n![screenshot](https://i.imgur.com/Kk9NROw.png)\r\n\r\nThis is a game changer.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/5b333d7630-vim-change-case-of-words\"\u003eVim Change Case of Words (Vinicius Negrisolo)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you want to switch the case in Vim:\r\n\r\n`gu` =\u0026gt; lowercase\r\n\r\n`gU` =\u0026gt; uppercase\r\n\r\n`g~` =\u0026gt; toogle case\r\n\r\nYou can also combine with Vim motions like:\r\n\r\n`g~ip` =\u0026gt; toogle case for the current paragraph.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/78fe826107-browse-and-repeat-vim-commands\"\u003eBrowse and repeat Vim commands (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nIf you typed a command in Vim's command line and want to repeat it you can open the command-line window and browse through past commands. There are two ways two do that:\r\n\r\n1. From Normal mode type `q:`\r\n2. From the command line after typing a colon press `CTRL-f`\r\n\r\nIn the command window you can browse up and down with HJKL and hit `return` to re-run the command.\r\n\r\n\u003ch3\u003e\u003ca href=\"https://til.hashrocket.com/posts/624b01ada0-delete-to-the-end-of-the-line\"\u003eDelete to the End of the Line (Josh Branchaud)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nThere are a number of ways to delete from the cursor position to the end of\r\nthe line. Generally when I am doing this, I want delete to the end of the\r\nline and then start typing something different. Perhaps the best way to do\r\nthis is by hitting `C`. It deletes to the end of the line and then leaves\r\nyou in insert mode. This also makes for easier repetition with the dot\r\ncommand.\r\n\r\nThis is synonymous with hitting `c$`.\r\n\r\nSee `:h C` for more details.\r\n\r\nh/t Dorian Karter\r\n\r\n\u003ch3\u003e\u003ca href=\"\r\nhttps://til.hashrocket.com/posts/ebddcf17b9-switch-direction-of-selection-in-vim\"\u003eVSwitch Direction of Selection in Vim (Dorian Karter)\u003c/a\u003e\u003c/h3\u003e\r\n\r\nSwitch the free end of the cursor in Vim's VISUAL MODE.\r\n\r\nSimply press `o` while selecting and the free end will go to the beginning of your selection.\r\n\r\n![screenshot](https://i.imgur.com/KmuuvVU.gif)\r\n\r\n### Conclusion\r\n\r\nThanks to Josh, Dorian, and Vinicius for those posts.\r\n\r\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great Vim tips from earlier. See them all here:\r\n\r\nhttps://til.hashrocket.com/vim\r\n\r\nKeep composing those commands, and learning every day.\r\n\r\n---\r\n\r\n_This post is part of a series. Stay tuned for my next post, when we will look at the top SQL posts from year one._","content_text":"Here are some of the top Vim posts from Today I Learned.\n\nToday I Learned is now over a year old.\n\nThe participation from my coworkers has been inspiring, rocketing our posts\ncount to over 750. The enthusiasm from fans of the\nsite has been encouraging, on Twitter, Hacker News, and elsewhere. We\nopen-sourced the codebase earlier this\nyear and have gotten issues and pull requests, as well as several clones in\nproduction. It's been awesome.\n\nTIL content is like a river; if you haven't posted today, your content gets lost\nin the stream. That's why I'd like to pause and highlight some of the\ntop posts from the first year of Today I Learned.\n\nBeyond a chance to reflect, I hope we can all benefit from the hard-won epiphanies of Rocketeers\nat work. Leverage the head-banging of others!\n\nWe'll start with Vim, our first and most active channel. Below are the top five\nmost liked Vim posts, in order, from the first year of Today I Learned.\n\nEnjoy!\n\nHighlight #Markdown Fenced Code Syntax in #Vim (Dorian Karter)\n\nUp until now I was editing all my blog posts in Atom for lack of markdown fenced code block highlighting in Vim. Atom supported it out of the box. As it turns out Vim can do that too, out of the box!\n\nIf you are running a recent version of Vim (mine at time of writing 7.4.9910) you can setup highlighting for fenced code blocks in markdown.\n\nOpen your .vimrc and add the following line:\nlet g:markdown_fenced_languages = ['html', 'vim', 'ruby', 'python', 'bash=sh']\n\nYou can customize it to your liking and add more languages. \n\n\u0026gt; Note: Not all languages are supported but you can try and see if they work. To see a list of languages you have installed on Mac (with Vim installed by Homebrew) run ls -l /usr/local/Cellar/vim/7.4.1190/share/vim/vim74/syntax\n\n\n\nThis is a game changer.\n\nVim Change Case of Words (Vinicius Negrisolo)\n\nIf you want to switch the case in Vim:\n\ngu =\u0026gt; lowercase\n\ngU =\u0026gt; uppercase\n\ng~ =\u0026gt; toogle case\n\nYou can also combine with Vim motions like:\n\ng~ip =\u0026gt; toogle case for the current paragraph.\n\nBrowse and repeat Vim commands (Dorian Karter)\n\nIf you typed a command in Vim's command line and want to repeat it you can open the command-line window and browse through past commands. There are two ways two do that:\n\n\nFrom Normal mode type q:\nFrom the command line after typing a colon press CTRL-f\n\n\nIn the command window you can browse up and down with HJKL and hit return to re-run the command.\n\nDelete to the End of the Line (Josh Branchaud)\n\nThere are a number of ways to delete from the cursor position to the end of\nthe line. Generally when I am doing this, I want delete to the end of the\nline and then start typing something different. Perhaps the best way to do\nthis is by hitting C. It deletes to the end of the line and then leaves\nyou in insert mode. This also makes for easier repetition with the dot\ncommand.\n\nThis is synonymous with hitting c$.\n\nSee :h C for more details.\n\nh/t Dorian Karter\n\nVSwitch Direction of Selection in Vim (Dorian Karter)\n\nSwitch the free end of the cursor in Vim's VISUAL MODE.\n\nSimply press o while selecting and the free end will go to the beginning of your selection.\n\n\nConclusion\n\nThanks to Josh, Dorian, and Vinicius for those posts.\n\nToday I Learned had a spike in traffic near the beginning of the year, and these posts are mostly from that time. But there's a lot of great Vim tips from earlier. See them all here:\n\nhttps://til.hashrocket.com/vim\n\nKeep composing those commands, and learning every day.\n\n\n\nThis post is part of a series. Stay tuned for my next post, when we will look at the top SQL posts from year one.\n","summary":"Here are some of the top Vim posts from Today I Learned.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/301/best_of_til.png","date_published":"2016-06-14T09:00:00-04:00","data_modified":"2016-06-14T09:11:23-04:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Development","Today I Learned","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/open-sourcing-today-i-learned","url":"https://hashrocket.com/blog/posts/open-sourcing-today-i-learned","title":"Open-Sourcing Today I Learned","content_html":"[Today I Learned](https://til.hashrocket.com/) is an [open-source](https://github.com/hashrocket/hr-til) project.\n\nBefore we [introduced Today I Learned](https://hashrocket.com/blog/posts/introducing-today-i-learned), it was a small Rails application with a handful of posts. Few people within the company had even seen it.\r\n\r\nHere is a screenshot of the site, pre-Hashrocket makeover:\r\n\r\n![Original TIL](https://s3.amazonaws.com/hashrocket-blog-production/til-original-small.png)\r\n\r\nToday, this application features over 500 posts from Rocketeers across the company. We have written about Vim, design, Rails, Ruby, testing, Bash, Git, HTML/CSS, JavaScript, Clojure, SQL, mobile, DevOps, Go, Elixir, and Ember.js. It's been awesome watching this project grow. Learning and communicating every day is a part of the Hashrocket culture, and this site helps us do that.\r\n\r\nWe've decided to open-source the codebase. In this post, we'll cover the rationale behind this decision, as well as the steps we took to prepare. I hope it helps people who are considering open-sourcing their own work.\r\n\r\n### Rationale\r\n\r\nOpen-sourcing a private project is a decision that deserves some serious thought. We've gotten a lot of requests to publish this code, so it was on our mind from the beginning. The application has even been impressively reverse-engineered in the meantime.\r\n\r\nThe idea was always intriguing because open-source is a core idea at Hashrocket. Our tools are mostly open-source, and we try to give back to that community.\r\n\r\nA second argument was that some of the features of TIL are pretty nice— it is well-designed, includes Slack and Twitter integration, has an RSS feed, and features a very simple, useful post creation page. We wanted to share the implementation of those features.\r\n\r\nThat somebody else might contribute, including aspiring Rocketeers and junior developers trying to get into open source, won the day. If somebody used this repo as inspiration to build something new, that would be awesome. If that's your intention, fire away!\r\n\r\n### Step 1: Create Pivotal Chore\r\n\r\nBecause we used [Pivotal Tracker](https://www.pivotaltracker.com) to build this site, building a Pivotal chore to track the progress toward public release was our first step.\r\n\r\nHere is our TIL Pivotal project:\r\n\r\nhttps://www.pivotaltracker.com/n/projects/1299990\r\n\r\nHaving something to attach commits to increases transparency. By adding `#[\u003cGit SHA\u003e]` to each commit message, combined with a Github integration hook, all our progress could be tracked in the Pivotal story.\r\n\r\n### Step 2: Generalize Documentation\r\n\r\nThe TIL README was targeted at Rocketeers; generalizing it included:\r\n\r\n* Adding generalized setup instructions and language\r\n* Moving as many Hashrocket-specific variables into environmental variables as possible\r\n* Adding contributing guidelines\r\n* Adding a license\r\n* Adding a changelog\r\n* Tagging v1.0.0 via [Semantic Versioning](http://semver.org/)\r\n\r\n### Step 3: Cross Link\r\n\r\n*Synergy Alert!* We wanted people to be able to find the repository from the site, so we added a link in the footer. We wanted people to be able to find the site from the repository, so we added a link in the Github repo.\r\n\r\n### Step 4: Scan the Repo\r\n\r\nAs a security precaution, we did a general audit of the site, upgraded to the latest versions of Rails and Ruby, and ran [Brakeman](http://brakemanscanner.org/) against it.\r\n\r\nWe also scanned the code for usernames, passwords, and API keys, removing a few files that were no longer relevant. This is pretty simple if you think about security from the first commit. If you do encounter a file in your repo you shouldn't have checked in, change your passwords and keys immediately, then follow this guide:\r\n\r\n[Github Help - Remove Sensitive Data](https://help.github.com/articles/remove-sensitive-data/)\r\n\r\n### Step 5: Add Metrics\r\n\r\nAn open-source project should have transparent metrics, so we added Circle CI, SimpleCov, and Code Climate to help evaluate our builds.\r\n\r\n### Step 6: Release\r\n\r\nYou are here. After completing all the other steps, we tagged the last commit and clicked 'Make this repository public' on the Github repo's settings page. \r\n\r\n### Conclusion\r\n\r\nToday we covered why we open-sourced TIL and the steps we took to get there.\r\n\r\nThank you to everybody who helped build this application and its content. Thank you to our readers and retweeters. I hope people find the code interesting, consider building their own TIL or contributing to ours, and continue learning and communicating every day.","content_text":"Today I Learned is an open-source project.\n\nBefore we introduced Today I Learned, it was a small Rails application with a handful of posts. Few people within the company had even seen it.\n\nHere is a screenshot of the site, pre-Hashrocket makeover:\n\n\n\nToday, this application features over 500 posts from Rocketeers across the company. We have written about Vim, design, Rails, Ruby, testing, Bash, Git, HTML/CSS, JavaScript, Clojure, SQL, mobile, DevOps, Go, Elixir, and Ember.js. It's been awesome watching this project grow. Learning and communicating every day is a part of the Hashrocket culture, and this site helps us do that.\n\nWe've decided to open-source the codebase. In this post, we'll cover the rationale behind this decision, as well as the steps we took to prepare. I hope it helps people who are considering open-sourcing their own work.\nRationale\n\nOpen-sourcing a private project is a decision that deserves some serious thought. We've gotten a lot of requests to publish this code, so it was on our mind from the beginning. The application has even been impressively reverse-engineered in the meantime.\n\nThe idea was always intriguing because open-source is a core idea at Hashrocket. Our tools are mostly open-source, and we try to give back to that community.\n\nA second argument was that some of the features of TIL are pretty nice— it is well-designed, includes Slack and Twitter integration, has an RSS feed, and features a very simple, useful post creation page. We wanted to share the implementation of those features.\n\nThat somebody else might contribute, including aspiring Rocketeers and junior developers trying to get into open source, won the day. If somebody used this repo as inspiration to build something new, that would be awesome. If that's your intention, fire away!\nStep 1: Create Pivotal Chore\n\nBecause we used Pivotal Tracker to build this site, building a Pivotal chore to track the progress toward public release was our first step.\n\nHere is our TIL Pivotal project:\n\nhttps://www.pivotaltracker.com/n/projects/1299990\n\nHaving something to attach commits to increases transparency. By adding #[\u0026lt;Git SHA\u0026gt;] to each commit message, combined with a Github integration hook, all our progress could be tracked in the Pivotal story.\nStep 2: Generalize Documentation\n\nThe TIL README was targeted at Rocketeers; generalizing it included:\n\n\nAdding generalized setup instructions and language\nMoving as many Hashrocket-specific variables into environmental variables as possible\nAdding contributing guidelines\nAdding a license\nAdding a changelog\nTagging v1.0.0 via Semantic Versioning\n\nStep 3: Cross Link\n\nSynergy Alert! We wanted people to be able to find the repository from the site, so we added a link in the footer. We wanted people to be able to find the site from the repository, so we added a link in the Github repo.\nStep 4: Scan the Repo\n\nAs a security precaution, we did a general audit of the site, upgraded to the latest versions of Rails and Ruby, and ran Brakeman against it.\n\nWe also scanned the code for usernames, passwords, and API keys, removing a few files that were no longer relevant. This is pretty simple if you think about security from the first commit. If you do encounter a file in your repo you shouldn't have checked in, change your passwords and keys immediately, then follow this guide:\n\nGithub Help - Remove Sensitive Data\nStep 5: Add Metrics\n\nAn open-source project should have transparent metrics, so we added Circle CI, SimpleCov, and Code Climate to help evaluate our builds.\nStep 6: Release\n\nYou are here. After completing all the other steps, we tagged the last commit and clicked 'Make this repository public' on the Github repo's settings page. \nConclusion\n\nToday we covered why we open-sourced TIL and the steps we took to get there.\n\nThank you to everybody who helped build this application and its content. Thank you to our readers and retweeters. I hope people find the code interesting, consider building their own TIL or contributing to ours, and continue learning and communicating every day.\n","summary":"Today I Learned is an open-source project.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/286/brain.jpg","date_published":"2016-02-18T09:00:00-05:00","data_modified":"2020-02-04T10:40:54-05:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/introducing-metabot","url":"https://hashrocket.com/blog/posts/introducing-metabot","title":"Introducing Metabot","content_html":"We made a robot.\n\nOur foray into chatbots began with Steambot. Rocketeer Josh Davey wrote a [Markov Chain](https://en.wikipedia.org/wiki/Markov_chain) text generator in Clojure, then trained it on some Kafka, Russell, Aristotle, Nietzsche, and a special ingredient: *Steam, Its Generation and Use* by Babcock \u0026 Wilcox Company (35th edition, copyright 1919).\r\n\r\nHe named his program Steambot and configured it as an outgoing webhook in [Slack](https://slack.com). This was Steambot's first message, triggered with the keyword 'steambot':\r\n\r\n\u003e'The Mean man will be vexed, but only moderately and as their age changes so likewise do their pleasures.' -Steambot (November 6, 2014)\r\n\r\nWe pinged Steambot for a few days, asking it Turing Test-style questions like 'Steambot, what is love?'. Steambot responded: \r\n\r\n\u003e'It is the test of a K. W. steam engine turbine unit, Mr. H. G. Stott and Mr. R. G. S.' -Steambot (December 18, 2014)\r\n\r\nPretty soon there was so much traffic that we needed a dedicated Slack channel just for these inane conversations. The *#steamroom* was born.\r\n\r\nSoon there were other bots, written by Rocketeers across the company. We made Madbot, a robot that returns slightly wrong proverbs such as: 'When the going gets loud, the shaky get going.' We made Artbot, a robot who draws you an abstract picture. We made Fightbot, a robot who creates hypothetical battle matchups like this:\r\n\r\n\u003e'A hipster, can turn to steel, has a hostage ​*VS*​ an evil doll, afraid of nachos, hands glued to hips' -Fightbot (December 18, 2015)\r\n\r\nHalobot, Knightbot, Bardbot, and more. Within a few months we had created over a dozen outgoing webhooks, pinging Clojure, Go, JavaScript, and Ruby web apps.\r\n\r\nLike any good sitcom, a spin-off was inevitable. Wouldn't it be cool, we thought, to build a web app that made it easy and fun to create chat bots? One meta-bot to rule them all.\r\n\r\nWe are proud to introduce [Metabot](http://metabot.hashrocket.com), a new side project from Hashrocket.\r\n\r\n### How It Works\r\n\r\nMetabot makes it easy to create your own bot. Simply click 'Make a bot', choose between the two bot types we've built (Markov Bot or Substitution Bot), feed your bots any text files you choose, and we'll provide you with an endpoint you can easily integrate into Slack.\r\n\r\nSoon your chat log will be alive with a fun, randomly coherent robot that you created. There's no limit to the personality you can give your bot, or the amount of bots you can create.\r\n\r\n### Technology\r\n\r\nTechnically, Metabot was a chance for us to showcase our process and hone competency in new technologies.\r\n\r\nThe backend is written in Go with a PostgreSQL database. We saw this as an opportunity to build a small code base using solid design patterns such as the [Respository Pattern](https://msdn.microsoft.com/en-us/library/ff649690.aspx) and a custom responsive caching system.\r\n\r\nThe Markov and Substitution algorithms are our own and were refined over months of dogfooding.\r\n\r\nThe frontend features a Middleman site generator and was written in React.js. It includes some cool CSS tricks that add personality to the robot.\r\n\r\nOn the devops side, Metabot features a rapid deployment with Nginx using [Mina](http://nadarei.co/mina) and a custom database backup.\r\n\r\nLook for more detail about the technology in forthcoming blog posts. In the future we plan to add more bot types and integrations, so everybody can have a bot.\r\n\r\n### Conclusion\r\n\r\nTo quote Steambot:\r\n\r\n\u003e'As this is growing wearisome, I would now be generally adopted.' -Steambot (October 5, 2015)\r\n\r\nMake your own bot with [Metabot](http://metabot.hashrocket.com), and let us know what you think.","content_text":"We made a robot.\n\nOur foray into chatbots began with Steambot. Rocketeer Josh Davey wrote a Markov Chain text generator in Clojure, then trained it on some Kafka, Russell, Aristotle, Nietzsche, and a special ingredient: Steam, Its Generation and Use by Babcock \u0026amp; Wilcox Company (35th edition, copyright 1919).\n\nHe named his program Steambot and configured it as an outgoing webhook in Slack. This was Steambot's first message, triggered with the keyword 'steambot':\n\n\n'The Mean man will be vexed, but only moderately and as their age changes so likewise do their pleasures.' -Steambot (November 6, 2014)\n\n\nWe pinged Steambot for a few days, asking it Turing Test-style questions like 'Steambot, what is love?'. Steambot responded: \n\n\n'It is the test of a K. W. steam engine turbine unit, Mr. H. G. Stott and Mr. R. G. S.' -Steambot (December 18, 2014)\n\n\nPretty soon there was so much traffic that we needed a dedicated Slack channel just for these inane conversations. The #steamroom was born.\n\nSoon there were other bots, written by Rocketeers across the company. We made Madbot, a robot that returns slightly wrong proverbs such as: 'When the going gets loud, the shaky get going.' We made Artbot, a robot who draws you an abstract picture. We made Fightbot, a robot who creates hypothetical battle matchups like this:\n\n\n'A hipster, can turn to steel, has a hostage ​VS​ an evil doll, afraid of nachos, hands glued to hips' -Fightbot (December 18, 2015)\n\n\nHalobot, Knightbot, Bardbot, and more. Within a few months we had created over a dozen outgoing webhooks, pinging Clojure, Go, JavaScript, and Ruby web apps.\n\nLike any good sitcom, a spin-off was inevitable. Wouldn't it be cool, we thought, to build a web app that made it easy and fun to create chat bots? One meta-bot to rule them all.\n\nWe are proud to introduce Metabot, a new side project from Hashrocket.\nHow It Works\n\nMetabot makes it easy to create your own bot. Simply click 'Make a bot', choose between the two bot types we've built (Markov Bot or Substitution Bot), feed your bots any text files you choose, and we'll provide you with an endpoint you can easily integrate into Slack.\n\nSoon your chat log will be alive with a fun, randomly coherent robot that you created. There's no limit to the personality you can give your bot, or the amount of bots you can create.\nTechnology\n\nTechnically, Metabot was a chance for us to showcase our process and hone competency in new technologies.\n\nThe backend is written in Go with a PostgreSQL database. We saw this as an opportunity to build a small code base using solid design patterns such as the Respository Pattern and a custom responsive caching system.\n\nThe Markov and Substitution algorithms are our own and were refined over months of dogfooding.\n\nThe frontend features a Middleman site generator and was written in React.js. It includes some cool CSS tricks that add personality to the robot.\n\nOn the devops side, Metabot features a rapid deployment with Nginx using Mina and a custom database backup.\n\nLook for more detail about the technology in forthcoming blog posts. In the future we plan to add more bot types and integrations, so everybody can have a bot.\nConclusion\n\nTo quote Steambot:\n\n\n'As this is growing wearisome, I would now be generally adopted.' -Steambot (October 5, 2015)\n\n\nMake your own bot with Metabot, and let us know what you think.\n","summary":"We made a robot.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/274/metabot.jpg","date_published":"2016-01-04T09:00:00-05:00","data_modified":"2016-01-04T09:11:13-05:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Company News","Hashrocket Projects"]},{"id":"https://hashrocket.com/blog/posts/introducing-today-i-learned","url":"https://hashrocket.com/blog/posts/introducing-today-i-learned","title":"Introducing Today I Learned","content_html":"I'm proud to introduce [Today I Learned](http://til.hashrocket.com), a concise mini-blog run by all of us here at Hashrocket.\n\nSoftware is an ever-changing field, and relevancy demands constant learning. We all learn every day, and Today I Learned allows us to continuously document and reflect on that journey as it happens. We use [the Hashrocket Blog](http://hashrocket.com/blog) to share announcements, new products, and software development techniques, but Today I Learned fills a gap for us: many Hashrocket Blog posts are lengthy, deliberate explorations of our field, but sometimes it's best to just post what you've learned the moment it happens.\r\n\r\nToday I Learned is different because it restricts posts to 200 words. It was designed to be readable and updated daily. Each post is personal– sometimes a tip is bleeding-edge stuff, while other times it's something basic that's just new to that person– but every post is fundamentally functional and directly related to our work.\r\n\r\nThis was my apprentice project, and I paired with Rocketeers from across the company. I learned a lot in that process and am grateful to everybody who lent stories, advice, and encouragement, especially my mentors in the Chicago office. Special thanks go to Cameron Daigle, who quickly styled an intuitive, responsive, and bold user experience.\r\n\r\nCheck it out!","content_text":"I'm proud to introduce Today I Learned, a concise mini-blog run by all of us here at Hashrocket.\n\nSoftware is an ever-changing field, and relevancy demands constant learning. We all learn every day, and Today I Learned allows us to continuously document and reflect on that journey as it happens. We use the Hashrocket Blog to share announcements, new products, and software development techniques, but Today I Learned fills a gap for us: many Hashrocket Blog posts are lengthy, deliberate explorations of our field, but sometimes it's best to just post what you've learned the moment it happens.\n\nToday I Learned is different because it restricts posts to 200 words. It was designed to be readable and updated daily. Each post is personal– sometimes a tip is bleeding-edge stuff, while other times it's something basic that's just new to that person– but every post is fundamentally functional and directly related to our work.\n\nThis was my apprentice project, and I paired with Rocketeers from across the company. I learned a lot in that process and am grateful to everybody who lent stories, advice, and encouragement, especially my mentors in the Chicago office. Special thanks go to Cameron Daigle, who quickly styled an intuitive, responsive, and bold user experience.\n\nCheck it out!\n","summary":"I'm proud to introduce Today I Learned, a concise mini-blog run by all of us here at Hashrocket.\n","image":"https://dkj231ikyz7c1.cloudfront.net/uploads/blog/post/image/229/til.png","date_published":"2015-06-11T09:00:00-04:00","data_modified":"2020-02-04T10:41:57-05:00","author":{"name":"Jake Worth","url":"https://hashrocket.com/team/jake-worth","avatar":"https://dkj231ikyz7c1.cloudfront.net/uploads/rocketeer/profile_image/86/jake-worth-headshot-2020-cropped-for-hr-3.jpeg"},"tags":["Company News","Today I Learned","Hashrocket Projects"]}]}