Check if command exists with shell script

if ! type gem > /dev/null; then
  echo 'gem command not found.'
fi


Tino

Delete merged git branches

Handy git command for deleting all local git branches that already merged git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

1
Stan

Simple Flux architecture with Vue.js

For a small app that only needs a simple state management pattern. I always use one component to hold the state of the app, a container. This act as a single source of truth for an app to refer to its states. Vue provides a mechanism to create a global event listener on the root level called EventBus which is a super simple way to mimic flux architecture.

All you need is one module that exports Vue as EventBus like so

// EventBus.js
import Vue from 'vue'
export const EventBus = new Vue()


Then you can use it inside your container to listen to event from any component inside the app. I normally add the listener on created life cycle.

EventBus.$on('event-name', callback)


Then you can import EventBus into any of your components and you can triggers my-custom-event from anywhere without having to emit the event to that component's parent and repeat the whole process in every component in between the component that triggers the change and the target container.

// Goes directly to the global listener and triggers callback
EventBus.$emit('event-name')


That's it. If it's getting too complex, consider using Vuex.

1
Tino

My most used slack shortcuts

⌘-K(or T) to open the channel switcher (I navigate channels solely with this shortcut and have my slack set to hide all channels without new messages)

⌘-F opens the search box. Can modify searches with from:@user and in:#channel for extra awesomeness

Up Arrow will edit you last message; perfect for when you hit Enter too early or mispell things

+:emoji: react to the last message. Have to be quick so nobody else replies before you react though or you'll react to the wrong message

/remind [someone usually myself] [to do something] [at this time in words] not really a shortcut but is great for not forgetting simple tasks

The channel switcher also supports fuzzy matching to some extent. If a channel is named foo-bar you can type fb to show it. It's doesn't work so well with multi-user-dm's though.

1.07 Thousand
Joe

Postgres Functions & Non-sargable Queries

Using postgres functions inside a where clause can make a query non-sargable.

Database Structure

tracks has_many artists

Non-Sargable Query

Using a LOWER function prevents DBMS engine from using indexes.

Track.joins(:artists).where('LOWER(tracks.display_name) LIKE ?', "eric clapton%").explain

Gather  (cost=1000.85..56714.32 width=4061)
   Workers Planned: 2
   ->  Nested Loop  (cost=0.85..55713.62 rows=3 width=4061)
         ->  Nested Loop  (cost=0.42..55708.37 rows=3 width=4069)
               ->  Parallel Seq Scan on tracks  (cost=0.00..55365.17 rows=41 width=4061)
                     Filter: (lower((display_name)::text) ~~* 'eric clapton%'::text)
               ->  Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations  (cost=0.42..8.36 rows=1 width=16)
                     Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
         ->  Index Only Scan using idx_35952_primary on artists  (cost=0.43..1.75 rows=1 width=8)
               Index Cond: (id = artist_relations.artist_id)


Sargable Query

Removing LOWER function allows DBMS engine to use indexes, resulting in faster execution.

Track.joins(:artists).where('tracks.display_name ILIKE ?', "eric clapton%").explain

Nested Loop  (cost=1497.60..2695.43 width=4061)
   ->  Nested Loop  (cost=1497.17..2684.94 rows=6 width=4069)
         ->  Bitmap Heap Scan on tracks  (cost=1496.75..1873.05 rows=97 width=4061)
               Recheck Cond: ((display_name)::text ~~* 'eric clapton%'::text)
               ->  Bitmap Index Scan on index_tracks_on_display_name  (cost=0.00..1496.73 rows=97 width=0)
                     Index Cond: ((display_name)::text ~~* 'eric clapton%'::text)
         ->  Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations  (cost=0.42..8.36 rows=1 width=16)
               Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
   ->  Index Only Scan using idx_35952_primary on artists  (cost=0.43..1.75 rows=1 width=8)
         Index Cond: (id = artist_relations.artist_id)


Sargable and Non-Sargable


A sargable query is one that can use an index to speed up the query. A sargable query allows the DBMS engine to do an index seek, which is much faster than scanning the whole table. A non-sargable query can’t use an index, so it’s slower. The term “sargable” comes from “Search ARGument ABLE,” meaning the DBMS engine can use an index to optimize the query. Understanding the difference between sargable and non-sargable is key to optimizing your database.

Non-Sargable Queries


Non-sargable queries can have a big impact on query performance especially on large datasets. When a query is non-sargable, the DBMS engine has to do a full table scan or an index scan, both of which are heavy operations. This can result to slower execution time, higher CPU usage and overall poor system performance. Finding and optimizing non-sargable queries is key to improve your database’s efficiency and responsiveness.

Functions in the WHERE Clause


Using functions in the WHERE clause can make a query non-sargable. This happens because the DBMS engine can’t use an index to optimize the query when a function is applied to a column in the WHERE clause. For example, consider the query SELECT  FROM table WHERE UPPER(column) = 'VALUE'. This is non-sargable because the UPPER function is applied to the column, so the index can’t be used. To make this query sargable, you can remove the function and rewrite the query as SELECT FROM table WHERE column = 'VALUE'. Then the DBMS engine can use an index and the query will be faster.

Indexes and Query Optimization


Indexes are key to query optimization because they allow the DBMS engine to find the data quickly, hence speeding up the query. But an index can only be used if the query is sargable. If the query is non-sargable, the index can’t be used and the query will be slower. So create indexes on columns used in the WHERE clause and make sure the queries are sargable. This will improve your database’s performance big time.

Converting Non-Sargable Predicates


Converting non-sargable predicates to sargable is a query optimization step. A non-sargable predicate can be converted to sargable by rewriting the query to remove any functions or operations that prevents the use of an index. For example the query SELECT  FROM table WHERE YEAR(date) = 2022 is non-sargable because the YEAR function is applied to the date column. To make this query sargable you can rewrite it as SELECT FROM table WHERE date >= '2022-01-01' AND date < '2023-01-01'. This rewritten query is sargable because the DBMS engine can use an index on the date column to optimize the query and will be faster.

1
Abhi

Watch CI status on Github

When you have Github's hub installed, you can get the ci-status of your current branch like this:

$ hub ci-status
pending


If you install watch (e.g. brew install watch) you can continuously see the state:

$ watch hub ci-status


Const

Bash aliases and magic

I have a seperate file in my user folder named ~/.aliases. I use this to store all of my bash aliases. I use aliases a lot and add new ones regularly so I created a bash function to add new aliases on the fly.

addalias() {
  echo 'alias '$1'="'$2'"' >> ~/.aliases
  source ~/.aliases
}


Now you can add an alias from the terminal which will be available to the current session and all new sessions... shell $ addalias foo 'echo "bar"'

If I find myself using commands over and over I will create aliases shell alias g='git' alias b='bundle' alias be='bundle exec' alias bu='bundle update' alias r='bin/rails' alias rr='bin/rails routes' alias migration='bin/rails generate migration' alias migrate='bin/rails db:migrate; bin/rails db:migrate RAILS_ENV=test' alias rollback="rake db:rollback; RAILS_ENV=test rake db:rollback" alias push='git push origin HEAD' alias pr='git pull-request -c -m' alias ppr="git push origin HEAD && git pull-request -m" alias pulls='git browse -- pulls' alias prs='git pr list' pull() { git browse -- pull/'$1' } alias la='ls -a' alias ll='ls -al'

3
Joe

You can use FactoryBot for non ActiveRecord models

You can use FactoryBot's initialize_with method to initialize an object any way you like which allows you to factorize any of your objects at will

FactoryBot.define do
  factory :citizen_id_image, class: CitizenIdImagePresenter do
    image_url { 'https://placehold.it/200x200' }

    initialize_with { new(image_url: image_url) }
  end
end
build(:citizen_id_image)
#=> 


Introduction


FactoryBot is a popular testing tool for Ruby on Rails applications that allows developers to define and create test fixtures on the fly. It provides a flexible and efficient way to create test data, making it easier to write and maintain tests. In this article, we will explore how to use FactoryBot effectively in Rails testing.

Setting up FactoryBot


To set up FactoryBot in your Rails application, you need to add the factory_bot gem to your Gemfile and run the bundle install command. You can then configure FactoryBot by creating a factory_bot.rb file in the config/initializers directory. In this file, you can define the factory_bot configuration, such as the factory paths and the default strategy.

Defining Models and Factories


In FactoryBot, a factory is a blueprint for creating an object. You can define a factory for a model by creating a file in the factories directory. For example, if you have a User model, you can create a user.rb file in the factories directory to define the user factory. In this file, you can define the attributes and associations for the user factory.

Factory Options and Attributes


FactoryBot provides several options and attributes that you can use to customize your factories. For example, you can use the class attribute to specify the class of the object being created. You can also use the attributes option to define the attributes for the factory. Additionally, you can use the association option to define associations between factories.

Conclusion


In conclusion, FactoryBot is a powerful tool for creating test fixtures in Rails applications. By defining factories for your models, you can create test data quickly and efficiently. With its flexible configuration options and customizable attributes, FactoryBot makes it easy to write and maintain tests. By following the best practices outlined in this article, you can get the most out of FactoryBot and improve the quality of your tests.
6
Joe

Force push previous commit to repo

If you push some code and want to force push a previous commit you can do so with shell git push origin +commit_sha^:branch_name

Where git interprets sha^ as the parent of sha and + as a forced non-fastforward push.

You can also use HEAD^ where ^ is the parent of HEAD so HEAD^^^ would push the commit 3 commits before the current commit. e.g. shell git push origin +HEAD^^^:feature/i_did_an_oopsie

1
Joe

Get current git branch name

git rev-parse --abbrev-ref HEAD


Ali