Mocks & Spies in Minitest
Ruby code with gems on AWS Lambda
Using AWS Lambdas and API Gateway together: Function Policies
Hash.new with a block
Apollo flattens your GraphQL data!
Suppose we’re retrieving items in an eCommerce cart:
query {
cartItems() {
item {
product {
id
size
}
}
}
}
Data is returned as expected.
{
cart_items: {
0: {
product: {
id: "nulogy-shirt",
size: "medium",
},
},
1: {
product: {
id: "nulogy-shirt",
size: "large",
},
},
}
}
In our cart, we have two nulogy-shirt
items. One is medium, one is large, so they’re not quite the same product. When this data hits Apollo, however…
{
cartItems: {
0: {
product: {
id: "nulogy-shirt",
size: "medium",
},
},
1: {
product: {
id: "nulogy-shirt",
size: "medium",
},
},
}
}
All the data is stored in Apollo’s cache as a flattened array. Regardless of how they’ve been nested inside other objects, no two objects of the same type can share an ID. Otherwise, the first object overwrites all others.
Apollo makes this comparison based on the id
or _id
field (or a user override). If not found, the object’s keys become dependent on the nesting (ROOT_QUERY.cartItems.0.product
and ROOT_QUERY.cartItems.1.product
)
If you experience this, a good solution is to rename the ID field for the query’s response.
See https://www.apollographql.com/docs/react/advanced/caching/#normalization
Slow Terminal Startup Tip: Lazy Load NVM
For a long time, my ZSH shell windows/tabs have had very slow startup times, sometimes taking 5-10 seconds before .zshrc
fully loads and the input cursor appears. This slows down my daily development cycles.
It turns out that loading NVM was the main culprit. Using this Medium post and this gist as motivation, I have added this snippet to my .zshrc
file in order to lazy load nvm
, npm
, node
, and npx
(copied from the gist, credit goes to that author). I have immediately observed major speed improvements in my shell speed load times.
lazynvm() {
unset -f nvm node npm npx
export NVM_DIR=~/.nvm
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
if [ -f "$NVM_DIR/bash_completion" ]; then
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
fi
}
nvm() {
lazynvm
nvm $@
}
node() {
lazynvm
node $@
}
npm() {
lazynvm
npm $@
}
npx() {
lazynvm
npx $@
}
Improve macOS Performance with Spotlight Privacy
File contents indexing on macOS is performed by Spotlight. You can reduce Spotlight’s activity by excluding directories such as:
- ~/src
- ~/Library/Caches/
- ~/Library/Containers/com.docker.docker/
- ~/Library/Containers/com.docker.helper/
Go to System Preferences > Spotlight > Privacy and get yourself a faster machine.
Finding a Rake Task Definition
Suppose you use a certain Rake task. Is there an easy way to find out where that task is defined?
There is. Use the ` –where` option.
Example: rake --where packman:update
Ignore some paths from git diff
Problem
I want to do a git diff
, but I need some paths to be ignored.
e.g. git diff --name-only
Output:
some_dir/aaa
some_dir/bbb
some_dir/ignore_me/aaa
some_dir/ccc
some_dir/ddd
What I want:
some_dir/aaa
some_dir/bbb
some_dir/ccc
some_dir/ddd
Solution
“After a path matches any non-exclude pathspec, it will be run through all exclude pathspecs (magic signature: ! or its synonym ^). If it matches, the path is ignored.”
git diff --name-only -- '!**/ignore_me/*'
Disable special characters in OS X (no 3rd party)
RubyMine comes with handful of mnemonics which are supposed to boost your productivity. However ones that are combined with alt
keys can sometimes cause unexpected behaviours since some of them are bound to special characters (e.g. ™, Ó, µ …).
You can disable special characters by choosing “Unicode Hex Input” as an input source (System Preferences > Keyboard > Input Sources > Others).
Now typing Alt
+ key won’t interfere with any keyboard shortcuts. Happy RubyMining!
Lazy-load NVM to speed up zsh initialization
UPDATE
Once appending --no-use
, ensure to source $NVM_DIR/.nvm.sh
when actually needed. For example, yarn install
will complain ` node: No such file or directory`
I was curious as to why the zsh initialization was so slow. After some benchmarking .zshrc, I learned that oh-my-zsh and NVM were the main source of slow-down. For oh-my-zsh, I’m trying to see if I can avoid loading plugins that I rarely use to cut some time. However for nvm, simply passing `–no-use the following will make a big difference.
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" --no-use
Benchmarking with bash’s buil-in time
command…
Before --no-use
:
❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
1.43 real 0.65 user 0.62 sys
2.42 real 0.66 user 0.61 sys
1.42 real 0.65 user 0.61 sys
1.42 real 0.65 user 0.61 sys
2.43 real 0.66 user 0.62 sys
After --no-use
:
❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
0.48 real 0.26 user 0.17 sys
0.46 real 0.25 user 0.16 sys
0.46 real 0.25 user 0.16 sys
0.46 real 0.26 user 0.16 sys
0.49 real 0.27 user 0.17 sys
Sources:
https://github.com/creationix/nvm/issues/539 https://github.com/michaelmoussa/dotfiles/commit/8d67223aad5885ffc17e540b00e00478dd3c44d2 https://blog.jonlu.ca/posts/speeding-up-zsh
Rebase your branch from one branch to another
Use: git rebase --onto new-base-branch current-base-branch
For example, let’s say we have a feature branch based on master, and we decided it’s better to rebase it off production. This is our current git history:
commit 6 [my-feature-branch]
commit 5
commit 4 [master]
commit 3
commit 2 [production]
commit 1
We just need to run:
git checkout my-feature-branch
git rebase --onto production master
And we will end up with the following history:
commit 6 [my-feature-branch]
commit 5
commit 2 [production]
commit 1
Reference: https://makandracards.com/makandra/10173-git-how-to-rebase-your-feature-branch-from-one-branch-to-another
Use Chrome to make "desktop apps"
You can use Chrome to make slick desktop apps for your frequently used tabs, and even make aliases:
alias twitter="open -na 'Google Chrome' --args '--app=https://mobile.twitter.com'"
# replace #{UID} with the index of the google account you want to use
# if you are signed in to multiple accounts on your computer, otherwise 0 should be fine.
alias cal="open -na 'Google Chrome' --args '--app=https://calendar.google.com/calendar/b/#{UID}/r'"
# for fun
alias pm="open -na 'Google Chrome' --args '--app=https://packmanager.nulogy.net/'"
Original tweet: https://twitter.com/JaKXz92/status/1025050967111344128, credits to Elijah Manor!
Before Callback Changes in Rails 5
In Rails 4 and below, callbacks like before_validation
always had a gotcha that you had to watch out for:
before_validation :ensure_field_is_false_when_condition
def ensure_field_is_false_when_condition
self.field = false if condition?
end
When condition?
is true
, the assignment happens. However, assignment returns the value that was assigned, so the before_validation
receives the returned value false
. As the docs mention:
If the returning value of a before_validation callback can be evaluated to false, the process will be aborted and Base#save will return false.
This is usually handled by an explicit return
(i.e. nil
does not stop the callback chain):
def ensure_field_is_false_when_condition
self.field = false if condition?
# extraneous return that is not Ruby-ish
return
end
Rails 5 Update
There is a great change to the before_validation
callback behaviour in Rails 5:
If the before_validation callback throws :abort, the process will be aborted and ActiveRecord::Base#save will return false.
This makes halting the callback chain much more transparent and intention revealing:
before_validation :safely_assign_false, :always_halt_validation
def safely_assign_false
self.field = false
end
def always_halt_validation
throw(:abort)
end
Accessing Redux Store Without Redux DevTools
Thank you Dan Ambrogio for discovering this tip. Also, check out this blog post for more on the topic of Redux DevTools on production environments.
Let’s say that you want to access the Redux Store on a production environment of your React/Redux application. Normally, you would do this through the Redux DevTools. However, your app has these DevTools disabled on production. What do you do then?
As long as your browser has the React DevTools installed, there’s this awesome workaround (assuming you are using Chrome, could easily be ported to other browsers):
- Navigate to the web page in question
- Open up the Chrome DevTools
- Click on the React tab
- Click on the top-level
<Provider>
element/component - Press
<ESC>
to bring up a console in a split panel - Execute the following code:
$r.store.getState()
. VOILA!
Hash keys must be symbols for keyword arguments
Recently our team worked on a ticket which required us to remove the tooltips for Edit, Delete button.
As an initial approach, we changed the signature by parameterizing the tooltip, and inserted into #link_to helper. To preserve the options parameter, we converted it into a keyword argument (**options).
def link_to_delete_remote(object, path, tooltip: _("Delete"), **options)
…
link_to(options[:title], path, options.merge('data-bad-after': js, id: link_id, title: tooltip, remote: true))
end
<%= link_to_delete_object(job, tooltip: nil) %>
However, bunch of specs started failing with the following message.
# ArgumentError: wrong number of arguments (given 3, expected 2)
Turns out, there were few callers of the method who were passing in an object that contains String keys, and they weren’t being used as keyword arguments…
<%= link_to_delete_object(
attachment,
"some-string-key" => _("some_string_value"),
"another-string-key" => true
) %>
In the end, we reverted the signature, injected tooltip: nil
to options
object, and just inlined options.fetch(:tooltip, _(“Delete”))
def link_to_delete_remote(object, path, options = {})
...
link_to(options[:title], path, options.merge('data-bad-after': js, id: link_id, title: options.fetch(:tooltip, _("Delete")), remote: true))
end
Dig-ging into Data
Ruby 2.3 added a couple of dig
methods to aid in accessing nested data.
Here’s some Hash and Array examples:
hash = {
animals: {
furry: ["dog", "cat"],
spikey: ["porcupine", "echidna"]
}
}
hash.dig(:animals, :furry)
# => ["dog", "cat"]
# safely returns `nil` for missing keys
hash.dig(:plants, :yellow)
# => nil
array = [1, [[2, 3], 4, 5], 6]
array.dig(1, 0, 1)
# => 3
# dig on arrays take indexes, and repeatly call dig on the result
# thus, you have to be careful if the return type is not an array!
array.dig(2)
# => 6
array.dig(2, 3)
# => TypeError: Fixnum does not have #dig method
# and duck typing means they can be combined!
hash.dig(:animals, :spikey, 1)
# => "echidna"
Finding Where Rake Tasks Are Defined in Rails
Rake has an option to print where a task was loaded from.
$ rake -W gettext:find
rake gettext:find $HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:64:in `block in <top (required)>'
We can also get this data with code. This allows us to explore the tasks (e.g. filtering). In a Rails console:
# load up all the tasks Rails knows about
> Rails.application.load_tasks
...
# if you know the task you are looking for:
> Rake::Task["gettext:find"].actions.map(&:source_location)
=> [["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb", 64]]
# if you want to explore known tasks
> gettext_tasks = Rake.application.tasks.select { |e| e.name.start_with? "gettext:" }
=> [<Rake::Task gettext:add_language => [environment]>, <Rake::Task gettext:base_without_table_attributes => [environment]>, <Rake::Task gettext:find => [setup]>, <Rake::Task gettext:pack => [setup]>, <Rake::Task gettext:setup => [environment]>, <Rake::Task gettext:store_model_attributes => [environment]>]
>
> pp Hash[gettext_tasks.map { |t| [t.name, t.locations] }]
{"gettext:add_language"=>
["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:99:in `block in <top (required)>'"],
"gettext:base_without_table_attributes"=>
["$HOME/src/packmanager/master/lib/tasks/gettext.rake:27:in `block in <top (required)>'"],
"gettext:find"=>
["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:64:in `block in <top (required)>'"],
"gettext:pack"=>
["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:59:in `block in <top (required)>'"],
"gettext:setup"=>
["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:43:in `block in <top (required)>'"],
"gettext:store_model_attributes"=>
["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:82:in `block in <top (required)>'"]}
React Synthetic Events
React is awesome! Because it helps with making consistent event handler functions [among many other things].
Every event handler will be passed instances of SyntheticEvent
which has consistent properties [as opposed to the native events’ variations in properties].
How to trigger a redeploy on ECS from web console
Sometimes, there is a neeed to trigger a redeploy on an ECS service without making any task changes (for example: rerun initialization scripts to pull secret updates). To trigger such a redeploy on an ECS service from the web console:
- Open the ECS service module on the AWS web console
- Click on the Cluster, then the Service you wish to trigger the redeploy on
- Press the Update button on the top-left
- Select the “Force new deployment” checkbox. Make no other changes. Press on the Next Step button.
- Click “Next Step” and “Confirm” on all subsequent screens without making any other changes.
You can observe that the process is a success by watching the Events tab for new tasks startin and old tasks stopping, and the Tasks tab to witness the new tasks go live.
What does the zeus's read unix EOF error mean?
Question
I’m running zeus, and it dies with the following error:
slavenode.go:226: [boot] read unix ->: EOF
What on Earth could be causing that? How do I fix it?
Answer
UPDATE (2018-06-13): I realized that this is one possible fix to this issue. Still useful info, so I’ll leave it here.
Run bundle install
Source: https://github.com/burke/zeus/issues/641
ORDER BY NULL Sorting Options
The ORDER BY
clause has options for placement of NULL
columns. From the Postgres docs, the ORDER BY
grammar is:
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
It shows we can put the NULL
columns first or last.
Example
Imagine we have a datetime range, implemented as (start_at
, end_at
) tuples.
CREATE TABLE dates (id INT, start_at TIMESTAMP, end_at TIMESTAMP);
INSERT INTO dates VALUES
(1, TIMESTAMP '2018-01-01 9:45', TIMESTAMP '2018-01-01 10:00'),
(2, TIMESTAMP '2018-01-01 10:00', null),
(3, TIMESTAMP '2018-01-01 10:15', null);
We want to order by end_at
, then start_at
. However, we want the NULL
end_at
tuples to appear before any with a value.
By default, NULL
values will appear after non-NULL
. With the NULLS FIRST
option, we can change that:
SELECT * FROM dates ORDER BY end_at NULLS FIRST, start_at, id;
╒══════╤═════════════════════╤═════════════════════╕
│ id │ start_at │ end_at │
╞══════╪═════════════════════╪═════════════════════╡
│ 2 │ 2018-01-01 10:00:00 │ <null> │
├──────┼─────────────────────┼─────────────────────┤
│ 3 │ 2018-01-01 10:15:00 │ <null> │
├──────┼─────────────────────┼─────────────────────┤
│ 1 │ 2018-01-01 09:45:00 │ 2018-01-01 10:00:00 │
╘══════╧═════════════════════╧═════════════════════╛
You can also specify NULLS
when creating indexes too.
Move cursor word by word on iTerm
Problem
Cursor navigation can be slow on iTerm
Solution
Enable word by word cursor movement
Preferences > Profiles > Keys > Select + to add new key mapping
To move left:
Keyboard Shortcut: ⌥ ←
Action: Send Escape Sequence
Esc+ b
To move right
Keyboard Shortcut: ⌥ →
Action: Send Escape Sequence
Esc+ f
Def keyword can also be used as a begin statement
In Ruby, the begin
keyword for exception handling (ie, begin...rescue...ensure
, traditionally try...catch...finally
in other languages) is optional. You can have a method that only declares a rescue
or an ensure
statement without begin
. That’s because the def
statement in the method can serve the same purpose as begin
. This means that this method:
def edit
begin
@user = find(params[:id])
...
rescue ActiveRecord::RecordNotFound
redirect_to :back
end
end
Can legally be shortened to:
def edit
@user = find(params[:id])
...
rescue ActiveRecord::RecordNotFound
redirect_to :back
end
Safe Navigation Operator
If you have worked in a Rails project, you have probably came across the try
and try!
methods. try
saves us from checking conditions before drilling-down through a message chain. try!
is more restrictive; it raises when the receiver does not respond to the method:
require "active_support"
require "active_support/core_ext/object/try"
User = Struct.new(:name)
users = [User.new("Jason")]
users.first.try(:name)
# "Jason"
users.first.try(:unknown_method)
# nil
users.first.try!(:unknown_method)
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">
Note these methods are provided by ActiveSupport
. As of Ruby 2.3, this behaviour is now available in the language, called the safe navigation operator &.
:
users = [User.new(name: "Jason")]
users.first&.name
# "Jason"
users = []
users.first&.name
# nil
Gotchas
When an object does not respond to a method, &.
behaves like try!
; it raises an error. However, nil
seems to break this pattern:
# behaviour like try!
user&.unknown_method
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">
# given that
nil.nil?
# true
# this is confusing
nil&.nil?
# nil
The last example has a simple explanation: &.
checks the receiver. Since the receiver is nil
, &.
immediately returns nil
. It does not matter that nil
responds to the message.
Block Kwargs
Ruby 2.0 introduced keyword arguments. Ruby 2.1 further added required keyword arguments. It is common to see methods using kwargs:
def some_method(keyword_arg: "Hello", required_arg:)
puts "#{keyword_arg} #{required_arg}"
end
some_method(required_arg: "world")
# Hello world
However, these changes also apply to block arguments:
define_method :prints_block_arguments do |default_arg: "hello", required_arg:, **others|
puts "default_arg: #{default_arg}"
puts "required_arg: #{required_arg}"
others.each_pair do |key, value|
puts "other arg: #{key} => #{value}"
end
end
prints_block_arguments(required_arg: "world")
# default_arg: hello
# required_arg: world
prints_block_arguments(default_arg: "ciao", required_arg: "mondo", something: "else")
# default_arg: ciao
# required_arg: mondo
# other arg: something => else
prints_block_agruments()
# ArgumentError: missing keyword: required_arg
Git Shortlog
There are many ways to customize your git log
output. However, the structure still the same: commit by commit.
A new variation I recently discovered was git shortlog
. It displays commits by author, rather than most recently committed order. It is intended to help producing release notes.
This lets you find out who your largest contributors are, especially with the --summary
option.
Try this:
$ git shortlog --summary | sort -r
Default Value for Deconstructed Object Parameter
In ES6, you can deconstruct a function’s object parameter to have its properties assigned to local named variables:
function MyComponent({
item: { foo, bar }
}) { ... }
Also in ES6, the properties of the object parameter can have a default value set:
function MyComponent({
item = "LOL"
}) { ... }
TIL: The object parameter can have both destructuring and default values applied to it!
function MyComponent({
item: { foo, bar } = { foo: 1, bar: 2 }
}) { ... }
Debug Arrow Functions With Comma Operator
Use the Comma Operator to execute many JavaScript expressions in one ‘location’, but only return the value from the last expression.
This is commonly used in classic for
loops, but has an interesting use case to quickly debug a single-line arrow function. For example, suppose you wanted to throw a console.log()
into this function:
const myFunc = value => doCrazyOperation(value.foo);
Without the comma operator, this function would have to be expanded into a multi-line “block” function with a return
statement, which is relatively quite longer:
const myFunc = (value) {
console.log("value", value);
return doCrazyOperation(value.foo);
};
With the Comma Operator, this debugging is much easier to write and maintain:
const myFunc = value => (console.log("value", value), doCrazyOperation(value.foo));
Using module_function instead of extend self
It’s a common pattern to use extend self
inside ruby module to make all methods available in a static context/declared as class methods.
Instead of this, you can use module_function
instead which will do the same as extend self but also have the added benefit of making those method private instance methods when they are included in another file.
module UserNameFormatter
module_function
def format_name(user)
"#{user.name}"
end
end
class User
include UserNameFormatter
def something
format_name(self)
end
end
Searching Through Gems
Sometimes you need to peak at the source of a class or method of a gem from your Gemfile
. Since gems are managed by bundler
, it has a command-line option that can help.
bundle show --paths
will list the paths of all the gems from your Gemfile
. You can grep through these directories to search.
I’m currently using ripgrep for searching at the command line, so can pass the paths there.
Here’s it all together in a simple Bash function:
function bundle-search() {
rg $1 `bundle show --paths`
}
Enumerable Predicate Methods Have a New Argument
Enumerable#grep
accepts an argument that returns elements that are true
using case equality (===
). These elements can then be passed to its block for further proccessing:
fruits = %w(apples orange grapes)
fruits.grep(/s$/) # => ["apples", "grapes"]
fruits.grep(/s$/) { |e| e.start_with?("a") } # => [true, false]
In Ruby 2.5, this parameter argument was added to the Enumerable
predicate methods all?
, none?
, one?
, and any?
.
fruits = %w(apples orange grapes)
fruit.any?(/s$/) # => true
# === works with more than Regexes!
[1, 3.14, 2ri].all?(Numeric) # => true
[0, 1, 2, 3].all?(1..10) # => false
[0, 5].one?(1..3) # => false
[0, 5].none?(1..3) # => true
More Expressive Regular Expressions with Ruby
I came across some parsing code that contained this regular expression:
# the first capture is the left quote
# the second capture is the string content
# the third capture is the right quote
METHOD_CAPTURE = /Module\.method\(\s*(['"])(.+?)(['"])\s*\)/
This regexp is matching the string contents of a particular method call. It captures three pieces of information, mentioned in the comments.
This code is not self-documenting. We have three comments explaining the captures, and a regexp we must parse in wetware.
Furthermore, numerical indexes are difficult to track and modify in complicated regexps. PCRE supports named captures; denoted in Ruby by (?<name>pattern)
.
To make the comments superfluous, let’s refactor using the following:
- Use named capture groups
- Use interpolation to give descriptive names to common components
- Don’t capture needlessly (in our case, the captured quote characters are not used)
- Prefer
[]
over escaping (personal preference)
quote_character = %q|['"]|
optional_whitespace = "\s*"
METHOD_CAPTURE = /Module[.]method[(]#{optional_whitespace}#{quote_character}(?<string_contents>.+?)#{quote_character}#{optional_whitespace}[)]/
# #match returns an object or nil
matches = 'Module.method("some string")'.match(METHOD_CAPTURE)
# if an object, access captures by name:
matches[:string_contents] # "some string"
You can tailor how many named expressions/variables to use based on the complexity of the regexp.
Copy current file path relative to project root
I already knew about copying the current file path to the clipboard by using Shift+Cmd+C
. The problem with this approach is that it copies the absolute path, for example, /Users/arturo/src/cool_project/lib/module/my_file.rb
. This is not ideal if you are planning on sending this path to someone else or for some document you are writing.
A better option is to use RubyMine’s Action Copy Reference
which by default is bound to Shift+Alt+Cmd+C
. This copies the current file path relative to the project, for example, lib/module/my_file.rb
To summarize:
Copy Paths Action
- Default shortcut: Shift+Cmd+C
- Example text to clipboard:
/Users/arturo/src/cool_project/lib/module/my_file.rb
Copy Reference Action
- Default shortcut: Shift+Alt+Cmd+C
- Example text to clipboard:
lib/module/my_file.rb
Thanks to Jordan N. for the tip!
Force push safely using --force-with-lease
We periodically force push feature branches when we rebase them.
To do this safely, I first check manually to see if my pair has pushed any commits I don’t yet have in my local branch.
But there’s an easier and safer way to do this. The --force-with-lease
option will fail if there are upstream changes not yet merged.
It will work smoothly for standard rebasing situations, but protect against any inadvertent destructive force pushes.
Thanks to Jason K for sharing this tip with me!
How to Center Vertically and Horizontally in CSS
This helpful guide teaches you everything you wanted to know about centering your HTML elements vertically and horizontally using CSS: https://css-tricks.com/centering-css-complete-guide/
Regexes are supported by Capybara has_content?
Problem
I am trying to assert the presence of a button on the page by checking the button text:
expect(page).to have_content("Close")
Unfortunately, the page also has a dropdown that contains the option Closed
.
Solution
Regex to the rescue!
expect(page).to have_content(/Close\b/)
Finding Where a Method is Defined
One great thing about Ruby is how flexible it is. Although sometimes it can be hard to determine where a method definition comes from.
One useful technique to pull out in just this circumstance is the source_location
method.
For example, suppose you see a call to the quantity
method in a spec and you wonder where its definition comes from.
Do some puts debugging by adding this line:
puts method(:quantity).source_location
Send commands to all panes in iTerm
Problem
I just edited my shell profile (~/.zshrc
).
Now I need to remember to reload any pane that needs the changes.
Solution
Send commands to all panes:
Cmd + Shift + I
source ~/.zshrc
Magic!
Lambda argument passing shorthand
Suppose that I have a Ruby lambda like so:
greeting = -> name { "Hello #{name}" }
The conventional way of calling this lambda is like so:
greeting.call("Ned") # "Hello Ned"
However, for those of you dreading having to type in call
(hello, JavaScript developers), you can use this syntactic sugar instead:
greeting["Ned"]
greeting.("Ned")
Source: https://stackoverflow.com/questions/18774139/how-works-with-lambdas
UPDATE
I am now a sad panda to learn that this shorthand syntax is not recommended in the ruby-style-guide: https://github.com/bbatsov/ruby-style-guide/issues/205 https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#proc-call
It’s still a cool learning for me to know that this syntax exists in the first place, though.
Repeat last substitution in VIM
Use the &
motion to repeat the last substitution in VIM. IE, the most recent :s
command.
Very handy in a git interactive rebase that requires every commit message to have a ticket reference changed.
FactoryGirl identifiers as symbols not strings
Why is FactoryGirl.create(:my_object)
better than FactoryGirl.create("my_object")
?
Symbols are immutable objects that are stored by the Ruby interpreter as a numeric ID (an implementation detail, the design of Ruby is flexible for different storage mechanisms).
Strings, on the other hand, take up a memory footprint as large as the number of characters in the string. Using symbols will thus take up less memory and potentially be faster because the same address in memory will be used.
If you have n instances of the same string in your code, Ruby will use O(n) memory to store all those strings, however, if you have n instances of the same symbol in your code, Ruby will use O(1) memory to do the same lookup.
Further reading: https://bugs.ruby-lang.org/issues/7792#note-58
This TIL came courtesy of a discussion with Evan and later on Arturo about best practices in writing test code, but shared here because it’s broadly applicable and the FactoryGirl example is just one use case.
Z-Index Equivalent in SVG
To mimic the z-index CSS property in SVG, add the SVG elements to the page in the reverse order that you expect their z-positioning to be set. The subsequent elements added are placed on top of previous elements.
For example, if I were using the React SVG charting library Victory and I wanted my chart lines to be stacked on top of my chart area shading, I will add them to my component like so:
<VictoryChart>
<VictoryArea ... />
<VictoryLine ... />
</VictoryChart>
Combine all ES6 generator values into an array
The ES6 spread operator can be applied to an iterable to combine all its results into one single array. A trivial use case for this is to merge extra elements into an existing array (ie, [...existingArray, 2, 3]
).
This usage of the spread can be applied to a Generator to combine all the results of the calls to next()
into one array. This serves as syntactic sugar to replace needing to use a for-of loop to do the same operation. Here’s an example (illustrative purposes only, ignore that this is not the best way to solve this problem):
function* evenNumbersGenerator(maxNum) {
for (let i = 0; i <= maxNum; i += 1) {
if (i % 2 == 0) {
yield i;
}
}
}
...
const evenNumbersTo100 = [...evenNumbersGenerator(100)];
Side Learning: Generator functions cannot be declared as an arrow function, because they have to be declared as a “non-method function”.
Surround around array of React SVG components
It is a typical practice when writing a React component that renders a list/array of components to surround these components around a <div>
tag. This is because React does not directly support rendering arrays of components.
This practice will not work if the React components will deep-render SVG elements instead of HTML markup. The solution instead will be to wrap the array of SVG-based child components around <g>
tags (which stands for group in SVG).
https://www.smashingmagazine.com/2015/12/generating-svg-with-react/
A More Succinct Way to Update Model Attributes
Instead of model.update_attributes!
you can use this shorter form: model.update!
VIM: Move a numbered line to current cursor
Let’s say I’m on line 20 and I want to move line 10 to my current line. Useful for code refactoring.
How I used to do it
10G
dd
19G
p
Or:
:10d
p
The new way I’ll do it
Thanks to my learnings here:
:10m .
Exclusion using File Masks
When using “Find in Path..” functionality to find a word across multiple files, file masks can be used to match certain types of files. For example, using *.rb will only look through Ruby files. On the other hand, if you want to exclude Ruby files instead, you can add an ! at the front (i.e. !*.rb).
Here are other useful examples/combinations:
all files excluding spec tests: !*spec.rb
all Ruby files excluding spec tests: *.rb,!*spec.rb
Add have_selector() matcher to RSpec Request Specs
If you are used to writing controller specs, you are probably comfortable with the `have_selector matcher. However, in request specs this matcher is not available. By default, you can only do text search inside the request body which leads to brittle assertions.
You can add the have_selector
matcher by updating your RSpec config to include the Capybara matchers on request specs as well.
RSpec.configure do |config|
config.include Capybara::RSpecMatchers, type: :request
end
Then you can write more confident Request specs by using assertions like expect(response.body).to have_selector('ul li', text: 'List content here!')
Stop a docker-compose container without removal
Suppose you need to stop your docker-compose container but you don’t want to remove the container. For example, this container runs your database, so removing the container would mean that you would also lose all your data.
Don’t use docker-compose down
. This will remove your container and you will have rebuild your database from scratch. Sad panda.
Instead, use docker-compose stop
. You can then restart the container and have all the data back that you had before.
Resources:
Search DOM by selector in Chrome Inspector
Problem
I want to select a DOM element by CSS selector on my React-generated web page for debugging purposes. In this case, I am trying to test out CSS selectors to be used in my Capybara acceptance test.
Solution
Use jQuery NO, DON’T DO THAT!
A neat feature of the Chrome Web Inspector is that I can search an entire page by CSS Selector, without needing to litter my code with debugger
statements. Just open up the Elements tab and then press CMD-F
(on Mac) to open up a search bar. I can now type whatever CSS Selector that I want and view the results that match. I can quickly test different selectors out, so that I can verify that I am writing my Capybara test accurately.
An Improvement to the Behaviour of the Git Pager
First, capture your current git pager settings (in case you want to go back):
git config --list | grep core.pager
Second, configure your new and improved git pager settings:
git config --global core.pager "less $LESS --tabs=2 -RFX"
--tabs=2: Is just right for displaying Ruby diffs
-R: Repaint the screen, discarding any buffered input
-F: Causes less to exit if a file is less than one screens worth of data
-X: Leave file contents on screen when less exits.
If you want to get even fancier consider diff-so-fancy.
Bulk Upsert through PostgreSQL 9.5+
Warning: This only works for PostgreSQL 9.5+ ___
Given the following:
- a users table:
- id
- name
- created_at
- updated_at
- users table only has 1 user with values:
- id: 1
- name: Alejandro
- created_at: ‘2010-10-10 10:00:00.000000’
- updated_at: ‘2010-10-10 10:00:00.000000’
You can upsert using the following SQL query:
INSERT INTO
users(id, name, created_at, updated_at)
VALUES
(1, 'Alexander', NOW(), NOW()),
(2, 'Belle', NOW(), NOW())
ON CONFLICT (id)
DO UPDATE SET
name=EXCLUDED.name,
updated_at=NOW()
;
Results:
- User(id=1) will be renamed from Alejandro to Alexander. The updated_at value will be set to current time.
- User(id=2) will be inserted to users table with name = Belle, and both created_at and updated_at will be set to current time.
Chrome: Inspecting DOM elements that require focus
Using Chrome Dev Tools, I occasionally want to inspect an element that requires focus - for example, inspecting a selected date in a date selector.
Problem
As soon as I click the dev tools window, the element loses focus and I can no longer inspect in with the desired state.
Undesirable solution
On occasion when I’ve run into this scenario, I’ve placed a breakpoint or debugger
statement in the JavaScript function that would be called when focus is lost. The problem with this is that it takes time and I need to locate the appropriate place in code.
Better solution
When in the desired state - for example, with the current date selected - pressing F8
will pause JavaScript execution. I can then inspect the DOM in the desired state.
Changing Your iterm2 Profile Programmatically
Change your iterm2 profile to Production with this command:
echo -e “\033]50;SetProfile=Production\a”
Create a function to make it easier to switch profiles:
function iterm_profile {
if [[ -z $1 ]]; then
profile="Default"
else
profile=$1
fi
echo -e "\033]50;SetProfile=$profile\a"
}
I use this feature to let me know I am working on the Rails migration.
Diff CSVs With Ease
We’re all familiar with diff tools like RubyMine, vimdiff, or the good old diff
command. These work well for source code but are not optimal for CSVs files, which may have many columns and rows.
I found myself wanting to write CSV-specific diff tool, but I fought that Not Invented Here impulse and Googled first. I found a good Python library called csvdiff
.
Imagine we have the following CSV file:
id,name
1,Alan Turing
2,John McCarthy
3,Edger Djikstra
We want to compare it to another file:
id,name
1,Alan Turing
3,Edsger Dijkstra
4,John Von Neumann
We’ve removed, edited, and added a row. The summary option confirms our changes:
$ csvdiff --style=summary id one.csv two.csv
1 rows removed (33.3%)
1 rows added (33.3%)
1 rows changed (33.3%)
The detailed view gives us all the gory details:
$ csvdiff --style=pretty id one.csv two.csv
{
"_index": [
"id"
],
"added": [
{
"id": "4",
"name": "Jon Von Neumann"
}
],
"changed": [
{
"fields": {
"name": {
"from": "Edger Djikstra",
"to": "Edsger Dijkstra"
}
},
"key": [
"3"
]
}
],
"removed": [
{
"id": "2",
"name": "John McCarthy"
}
]
}
Range prefix to VIM command (from current line)
When I want to execute a command in VIM over a range of lines (for example, search-replace with :s
) starting from the current line, I could execute a command like so:
:.,.+10s/foo/bar/g
This reads as search-replace from the current line (.
) until 10 lines after. While useful functionality, it does require quite a bit of typing to execute.
Thankfully, there is a neat little shortcut that can be used to reduce some of this type. Simply enter the number of lines that you want to change from the current line and VIM will fill in the rest in the command prompt.
For example, I need to type 11:
and VIM will insert :.,.+10
into the command prompt. You can now finish off this command like needed. Do note that the line count includes the current line itself (think of this count as current line plus number of lines after).
Squish Those Strings
While reading some Rails code, I came across a deprecation warning:
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
`redirect_to :back` is deprecated and will be removed from Rails 5.1.
Please use `redirect_back(fallback_location: fallback_location)` where
`fallback_location` represents the location to use if the request has
no HTTP referer information.
MESSAGE
What caught my eye was the squish
method on the heredoc. It’s common to see methods after heredocs to clean up formatting, but squish
is a great method name.
squish
removes all leading and trailing whitespace, then replaces all consecutive whitespace with a single space. One application has been cleaning up long string messages that use the line continuation operator. The community style guide says to only use line continuations for concatenating strings, but I think squish
is cleaner:
long_string = "a long string " \
"spanning " \
"three lines"
# => "a long string spanning three lines"
better_long_string = "a long string
squished to a single line
without extra spaces or backslashes".squish
# => "a long string squished to a single line without extra spaces or backslashes"
An all-too-common caveat: squish
is an extenstion method from active_support
.
Speed Up Bundler
It turns out that you can speed up Bundler if you increase parallelization.
$ bundle config --global jobs 8
On OS X you can use the sysctl
command to determine the jobs
setting appropriate for your hardware:
$ sysctl hw.ncpu
hw.ncpu: 4
I’m using number of cores times two. Works for me. YMMV.
Cherry-picking a range of commits in git
Problem
I would like to cherry-pick a range of commits (e.g. an entire branch). For example, I want to cherry-pick the commits f00b4r
to f00ba5
, where foob4r
is the oldest commit on the branch.
Solution
git cherry-pick f00b4r~..f00ba5
.
Using Trigram Indexes to Speed Up LIKE Queries
Queries containing ILIKE '%anything%'
result in table scans since they have a leading wildcard. Typical btree
indexes can not help improve performance in this case.
Trigrams are 3-character slices of words:
SELECT show_trgm('Ruby');
-- {" r"," ru","by ",rub,uby}
They are useful as indexes since they can speed up LIKE
, ILIKE
, ~
, and ~*
clauses.
Let’s query a table of 14K email addresses:
CREATE TABLE emails (email TEXT);
\copy emails FROM 'emails.csv' DELIMITER ',' CSV;
EXPLAIN ANALYZE SELECT * FROM emails WHERE email ILIKE '%ion%';
The query plan shows a table scan:
Seq Scan on emails
Filter: (email ~~* '%ion%'::text)
Rows Removed by Filter: 14040
with an average execution time of 15ms
. Let’s create a trigram index and try again:
-- postgres 9.2+
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX emails_search_email_idx ON emails USING GIN (email gin_trgm_ops);
EXPLAIN ANALYZE SELECT * FROM emails WHERE email ILIKE '%ion%';
The improved query plan is:
Bitmap Heap Scan on emails
Recheck Cond: (email ~~* '%ion%'::text)
Heap Blocks: exact=98
-> Bitmap Index Scan on emails_search_email_idx
Index Cond: (email ~~* '%ion%'::text)
and averages 0.8ms
. A 19X improvement without updating any SQL queries! YMMV
bundle update --conservative
Let’s say you want to update the gem foo. After running bundle update foo
you look at your gemfile.lock and find that not only was foo updated, but so were many of its dependencies. You also notice that many of these dependency updates weren’t necessary, as the previously installed versions were compatible with the new version of foo.
The default bundle update foo
behaviour will unlock and update all dependencies of foo.
If you don’t want to update these dependencies unnecessarily, one solution is to add the current versions to your gemfile.lock.
However, an easier way to prevent the updating of shared dependencies is to use bundler’s new --conservative
flag.
All the different ways to lock your Mac computer
- Using the keyboard:
CTRL-SHIFT-eject
- Using Alfred: execute the
lock
command - Using a taskbar icon from Keychain:
- Open the app Keychain Access
- Preferences –> Enable the option “Show keychain status in menu bar”
- A lock-shaped icon will appear in the taskbar, with the option “Lock Screen”
- Use Hot Corners:
- System Preferences –> Desktop & Screen Saver –> Hot Corners button
- Set one of the corners as “Put Display to Sleep”
- Mouse into the direction of that corner (on the monitor closest to that side, for multi-monitor setups)
- If all else fails, just hold the Power button on your keyboard for a second to put your computer to sleep
Chef override attributes vs chef-client -j switch
When applying recipes via chef-client
, you can override attributes via the –json-attributes (or -j) switch. However, the override_attributes
option on roles
, environments
and recipes
has higher precedence over the –json-attributes switch.
For more info about Chef attribute precedence, use this as a reference. The attributes set via --json-attributes
are “normal” attribute types.
async/await Keywords of ES7 for Simpler Promises
ES7 introduces the async
/await
keywords. They are mostly syntactic sugar on top of Promises. You can write cleaner more readable asynchronous tasks code.
NOTE: They are available in Node 7.6.0 also.
Example:
Here is some code for programmatically creating a coding exercise for a developer candidate that has applied to us. We’ve improved the readability of it using async
/await
.
This hard to read test which uses Promises:
it('returns any errors that may have occurred', () => {
return automator
.getRepo()
.then(repo => !repo ? automator.createExercise() : Promise.resolve())
.then(() => this.room.user.say('alice', `hubot create coding exercise repo for ${candidateEmail}`))
.then(() => {
expect(lastBotMessage()).to.contain(`Error creating coding exercise for *${candidateEmail}*:`)
});
});
Becomes this:
it('returns any errors that may have occurred', async() => {
let repo = await automator.getRepo();
if (!repo) {
await automator.createExercise();
}
await this.room.user.say('alice', `hubot create coding exercise repo for ${candidateEmail}`);
expect(lastBotMessage()).to.contain(`Error creating coding exercise for *${candidateEmail}*:`)
});
Which reads more like an Arrange/Act/Assert style test.
Use PostgreSQL table as queue skipping locked rows
This command only works in PG 9.5
First, are you sure you shouldn’t be using some in-memory queue? Or some message broker? Or Redis?
If you are really convinced that you want this sort of behaviour on top of the goo’old PostgreSQL you can achieve a queue-like access pattern by locking and skipping locked rows.
One way to ensure that only one database client can modify a set of rows is to select the rows for update as in
BEGIN;
SELECT * FROM queue ORDER BY priority DESC LIMIT 1 FOR UPDATE;
...
This will block any other UPDATE or SELECT .. FOR UPDATE until the above transaction is finished. Now if you want concurrent database clients to fetch the next row available in the priority list just use:
BEGIN;
SELECT * FROM queue ORDER BY priority DESC LIMIT 1 FOR UPDATE SKIP LOCKED;
...
The above command could be interpreted as “select the next row from queue that nobody has yet locked”.
Skip duplicate history entries in zsh
In zsh, pressing UP searches through the history and brings up all matching commands, even if they are duplicates. That means, sometimes you need to press UP many times to actually find a previous match.
However, it is possible to disable this behaviour and skip duplicate entries from the history. To do that, add one line to your ~/.zshrc
:
setopt HIST_FIND_NO_DUPS
Ignore whitespace-only changes in Gitlab MRs
Problem
You are reviewing a Gitlab Merge Request (MR). It involes changes where a Ruby file is moved into or out of particular modules. This means that one or more module ... end
constructs are either added or removed around the entire class, resulting in a tabbing-width change on almost every line of the file. This makes reviewing the file in the MR quite difficult, as the reviewer will need to sift through the code diff and separate out actual logic changes from whitespace-only changes.
Solution
By appending ?w=1
to the end of the URL of the MR, Gitlab will ignore all lines that only feature a whitespace change in the code diff. This means that the only changes visible will be ones with a non-whitespace change, thus allowing the reviewer to focus in on actual logic changes and not waste time reading whitespace changes.
Time to poke Gitlab EE support on this issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/1393
Assignment on associations will bypass validation
Important gotcha that assignment to has_many associations will cause an immediate save even if callback validation fails.
u = User.last
u.accounts = []
u.save # returns false because this user cannot have blank accounts
u.reload.accounts # returns empty array
The gotcha here is that save is a no-op really. As soon as u.accounts=[]
is called, the data is saved immediately, bypassing validation.
Fixing ZDT Deploys with Monitoring-Driven Develop.
We were debugging a bug in our zero downtime deploy script. We tested the deploy using Chef, Kitchen and Vagrant. The bug was causing an error page to show for less than 3 seconds at the very end of the deploy.
We used Monitoring Driven Development to consistently reproduce the bug (the red phase), and to validate our fix (the green phase). Here were the steps:
Preparation:
kitchen login # ssh to the vagrant box
sudo tail -fn100 /var/log/nginx/go.access.log # to see the response codes from the server. If all responses show 200 code during the deploy, the deploy is working.
- Open other terminal window
kitchen login # ssh to the vagrant box
watch -n 1 "curl localhost" # make a request every 1 second
Then we followed this feedback loop
On the host computer:
- Make changes to the deploy recipe
kitchen converge # this will run our deploy
- Check the output of the logs to see the result of the changes
- Repeat the loop until bug is fixed
Creating multiple objects with Factory Girl
If you need to create more than one object from a factory, you can use the create_list
method to accomplish this.
` FactoryGirl.create_list(:user, 10, :supervisor) `
Will create 10 supervisor users with the supervisor trait.
Replacing num.times.map with Array.new(num)
Problem
I want to create an array containing objects created with an incrementing integer index parameter. For example, an array of hashes containing strings built off of the incrementing number.
Standard Solution
my_array = num.times.map do |index|
build_hash(index)
end
BUT…rubocop didn’t like this:
… C: Performance/TimesMap: Use Array.new with a block instead of .times.map
Improved Solution
The improved solution allows us to build the same array with less chained methods, thus improving readability:
my_array = Array.new(num) do |index|
build_hash(index)
end
pgcli — a great alternative to psql
Ever wished for a feature-rich, intuitive command-line postgresql client? Look no further! Presenting, pgcli — a result of pouring creativity into features rather than the name of the tool.
Supports:
- Smart autocompletion for almost anything. Even column names in the select query are properly autocompleted from the table you are selecting from;
- Multi-line query editing support;
- SQL Syntax highlighting;
- CLI parameters compatible with psql params. No need to relearn anything;
- Vi mode, allowing to edit multi-line queries using some of the vi bindings. There are also Emacs bindings too;
- Installation as easy as
pip install pgcli
(and if that fails, fix is as easy asxcode-select --install
(usually));
Grab your copy today!
Speeding Up Rake Command Completion
The speed of rake
command completion is determined by the startup time of your Rails app.
If your Rails app is slow to startup, the oh-my-zsh rake-fast plugin will make rake
command completion tolerable again.
Edit your zsh configuration file:
plugins=(... rake-fast ...)
After refreshing your shell instance issue the following command:
$ rake_refresh
Take a deep breath. Enjoy fast rake command completion.
OS X Command Line
I love being able to use Alfred as a kind of GUI command line…
..and I also like using the command line to get things done. I just discovered all sorts of new things that I can do from the command line from this GitHub repo.
For example, to show Wi-Fi Connection History:
defaults read \
/Library/Preferences/SystemConfiguration/com.apple.airport.preferences | \
grep LastConnected -A 7
Record File Handle Usage in OSX
lsof
is a helpful tool for looking at what files a process currently has open, however sometimes a process may only access a file for a second and lsof
may miss the moment.
For OSX we also have Instruments. This is included with XCode and is pretty straight forward to use:
- Open Instruments
- Select File Activity
- Select the process
- Hit Record
- Perform your action
- Stop Recording
You can also save the log for later analysis.
Mocha: Fail on any console error message
PROBLEM
I want to write a Mocha (JS) test that will fail if there is any warning printed to the console to fail. My use case to necessitate this requirement is that I want to test whether the correct prop type is passed to a React component. PropTypes
exists for this purpose, but would only print out a message to the console instead of failing.
SOLUTION
Use the following code, either at the beginning of your test file or a global helper such as specHelper.js
, to stub out the implementation of console.error
to throw an Error
and thus fail the test.
before(() => stub(console, "error", (warning) => {
throw new Error(warning);
}));
after(() => console.error.restore());
Reference: this gist.
webpack-merge is a thing and it is beautiful
Let’s say you want to redefine a loader from your base webpack config in your production webpack config. Try webpack-merge.smart
!
webpack.base.config.js
const config = {
entry: "./index.js",
module: {
rules: [
{
test: /\.css?$/,
exclude: /node_modules/,
use: [{
loader: "css-loader",
options: { sourceMap: true }, // set to true
}],
},
{
test: /\.css?$/,
include: /node_modules/,
use: ["css-loader"],
},
],
},
};
webpack.production.config.js
const merge = require("webpack-merge");
const baseConfig = require("webpack.base.config");
const productionConfig = {
module: {
rules: [{
test: /\.css?$/,
exclude: /node_modules/,
use: [{
loader: "css-loader",
options: { sourceMap: false }, // override to false
}],
}],
},
};
module.exports = merge.smart(baseConfig, productionConfig);
Result
const config = {
entry: "./index.js",
module: {
rules: [
{
test: /\.css?$/,
exclude: /node_modules/,
use: [{
loader: "css-loader",
options: { sourceMap: false }, // yep! it's false
}],
},
{
test: /\.css?$/, // but we didn't touch this rule
include: /node_modules/,
use: ["css-loader"],
},
], // and we didn't append anything either!
},
};
webpack-merge.smart
is aware of the shape of a webpack configuration and allows you to update only the rule you want.
Check it out: https://github.com/survivejs/webpack-merge#smart-merging
Capybara will skip invisible elements by default
While working on an acceptance test for a date range filter in GO, we were having an issue where Capybara couldn’t find an element on the page, even though we could verify it was there. Eventually we realized that the element had an opacity of 0, and that Capybara was passing it over.
To illustrate, imagine you have an element with the id #myElement
.
CSS:
#myElement { opacity: 0; }
And in your Rails spec:
page.find("#myElement");
The spec will fail, because #myElement
can’t be found.
Fortunately, there is a visible
option that can be set to false
so that Capybara doesn’t skip the element. So now, changing the line in the spec to:
page.find("#myElement", visible: false);
will cause it to pass.
Encrypt data using psql + keybase
To export any query to a CSV and send it to stdout
one can use:
psql -c "\copy (select version()) to stdout csv header"
So you can just replace select version()
with any query in the above command and the results will be dumped in your terminal screen. If you have any sensitive data that is not already encrypted you could pipe this results directly to keybase as in:
psql -c "\copy (select version()) to stdout csv header" | keybase encrypt diogob
Where diogob
is the recipient of your message (or your own username in case you want to store this file for future use).
Creating More than One Instance with FactoryGirl
In some test fixtures I need to create an array of instances . FactoryGirl provides the create_list
method for exactly this purpose.
To create four shipments on an outbound trailer:
FactoryGirl.create_list(:shipment, 4, outbound_trailer: trailer)
In the example above, create_list
returns an array containing the newly created shipments.
Global gitignore
To enable a global .gitignore for a specific user you can use the git config core.excludefiles as in:
git config --global core.excludesfile '~/.gitignore'
This will make the .gitignore in your home folder to be used in every git project in adition to local .gitignore files.
For more info read the git documentation on gitignore
SQL's WITH RECURSIVE Query
While optimizing calls to a recursive table, we found a neat SQL solution. It uses a common table expression as a working table to query against iteratively.
Here’s an example of using WITH RECURSIVE
with a modified nested set example of clothing categories that find all paths through the categories:
CREATE TEMPORARY TABLE categories (id INT, name text, parent_category_id INT);
INSERT INTO categories VALUES
(1, 'Clothing', null),
(2, 'Mens''s', 1),
(3, 'Women''s', 1),
(4, 'Suits', 2),
(5, 'Dresses', 3),
(6, 'Skirts', 3),
(7, 'Jackets', 4),
(8, 'Evening Gowns', 5);
WITH RECURSIVE category_hierarchies AS
(SELECT id, parent_category_id, name AS full_path
FROM categories
WHERE parent_category_id is NULL
UNION ALL
SELECT child_categories.id,
child_categories.parent_category_id,
parent_categories.full_path || ' -> ' || child_categories.name as full_path
FROM categories AS child_categories
INNER JOIN category_hierarchies AS parent_categories
ON child_categories.parent_category_id = parent_categories.id
)
SELECT full_path FROM category_hierarchies ORDER BY full_path;
Produces paths through all categories:
- Clothing
- Clothing -> Mens’s
- Clothing -> Mens’s -> Suits
- Clothing -> Mens’s -> Suits -> Jackets
- Clothing -> Women’s
- Clothing -> Women’s -> Dresses
- Clothing -> Women’s -> Dresses -> Evening Gowns
- Clothing -> Women’s -> Skirts
Read more about WITH RECURSIVE
queries
Run last command in BASh/ZSH (they're different)
To run the last executed command in BASH, execute the following:
!!
In ZSH, things are a little different. Using !!
will only expand the command into the shell prompt. You would have to press enter again to execute it. Rather, if you want to immediately execute the last command similar to BASH, use this:
r
If you prefer for ZSH behaviour to match that of BASH, then add setopt no_hist_verify
to your .zshrc file.
Serializing many value objects to database columns
While reading the IDDD book on serialization of value objects there is this description of an approach called “ORM and Many Values Serialized into a Single Column”. It’s good to note that some of the main objections to this approach are technology related and barely applicable in a world of Rails’ ActiveRecord + PostgreSQL.
The objections presented by the book are:
- Column width: It mentions that serializing to varchar fields will meet some limitations imposed by Oracle and MySQL implementations. In PostgreSQL, besides having composite types (e.g. json or array), the limit on any column is much higher (1GB).
- Must query: The book states that if the values must be queried this approach cannot be used. This is another limitation imposed by the underlying technology. Using PostgreSQL one can easily query composite values and even created indexes over them.
- Requires custom user type: This is not related to the database technology but is heavily biased towards hibernate. In Rails’ ActiveRecord the custom serializers require very little boilerplate and it offers out of the box support for json, array and range types.
Am I executing the correct executable?
Q: When I run a command (let’s say rails), which executable is it executing?
A:
> which rails
/Users/username/.rvm/gems/ruby-2.1.6/bin/rails
Q: Ah, I see which one it’s running. And it’s not the right one! Where are all the potential executables, given the current PATH?
A:
> where rails
/Users/username/.rvm/gems/ruby-2.1.6/bin/rails
/usr/bin/rails
Now I know whether it’s a PATH ordering issue, or whether it’s not included PATH at all.
Turn AWS tags into a useful data structure with jq
The JSON responses from the AWS API contain tags in a data structure like this:
"Tags": [
{
"Value": "consul-test-jf",
"Key": "Name"
},
{
"Value": "test-jf",
"Key": "consul-group"
},
{
"Value": "server",
"Key": "consul-role"
}
]
This structure is awkward to query with jq, but you can map it into a normal object like this:
jq '<path to Tags> | map({"key": .Key, "value": .Value}) | from_entries'
Which returns an object that looks like this:
{
"consul-role": "server",
"consul-group": "test-jf",
"Name": "consul-test-jf"
}
Comparing Version Strings in Ruby
While writing a Ruby script, I needed to check the the version of a binary dependancy. The --version
switch gets me the data, but how to compare to the required version?
The binary follows semver, so a quick and dirty attempt might be:
"1.4.2".gsub(".", "") >= "1.3.1".gsub(".", "")
# => true
Unfortunately, this is misleading: we are lexicographically comparing the strings and these strings happen to have the same length. Thus, "142"
comes after "131"
.
Testing that version "1.200.0"
is newer than "1.9.0"
will fail as "120"
comes before "190"
.
It would be straight-forward to write a small class to parse the string and compare the major, minor, and patch values. But, Ruby has a quick solution provided by RubyGems. Since Ruby 1.9, RubyGems has been included in Ruby’s standard library:
Gem::Version.new("1.200.1") >= Gem::Version.new("1.3.1")
# => true
Gem
also provides a way handle pessimistic constraints:
dependency = Gem::Dependency.new("", "~> 1.3.1")
dependency.match?("", "1.3.9")
# => true
dependency.match?("", "1.4.1")
# => false
Configuring a Rails app to redirect http to https
Problem
I have a Rails app on Heroku that is serving up a site on http and https. Google oAuth’s callback URL is for https, so attempting to log into the site from the http URL fails.
Solution
The intention was to serve up the site just from the https url, so the solution is to configure Rails to redirect all http traffic to https.
In config/production.rb
:
config.force_ssl = true
Resource: http://stackoverflow.com/questions/27377386/force-ssl-for-heroku-apps-running-in-eu-region
Decorator Pattern in Ruby with SimpleDelegator
The Decorator Pattern allows us to chain new behaviours to objects without modifying the underlying objects. It is an application of the Open/Closed Principle. This pattern is useful for example when we need to tack on logging, monitoring, and other non-functional requirements to objects.
In Java or C# this can be achieved using interfaces. In Ruby, we can use the SimpleDelegator
class to achieve this:
require "delegate"
class FooDecorator < SimpleDelegator
def bar
"This is a decorated #{__getobj__.bar}"
end
end
class Foo
def bar
"bar"
end
def fiz
"Fiz"
end
end
decorated = FooDecorator.new(Foo.new)
puts decorated.bar # outputs "This is a decorated bar"
puts decorated.fiz # outputs "Fiz"
double_decorated = FooDecorator.new(FooDecorator.new(Foo.new))
puts double_decorated.bar # outputs "This is a decorated This is a decorated bar"
Sources:
- http://howwedoapps.com/2014/10/03/simple-decorator-pattern-implementation-in-rails
- http://devblog.orgsync.com/2013/03/22/decorate-your-ruby-objects-like-a-boss/
Bundle Console
bundle console [GROUP]
runs Ruby console with bundled gems
Convenient Git Command to Discard Local Changes
In order to discard all local commits on a branch, that is, to make the local branch identical to the upstream of the branch, run:
git reset --hard @{u}
where @{u}
is the short form of @{upstream}
and denotes the upstream branch.
Non-Invasive Monitoring of Socket Traffic
Problem
I would like to diagnose failures to communicate with an external service over a network socket, without making modifications to the code or otherwise disturbing a production-like environment.
Solution
One writes to or reads from a socket by making a request to the kernel (a.k.a syscall). This requires the file descriptor (numerical identifier) of the socket and the message to be sent over the socket, or a buffer that will contain the next message read from the socket.
Using strace
(or dtruss
on MacOS), one can inspect the stream of syscalls issued to the kernel and the arguments for each syscall. First, find the ID of the process that will be communicating over the socket:
ryan@staging ~ $ ps ax | grep unicorn
99999 ? Sl 0:00 unicorn worker[0]
Then attach to the process with strace
:
ryan@staging ~ $ strace -p 99999
Process 99999 attached
[pid 99999] write(11, "Hello", 6) = 6
[pid 99999] read(11, 0xBAAAAAAD, 64) = -1 EAGAIN (Resource temporarily unavailable)
Here, a Hello
message was sent with a write
syscall over socket with file descriptor 11, though the read
syscall failed as the socket was temporarily blocked.
Passing all env. variables to a shell command
Some of the methods in the Kernel module allows you to pass environment variables to a shell command. So rather than doing:
system("RAILS_ENV=test rake do_stuff")
You can do
system({ "RAILS_ENV" => "test" }, "rake do_stuff")
This is particularly useful when we want to pass all environment variables on our current process.
system(ENV, "rake do_stuff")
Attach to Local Ruby Process with Debugger
RubyMine has a nice feature that allows you to debug a Rails app without restarting the server.
With the server running,
1) Run the “Attach to Local Process..” action from RubyMine
2) RubyMine will show a list of Ruby processes running. Pick the one running your server
3) Wait for RubyMine to connect to the process
4) Add a break point in RubyMine
5) Execute the action on the web application that hits that breakpoint
6) Execution will stop on that line. Now you can use all the nice tools the RubyMine debugger gives you.
I’m really exited with this new feature and I hope you are too. You can read more about it in here
Prefer sort_by to sort when providing a block
Prefer the sort_by
method over the sort
method whenever you provide a block to define the comparison.
Common form:
line_adds.sort { |x, y| x.elements["ItemRef/ListID"].text <=>
y.elements["ItemRef/ListID"].text }
Preferred form:
line_adds.sort_by { |x| x.elements["ItemRef/ListID"].text }
For small collections both techniques have similar performance profiles. When the sort key is something simple like an integer there is no performance benefit from sort_by
.
The performance difference is especially noticeable if the sort key is expensive to compute and/or you have a large collection to sort.
The algorithm that yields the performance benefit is known as the Schwartzian Transform.
React will conditionally batch calls to setState()
React tries to be smart and batch calls to setState() when its being called from a UI event context (e.g. button click). This has ramifications on code as your setState() call is no longer synchronous and accessing this.state
will actually refer to the old state.
E.g.
this.state = { hello: false };
...
onClick() {
this.setState({ hello: true });
console.log(this.state.hello); //<=== will print false instead of true
}
However, if the setState is in a context not from a UI event, setState becomes synchronous
this.state = { hello: false };
...
changeState() {
this.setState({ hello: true });
console.log(this.state.hello); //<=== will print true!
}
There’s more info here on the topic of batching setState calls: https://www.bennadel.com/blog/2893-setstate-state-mutation-operation-may-be-synchronous-in-reactjs.htm
Ruby print to replace contents on same line
In Ruby, the print
command can be used with the '\r'
(carriage return) character to bring the cursor back to the beginning of the printed line, so that the next print
call will replace the contents already outputted to that line. This is a very useful tool for printing status updates in a CLI script. For example:
print "#{index} done. Progress: %.2f%" % (index.to_f / items * 100).round(2) + "\r" if (index % 10) == 0
This will print and replace a line in STDOUT to report the status of a list of items being processed by a function, like so:
200 done. Progress: 15%
Typewriters still hold a lasting impact on modern-day computing!
Hotkey to switch control mode in Mac Screen Share
I use MacOS screen sharing to power pair programming sessions that I have in my development team. There are two modes for the navigator to use when observing the driver’s screen (assuming that the screen being shared is of the driver): Observe Mode to disallow taking control of the screen, or a self-explanatory Control Mode.
I like being in Observe Mode as the navigator so that I don’t mistakingly take control of the driver’s screen and start polluting the screen with accidental key strokes. But if I ever need to switch control, I would have to then make a mouse click on the correct icon. This gets annoying if I am observing in Full Screen mode (which is almost always). I would have to exit full screen mode first in order to switch to taking control.
SOLUTION: I can instead use the CMD-ALT-X key combination to quickly switch control mode :D
Why Git Uses (:) to Delete Remote Branch
It would appear that the colon in git push origin :<branch-to-delete>
is used exclusively to delete branches. But such is not the case.
The format for the refspec is*:
<source>:<destination>
This tells Git to push the source
branch to the destination
branch in remote. So if the source
is blank, we get a leading colon. This has the effect of deleting the destination
branch. Its like saying “push null pointer to destination”.
*You can learn more about the refspec in its entirety in this Stack Overflow
Reading Text File with Byte Order Mark Using Ruby
Ruby’s File.read()
can natively read a text file containing a byte order mark and strip it out:
text_without_bom = File.read("file.txt", encoding: "bom|utf-8")
Performance Metrics for Scripts Using Command Line
To quickly collect performance metrics for a script via command line:
- Start running the script. Make note of the process name that the script is running as (e.g. ruby)
- Create a script called
profiler.sh
with this content:ps aux | grep $1 | head -1 | awk '{print "CPU="$3 ", MEM="$4 ", RSS="$6}'
- Make the profiler executable:
chmod +x profiler.sh
- Execute the profiler in a watch session every minute:
watch -n 60 --no-title "./profiler.sh SCRIPT_IDENTIFIER | tee -a logfile"
. Where the script identifier is any text that we can use to grep for the process in theps aux
output. - After your script is done running or you have enough data points, observe the output in
logfile
.
NOTE: RSS is resident set size
ZDT Column Rename in a Distributed System
In order to deploy code to a highly available distributed system any two sequential versions of the code can be running at the same time. Therefore they need to be compatible.
- Add the new column, keep the columns in sync when updating.
- Migrate the data, start using the new column however fallback to the old column if the new column is blank, continue keeping the columns in sync.
- Remove all dependencies on the old column, only use the new column, do not sync them anymore.
- Drop the column.
When in Rails, Step #3 requires some special care as the column needs to be marked for removal:
module MarkColumnsForRemoval
def mark_columns_for_removal(*columns_marked_for_removal)
@columns_marked_for_removal = columns_marked_for_removal.map(&:to_s)
end
##
# Overrides ActiveRecord's list of the database columns in order to hide a column which we intend to delete
# This ensures that ActiveRecord does not try to read or write to the column
#
def columns
cols = super
cols.reject { |col| (@columns_marked_for_removal || []).include?(col.name.to_s) }
end
end
class SomeModel < ActiveRecord::Base
# Remove this as part of step 4 when dropping the old_column
extend MarkColumnsForRemoval
mark_columns_for_removal :old_column
end
A quick deep dive into 'rake gettext:find'
Problem
I am using Ruby Gettext to manage
translations. But today, when I ran rake gettext:find
to update my
PO files, none of them got updated.
Why??
The Investigation
After some digging, I noticed that Ruby Gettext defines one FileTask (a specific type of Rake task) per PO file, which delegates the work to GNU gettext.
FileTask looks at the timestamps of dependent files, and only executes the supplied block if any of the dependent files have a timestamp later than the file to update.
For example:
dependent_files = ["translations_template_file.pot"]
file "file_to_update" => dependent_files do
# update the file
end
Why gettext:find
was not doing anything
It turned out that gettext uses two FileTasks.
One to update the template:
files_needing_translations = ["file1.js", "file2.rb"]
file "translations_template_file.pot" => files_needing_translations do
# update the translations template file
end
and another to update the PO file:
file "en-US/translation_file.po" => ["translations_template_file.pot"] do
# update "en-US/translations.po"
end
The reason gettext:find
did not do anything was because none of the
files needing translation were updated, thus no PO files were updated.
Solution
> touch one_of_the_files_that_gettext_looks_at.js
> rake gettext:find
the .then(onSuccess, onError) anti-pattern
Before:
somePromise().then(
function onSuccess (res) {
// stuff happens, but oh no!
// an error is thrown in here!
},
function onError (err) {
// request-only error handler
}
);
After:
somePromise()
.then(function onSuccess (res) {
// stuff happens, but oh no!
// an error is thrown in here!
})
.catch(function onError (err) {
// yay! The error thrown in the function above
// can be handled here or rethrown to be handled elsewhere.
});
More details here.
Compounding expectations in Rspec and Chai
When I had multiple expectations on the same object in rspec, I would write the code like so:
expect(page).to have_content("Foo")
expect(page).to have_content("Bar")
expect(page).to have_content("Other Stuff")
You can save yourself some typing if you instead use compound expectations, which is basically the usage of the and
function after the previous expectation. Doing so will allow the previous code to be writted as such:
expect(page).to have_content("Foo")
.and have_content("Bar")
.and have_content("Other Stuff")
The same concept also exists in the Chai JavaScript testing library (documentation):
expect(page).to.contain("Foo")
.and.contain("Bar")
.and.contain("Other Stuff");
Add executable flags in git file
There is support in the git add
command to make a file tracked in your git repository executable. For example, let’s say you added a foo.sh
script to your repo but forgot to add the executable bit to its file permissions. You can now do this:
git add --chmod=+x foo.sh
One gotcha of this approach is that this will only change the permissions tracked by git, but not the actual permissions of the file on YOUR filesystem. You will still need to run chmod +x foo.sh
to modify your local permissions. However, your teammates should be able to pick up the permission changes from a git pull
.
Courtesy of http://stackoverflow.com/a/38285435/814576
ES2015 Arrow fns do not have the arguments object
const myFn = (/*unknown arity*/) => {
console.log(arguments); //EMPTY ARRAY!
};
function myFn(/*unknown arity*/) {
console.log(arguments); //returns what you expect!
}
My takeaway: only use arrow functions when they’re necessary, which actually isn’t that often! Plain old named JS functions are still powerful and if necessary can still easily be bound with .bind(this)
.
Related reading: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments
Matching array subset in Ruby
Problem:
How do you evaluate whether one array is a subset of another? For example, are the elements ` [a,c] included in
[a,b,c]`?
First attempt:
I was hoping to find something like ` Array.include?([…])`, but this only checks if the array includes the argument as one of its values.
Second attempt:
Another approach is to pass a block into ` Array.any?`
!arr1.any? { |e| !arr2.include?(e) }
But the double negation is rather indirect and doesn’t easily reveal the intent.
I considered extracting a method to name the functionality:
def subset?(arr1, arr2)
!arr1.any? { |e| !arr2.include?(e) }
end
But it’s still difficult to read, as it’s not clear whether arr1
is a subset of arr2
, or vice versa.
Final Solution:
The ` Enumerable module includes a
to_set method to convert the array to set, and
Set includes a
subset?` method.
arr1.to_set.subset?(arr2.to_set)
Technically, you need to require set.rb to get this method defined on Enumberable
:
require "set"
arr1.to_set.subset?(arr2.to_set)
But you get this require for free in Rails.
Add extra line to git commit message from CLI
You can add extra lines to your commit messages by adding an extra -m
flag to the git commit
flag. This is useful if you have extra information that you want captured in your commit, but you don’t want it in your commit message header. For example:
git commit -am "Updates the README with copyright information" -m "This conforms to requirements from Legal."
Will produce the following commit message:
Updates the README with copyright information
This conforms to requirements from Legal.
Now your commit message is split up into a header and a body. You can also add another -m
flag for a footer.
Rolling back Rails migrations
There are a bunch of ways to roll back migrations, so I figured I’d capture them in Q & A format.
Let’s say the following migration files exist:
> ls db/migrate
20160613172644_migration_1
20160614173819_migration_2
20160615142814_migration_3
20160615160123_migration_4
20160615174549_migration_5
Q: How do I roll back the last migration.
A: rake db:rollback
Q: How do I roll back the last 3 migrations?
A: rake db:rollback STEP=3
Q: How do I roll back a specific migration?
A: rake db:migrate:down VERSION=20160615142814
Details:
The timestamp comes from the filename: 20160615142814_migration_3
and… the one I learned today:
Q: How do I roll back all the migration past a certain version?
A: rake db:migrate VERSION=20160615142814
.
Details:
The above will keep the following:
20160613172644_migration_1
20160614173819_migration_2
20160615142814_migration_3
and roll back the following:
20160615160123_migration_4
20160615174549_migration_5
In other words, it will keep all the migrations upto and including the version you specified.
RSpec Matchers for Array Comparisons
Whenever you are matching arrays ask yourself two questions:
- Is order important?
- Am I matching a subset of the elements or all of the elements?
How I decide on a matcher:
- Choose between the
eq
andbe
matcher if order is important. - Choose the
include
matcher if you want to match on a subset of the elements. - Choose between the
match_array
andcontain_exactly
matcher if you want to match all elements (and order doesn’t matter).
Below is an example of an improvement to a previously intermittent test. I replaced the eq
matcher with the match_array
matcher because I wanted to match all location_ids
and order doesn’t matter.
expect(location_ids).to eq([location_2.id, location_3.id])
expect(location_ids).to match_array([location_2.id, location_3.id])
The root cause of the intermittent test was that the locations were being retrieved from the database with no order specified. From the PostreSQL documentation: If sorting is not chosen, the rows will be returned in an unspecified order. The actual order in that case will depend on the scan and join plan types and the order on disk, but it must not be relied on.
Retrieving the IDs for a Model
Prefer the ids
method to map(&:id)
when you want to retrieve an array of model IDs.
Example
receipt.receive_orders.ids
receipt.receive_orders.map(&:id)
In the example above, using ids
avoids fetching the receive orders from the database.
Rails Source
def ids
pluck primary_key
end
zsh-autosuggestions
Fish-like fast/unobtrusive autosuggestions for zsh.
I followed the installation instructions for Oh My Zsh and works for me.
My command line life is so much sweeter.
How to see invisible text in iTerm2
Yesterday, I tried to run ‘npm test’ for a new project and the text was invisible (i.e. the same color as the background color of my chosen color scheme for iTerm2). You can find a long discussion about this problem here: https://github.com/altercation/solarized/issues/220
Buried in this discussion was the solution: iTerm2 -> Preferences -> Profiles -> Colors -> Minimum contrast -> Move slider about a third of the way
Testing an Independent Mixin With RSpec
Objective: write a spec for the Inventory::Query
mixin.
Note: the mixin is independent of the including class as it does not depend on any instance variables or instance methods.
Original Approach
class InventoryQueryTest
include Inventory::Query
end
subject(:inventory_query) { InventoryQueryTest.new }
Preferred Approach
subject(:inventory_query) { (Class.new { include Inventory::Query }).new }
Advantage
Simpler and avoids polluting the global namespace with a test class.
NPM: List available custom scripts in the CLI
If you are working in the CLI on a project that uses NPM and you want to know what what custom scripts are available to you, without need to open and scroll through package.json
, just simply execute:
npm run
and all your custom scripts will be outputed to the screen.
Toggle Console Tab From Chrome Inspect Tools
If you have the Inspect Tools open on your Google Chrome browser, you can toggle a Console tab to appear at the bottom of the Inspect pane by pressing Escape on your keyboard. This is very useful if you need to have another Inspect tab open at the same time as the Console, such as Source or React Dev Tools.
Prettify JSON in the browser console
Problem
I want to check the shape of data for an XHR request in Chrome. So I go to the Network panel in the inspector.
When I check the response tab, I see the following:
[{"id":43,"child_node":{"active":true,"name":"name","created_at":"2015-05-25T16:55:09.600-04:00"},"notes":null}]
Not very inspectable.
When I check the preview tab, it’s a fancy preview mode, with all the nodes folded:
v [{id: 43,…}, {id: 44,…}, {id: 46,…}, {id: 45,…}]
> 0: {id: 43,…}
> 1: {id: 44,…}
> 2: {id: 46,…}
> 3: {id: 45,…}
Not easy to check the shape of the data either.
Solution
JSON.stringify
to the rescue!
function prettifyJson(json) {
console.log(JSON.stringify(
json, // copied from Response tab
undefined, // ignore this argument (or read link below)
2 // spaces to indent
));
};
Paste the above into the Chrome inspector.
Then copy the response in the response tab, and call the function:
>> prettifyJson([{"id":43,"child_node":{"active":true,"name":"name","created_at":"2015-05-25T16:55:09.600-04:00"},"notes":null}])
Output:
[
{
"id": 43,
"child_node": {
"active": true,
"name": "name",
"created_at": "2015-05-25T16:55:09.600-04:00"
},
"notes": null
}
]
// Tada!!
Resource:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
RubyMine Highlight for Multi-cursor Drag-and-drop
To create a Multi-cursor in RubyMine with your mouse, hold Alt while dragging your mouse up/down. This is especially useful if you want to adjust tabbing or add some extra characters on consecutive lines.
Using WIP acceptance specs
Context
I usually follow the following approaching when working on a story:
- Write a failing acceptance spec.
- Do a spike to validate the proposed solution. Get the spike to pass.
- Capture learnings, and blow away the spike changes.
- Properly TDD away at the solution.
One annoyance with this approach was:
What do I do with the failing acceptance spec?
I usually try not to commit failing specs, since that makes git bisect
less useful when I’m trying to see what broke it.
Solution
RSpec tags to the rescue.
Configure your specs to ignore wip specs by default:
RSpec.configure do |c|
c.filter_run_excluding wip: true
end
Write a WIP spec:
it 'tests my yet-to-be-added feature', :wip do
"my test"
end
Run the spec:
rspec my_acceptance_spec.rb --tag=wip
The acceptance spec can be committed, because it won’t run as part of your regular test suite.
Once the story is done, make sure you remove the :wip flag!
Rails assignment operation implicitly updates DB
In Rails, you may fall into a trap where simply assigning a value to an ActiveRecord object’s properties may cause a DB write immediately.
This will occur implicitly without callingobject.save()
!
What’s vulnerable? It appears that ActiveRecord objects that expose a property via association are vulnerable to this quirk. This won’t happen for properties that have no association.
For example, given the following:
class MyClass < ActiveRecord::Base
` has_many :children`
` attr_accessor :property_name`
end
….
obj = MyClass.find(1)
obj.children = [child_one, child_two, child_three] <=== this will write to the DB immediately!
obj.property_name = 'value' <=== this is in memory only, the DB has not been updated
obj.save <=== property_name is updated in the DB now
This may cause issues if your save implies validations and the validations fail. In this case, the associated property was updated in the DB but the other properties were not because of the validation failure.
Yikes!
[GIT] Change capitalization of file
HOW DO I CHANGE THE NAME OF A FILE UNDER GIT CONTROL WHERE NOTHING CHANGES EXCEPT THE CAPITALIZATION OF THE LETTERS?
For example, let’s say that you had a file called myfile.js
and you wanted to rename it to MyFile.js
. This change would not be recognized in git status
and therefore cannot be committed because none of the characters actually changed. It appears that git treats files in a ignores-case way when scanning for changes. Whereas, if I added or removed any of the characters in that name, ie MyFile1.js
, then git would recognize the rename.
SOLUTION
As per this Stackoverflow post, you can still commit this filename capitalization change using a git mv
command. So in this example, we would want to execute this:
git mv myfile.js MyFile.js
RubyMine group search by Test and Production code
When I do code searches in RubyMine, I sometimes want to only see non-test code for various reasons, such as knowing how often a particular method is used in our code base to judge adoption level. Normally, I would have to select each directory and run a code search one at a time, or search all directories at once and carefully skip over all test code while scrolling through the list. In a Rails app, directories that contain non-test source code could include app/
, domain/
, lib/
and even more.
There is a better way! The RubyMine Search tab has a toggle that will let you group source code search by Production and Test code. All you have to do is press this toggle and voila!
A little thing about .to_str
Playing with Ruby’s === today and found some knowledge that’s share-worthy. I noticed in ruby docs for “string ===” a reference to “.to_str” and decided to investigate.
Nothing too exciting here, but its an important point of reference.
> hello = "hello"
> goodbye = "goodbye"
> hello === hello #=> true
> hello === goodbye #=> false
This is also what would usually be expected. Hang in there…
> string = "string"
> object = Object.new
> string + object #=> TypeError no implicit conversion
Here’s where things get funky.
class SomeObjectWithToStr
def to_str
"is now a string"
end
end
> string = "string"
> object = SomeObjectWithToStr.new
> string + object #=> "string is now a string"
> "string is now a string" === "string" + object #=> true
Hunh? Why did that work?
TIL that .to_str is the default method call when operators force a conversion to a string. You’ll likely have to define it yourself. Also note that the object type on the left is what the object type on the right will try to convert into.
Do you know of any Objects that come with pre-defined .to_str methods?
Temporarily skip an RSpec example group
I knew about prefixing an RSpec example with x
to skip it. I just found out that a describe
or context
example group can also be temporarily skipped using xdescribe
and xcontext
.
How did I find out? RTSL
Special bonus: the focus effect works similarly: fit
, fdescribe
, and fcontext
.
Usage of $0 in the Chrome dev tools
In the Chrome dev console, typing $0
evaluates to the last selected HTML element (by clicking on it under the ‘Elements’ tab). $1
is the second last selected, up to $4
- and despite the $
this works independently of jQuery.
https://developer.chrome.com/devtools/docs/commandline-api#0-4
validates_presence_of won't work with booleans
If you want to validate that a value for a particular boolean field exists (using ActiveRecord instead of null constraints from you DB), then you cannot use validates_presence_of
. This is due to the way that the blank?
works on an object with the value false
. Instead, you will need to use this for your validation:
validates_inclusion_of :field_name, :in => [true, false]
SEE:
http://stackoverflow.com/questions/2883823/why-does-false-invalidate-validates-presence-of http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_presence_of
Database Column "type" is reserved in Rails
I made a database column called “type”. It contained a string. It was bound to Object. Everything was cool.
I wanted to create my object. But I kept getting this error.
object = Object.create(food: "P&L Burger", name: "The Matty", type: "Burgers")
**************************************
Invalid single-table inheritance type: 1 is not a subclass of Object
TIL that Rails has some reserved keywords for database column names. It just so happens that the column name “type” is reserved. There are also other reserved column names.
See: Active Record Basics: 2.2 Schema Conventions
The “type” column is reserved for single-table-inheritance where the Ruby Object name would be stored in the “type” column and would be accessible through object.type #=> Object
Learning lessons the hard way: git clean
I had a huge list of superfluous changes in git that I wanted to clean up. Most of them were additions so doing a git checkout
wasn’t going to work.
I followed some instructions online and ran: git clean -r -d -x
The trojan horse of this command is the -x
flag which will delete all files in your .gitignore!
This led to a half day of setting up my dev environment again to recover all the lost environmental configurations deleted by this command.
Stay tuned for tomorrow’s lesson: Adventures with rm -rf /
In RubyMine, shift a line or a whole block of code
RubyMine has a key-mapping for grabbing lines of text in the editor, from cursor focus. If you have your cursor focused anywhere in a line of code you can shift it up or down with the following [default] key bindings:
CMD + SHIFT + Up Arrow || Down Arrow
Supercharge your grabbing
If you want to move an entire block of code without having to highlight the entire block, put your cursor on the definition of the statement and RubyMine will shift the entire block for you.
This can work on blocks defined by module; class; def; if; find more use cases and share because I definitely haven’t uncovered them all yet!
Happy Shifting!
Fix Mac RubyMine Floating Window Bug
PROBLEM
On RubyMine in Mac, I want to have my RubyMine IDE in one window but have the Run display in Floating Mode appear in my secondary monitor. The issue, though, is that after I have moved the Run display into my secondary monitor, lose focus to another window, then click back into the Run display, the will suddenly JUMP to the same window as my main RubyMine IDE.
SOLUTION
The problem appears to be a conflict with a setting in Mac’s Mission Control. You will need to deselect the “Displays have separate spaces” option in the Mission Control preferences screen, as described here.
#thanksapple
Enable Mac Keyboard Number Pad in iTerm
If you Mac keyboard’s number pad is not working in iTerm, then follow the steps outlined here: http://superuser.com/a/565179/175226
Looks like the answer is to go into Preferences->Profiles->Keys
and load preset of: xterm with numeric keypad.
You will lose any default key mappings that you already set in your iTerm profile already, so you may want to do this in a brand new profile so you can bring over your old mappings to the new profile and not outright lose them like I just did.
Re-run only failed tests through Rspec
In cases where large refactoring is taking place and there are multiple tests across multiple files failing, there’s an easy shortcut built into Rspec that allows you to re-run your specs but only the ones that failed.
The command
———————
rspec –only-failures
This allows for a tighter feedback loop to get failing tests green.
Setup
———-
This functionality doesn’t come for free and some simple, but required, setup is necessary. Details about what’s required can be [found here.] (https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures)
The quick rundown is your Rspec configuration needs some extra flags set:
RSpec.configure do |c|
c.example_status_persistence_file_path = "failing_specs.txt"
c.run_all_when_everything_filtered = true
end
This is required so Rspec will output any failing specs to a file and then read from it when --only-failures
is specified.
Permanently using this, it’s also a great idea to add it to your .gitignore
file.
Rails console options to make your life better
Often when learning or testing out an implementation in planning, entering into a REPL to get some feedback and play with something more physical is desirable.
Here are some tips to improve your rails console workflow:
Specify the environment you wish to use
Maybe you want to try and reproduce an error in production during your test runs. Maybe you want to seed the database for your development server before having created a seed file. Maybe you’re just feeling wild for the day and want to switch things up.
Rails gives you the option to select the environment for the console session:
>rails c --environment=test [test/development/production/...other...]
>rails c test # as a shorthand
Note: The default environment is set to development
Sandbox so your DB entries do not persist</h3> Often I find myself wanting to just play around with the current build, knowingly wanting to throw away the changes after. Sandboxing is a great way to do this while reducing your cleanup workflow. ``` >rails c --sandbox >rails c -s ``` This saves you from having to write out the following to return to a seeded state: ``` >rake db:reset RAILS_ENV=[environment] ```
Pinch to zoom in Mac RubyMine
PROBLEM
I am presenting some source code during a meeting on RubyMine on my Mac machine. When I plug into the projector, my display resolution becomes quite high, so all text on the projector become very small. Using “CMD +” does not zoom in.
SOLUTION
Instead, you will need to pinch the Mac’s touchpad with two fingers to control the zoom. Pinch inwards for zoom-out and outwards for zoom-in. You will need to do this on every code tab you have open.
Thanks for the tip, Sean Kirby.
What's a "twiddle-wakka"?
I’m proud to say that I now know what a “twiddle-wakka” is. It is the notation ~>
that we use in our Ruby-flavoured semver notation in Gemfile. Specifically, it means that the accepted version must be at the same level of the specified version. All sub-levels below the next increment of the current level are accepted. For example, ~> 2.0
means 2.0 <= VERSION < 2.1
, while ~> 2.0.1
means 2.0.1 <= VERSION < 2.0.2
.
Reference: http://guides.rubygems.org/patterns/
But seriously, now I know what a “twiddle-wakka” is. :D
Get Overwritten/Discarded Commits using reflog
git reflog
shows commits including the overwritten/discarded ones. This is useful in case of accidents such as unwanted git commit --amend
and git reset
.
Source
https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog
Extra
Use
git reflog --date=iso
to include dates.
Rails 4 Strong Parameters Gotcha: Array in Params
When using strong parameters in Rails 4, any non-scalar parameters must be permitted using a special syntax. The following example is for when you are passing in an array of scalar values in a request parameter (and you are using Rails 4 Strong Parameters to whitelist the parameter).
Firstly, note that the following will not work (i.e. the spec will fail):
# routes.rb
post '/thing/create' => 'thing#create'
# thing_controller_spec.rb
RSpec.describe ThingController, type: :controller do
example do
post :create, things: [1, 2, 3]
expect(response.body).to eq('1,2,3')
end
end
# thing_controller.rb
class ThingController < ApplicationController
def create
permitted_params = params.permit(:things)
render inline: permitted_params[:things].join(',')
end
end
Why does it fail? Rails is expecting a scalar value to be passed in the :things
parameter. However, we pass in an array, so Rails silently removes the parameter, even though it is included in the call to params.permit
.
In order to make the spec pass, we update the implementation as follows:
# thing_controller.rb
class ThingController < ApplicationController
def create
permitted_params = params.permit(things: [])
render inline: permitted_params[:things].join(',')
end
end
For more info about strong parameters, especially in regards to how to permit non-scalar and nested parameters, please refer to: https://github.com/rails/strong_parameters#permitted-scalar-values.
Enhancing rake tasks
Problem
I have a rake task, and I want to make it do something before and after it’s done.
task :a_task do
puts "task"
end
task :setup_task do
puts "setup"
end
task :run_after do
puts "after"
end
What are my options?
Solution
For pre-req tasks, this is what is often done:
task :a_task => [:setup_task] do
puts "task"
end
task :setup_task do
puts "setup"
end
> rake a_task
setup
task
However, this requires modifying the existing task. This might not even be an option for rake tasks from 3rd party gems. We can do better: Enhance the task!
task :a_task do
puts "task"
end
task :setup_task do
puts "setup"
end
Rake::Task[:a_task].enhance [:setup_task]
> rake a_task
setup
task
To run a task (or any code for that matter) after a rake task:
task :a_task do
puts "task"
end
task :run_after do
puts "after"
end
Rake::Task["a_task"].enhance do
Rake::Task["run_after"].invoke
end
> rake a_task
task
after
Source: http://www.dan-manges.com/blog/modifying-rake-tasks
Expect to Receive and Call to Original
In integration specs, it is preferable to call the original method when setting up an expectation on an object to receive an invocation of that method. This way, the method isn’t stubbed out but instead will still be invoked. Any downstream effects of calling that method won’t be hidden.
class Calculator
def self.add(x, y)
x + y
end
end
Should be tested like this:
require 'calculator'
RSpec.describe "and_call_original" do
it "responds as it normally would" do
expect(Calculator).to receive(:add).and_call_original
expect(Calculator.add(2, 3)).to eq(5) # any bugs inside of #add won't be hidden
end
end
This code example is taken from: Relish - Calling the original implementation
Share a TTY under Linux
From: https://www.linux.com/learn/using-screen-remote-interaction
-
Set the screen binary (/usr/bin/screen) setuid root. By default, screen is installed with the setuid bit turned off, as this is a potential security hole.
-
The teacher starts screen in a local xterm, for example via screen -S SessionName. The -S switch gives the session a name, which makes multiple screen sessions easier to manage.
-
The student uses SSH to connect to the teacher’s computer.
-
The teacher then has to allow multiuser access in the screen session via the command Ctrl-a :multiuser on (all screen commands start with the screen escape sequence, Ctrl-a).
-
Next the teacher grants permission to the student user to access the screen session with Ctrl-a :acladd student where student is the student login ID.
The student can now connect to the teacher’s screen session. The syntax to connect to another user’s screen session is screen -x username/session.
Unicode Entry on Mac OSX
If you have the code point of a Unicode character, it is possible to enter these characters into (almost) any program on Mac OSX, by first jumping through a few hoops:
- Open Language & Region.
- At the bottom right, open Keyboard Preferences…
- Click the plus sign at the bottom left to add a new Input Source.
- Under the Others category, select the Unicode Hex Input source.
- Check the Show Input menu in menu bar option.
You should now see a country flag in your menu bar, which will allow you to switch between different Input Sources (e.g. Canadian English, U.S, Unicode Hex Input). Whenever you want to enter Unicode characters, switch to the Unicode Hex Input source.
Now, you can hold down ⌥ (Option/Alt) and enter your code point to type Unicode characters. For instance, the ⌥ character has code point 2325 and can be entered by holding Option and entering “2325”.
Disabling emdash substitutions in OSX apps
Problem
I use the slack app on my Mac, but it keeps replacing double dashes with an emdash.
e.g. –stat becomes —stat
Solution
In the slack app (and many other apps I presume?), right-click the field that has the problem, and turn off this option:
Substitutions -> Smart Dashes
Diffing a topic branch against the base branch
I often want to check all the changes made in my branch, relative to the base branch. Let’s say the base branch is master.
Most of the time, I use plain ol’ git diff
.
git diff master
git diff master --name-only # only list the changed files
However, git diff master
doesn’t always work. For example, if I pulled the latest changes in master, and haven’t rebased my branch, then git diff master
will show all kinds of changes I didn’t make.
So what is a dev to do?
git merge-base
to the rescue!
Here’s the description from git help merge-base
:
Find as good common ancestors as possible for a merge
The following gives me a good commit to compare against:
> git merge-base master HEAD
0783e77e5ca810e36fc7080753ac62526c09d0e4
Therefore, I can check all my changes using:
git diff `git merge-base master HEAD`
zsh function:
gdb() {
git diff `git merge-base master HEAD` $@
}
Git Cherry-Pick A Merge Commit
PROBLEM
I picked up work on a topic branch that has a WIP commit. I reset the branch, fix a few lines, then committed. I noticed now that I’m 1 Ahead and 1 Behind on my branch. I should do a force push….but I forgot to! Instead, I pulled and thus created a merge commit. Ruh roh!
WIP
/ \
A --- B --- C --- D --- M --- E --- F
Not only will this merge commit (empty, by the way) make our overall git history look ugly, it is also going to make rebasing off master very difficult, since we will have to resolve a conflict for all future commits (E and F). I want to keep my topic branch flat.
SOLUTION
You can escape this mess via a series of git cherry picks. The key part of this is how we applied the cherry-pick on merge commit F. We need to specify which “parent” to base the commit off of.
git checkout -b new_branch
git cherry-pick A
git cherry-pick B
git cherry-pick C
git cherry-pick D
git cherry-pick M -m 1
git cherry-pick E
git cherry-pick F
Open a Mingle ticket via Alfred
Open Alfred Preferences -> Features -> Web Search -> Add Custom Search
- Search URL: https://mingle.hq.nulogy.com/projects/packmanager/cards/{query}
- Title: Mingle
- Keyword: mingle
Usage: Open Alfred search, type mingle 9800
iTerm2 Window Arrangements
Motivation
Over the course of development on a project, there are many common jobs that one may run on a daily basis, such as:
- Starting a Rails app and watching a log tail
- Running a Zeus server and monitoring its status
- Monitoring RSpec output
- Keeping an IRB session open for quick experiments
I like to have a consistent workspace and layout that I can assume is readily available, as opposed to hunting down multiple terminal windows on my desktop. iTerm2 happens to provide a built-in mechanism for preserving workspaces and layouts.
Solution
Once you have all of your iTerm2 panes, windows, and tabs arranged to your liking, you can hit ⌘⇧s (Command-Shift-S) to Save and name your arrangement.
The next time you start iTerm2, you can Restore your saved layout by pressing ⌘⇧r (Command-Shift-R).
Show definition of a method at runtime in Ruby
Many people know about method(:foo).source_location
to find where a method is defined at runtime. I just found a better way by using pry.
From the pry console, run:
[8] pry(main)> show-source Bar.scoped.where
From: /Users/arturo/.rvm/gems/ruby-2.2.6/gems/activerecord-3.2.22.1/lib/active_record/relation/query_methods.rb @ line 132:
Owner: ActiveRecord::QueryMethods
Visibility: public
Number of lines: 7
def where(opts, *rest)
return self if opts.blank?
relation = clone
relation.where_values += build_where(opts, rest)
relation
end
Happy Hacking!
Quickly find the git commit that broke a test
Git bisect is a very cool tool that automate a binary search for you to find the first “bad” commit. Here is an example on how to find a commit that broke a test:
git bisect start
git bisect good <good_sha> # <good_sha> is any commit where the test is passing
git bisect bad <bad_sha> # <bad_sha> is any commit where the test is failing
git bisect run zeus rspec <broken test> # remove zeus if you don't use it
Git bisect will perform a binary search and run the test on every step. It uses rspec exit status to know if the commit is “good” or “bad” (0 exit status means “good”, otherwise it’s “bad”). When it’s done it will print the first bad commit:
a5cf29ac1dd64e5ce05336f28aa0ffc17e57fc10 is the first bad commit
commit a5cf29ac1dd64e5ce05336f28aa0ffc17e57fc10
Author: Arturo Pie <example@example.com>
Date: Fri Apr 1 08:55:31 2016 -0400
This is the commit message
:040000 040000 b2399ed1361548a743d95aa6aa95e42096f5ffd3 b500421bbfb9bb3dfebee1e45ff2197a7f32a43e M app
bisect run success
When you are done debugging, run git bisect reset
to end the bisect.
Happy Hacking!
Which Javascript Shell?
When it comes to Javascript Shells, there’s a long list to choose from, but typically, when I want to play with Javascript, the easiest way is to simply open up a console in Chrome.
Recently, I’ve switched over to using SpiderMonkey’s Javascript shell because it allows me to execute a JS file and then drop into the shell.
Installation:
$ brew install spidermonkey
Vanilla Use Case:
Open up a shell with js
command:
$ js
js> var obj = {a: 1};
js> obj;
({a:1})
js>
How to execute a file and then drop into the shell:
Given a file example.js
with the following contents:
var a = 42;
Execute the file (-f
) and continue in interactive mode (-i
):
$ js -f example.js -i
js> a;
42
Check out the docs for a full list of options.
Diffing code snippets between large files
Sometimes I like to compare and contrast differences between sections of large files that exhibit textual similarity.
Suppose I want to compare lines 100-200 from FileA.txt
with lines 300-400 from FileB.txt
. The following can be accomplished from the command line as follows:
diff <(sed -n '100,200p' /path/to/FileA.txt) <(sed -n '300,400p' /path/to/FileB.txt)
You can substitute diff
with any program of your choice (try diffuse, meld, or vimdiff).
Where Does That git Setting Come From?
Yesterday git config
learnt a new --show-origin
option to indicate where configuration values come from.
$ git config --show-origin user.email
Note: available in the 2.8.0 release.
Inheritance does not affect method visibility
Contrary to visibility conventions in other languages such as Java, Ruby methods defined under a private
block in a class definition are still accessible by that class’ children:
class Foo
private
def private_method!
p "Hello world!"
end
end
class Bar < Foo
def uses_private_method
private_method!
end
end
b = Bar.new
b.uses_private_method # => "Hello world!"
This is because the private
keyword in Ruby has nothing to do with inheritance;
declaring a method as private
only adds the restriction that it may not be invoked
with an explicit receiver, as illustrated below:
class Quux < Foo
def explicit_receiver
self.private_method!
end
def implicit_receiver
private_method!
end
end
q = Quux.new
q.explicit_receiver # => NoMethodError: private method `private_method!' called for #<Quux:0x007fee689e0ff8>
q.implicit_receiver # => "Hello world!"
ActiveRecord #count versus #length
Let’s say you have an ActiveRecord model with a has_many
association. Ever wonder why you receive different results from #count
and #length
after you append to that has_many collection? Consider this rough example where Parent
and Kid
are ActiveRecords and Parent
will has_many :kids
:
parent = Parent.create!
parent.kids.create! name: 'Evan'
puts "Current length is #{parent.kids.length}"
puts "Current count is #{parent.kids.count}"
The output will be:
Current length is 0
Current count is 1
The difference in results appear to be happening because of how length()
and count()
compute their results. length()
is only considering what is loaded into heap memory (“cached”), while count()
will actually check what is loaded into the DB.
Here’s a great blog post about the difference between the two methods, as well as size()
.
Fetch: two approaches for setting a default value
When using #fetch
to assign a default value, the default can be passed either as an argument or as a block.
What are the implications for choosing one approach over the other?
# Option 1: block
setting = settings.fetch('key') { default_setting }
#Option 2: argument
setting = settings.fetch('key', default_setting)
When the default value is passed as a block, it is only evaluated when needed (lazy evaluation).
The argument approach could lead to serious performance issues if the default is an expensive operation.
Running past commands from history
There are many ways to search/recall previous commands from the command line but I find the combination of history
and !<history_id>
to be quite useful, especially when you don’t remember the command you ran. For example:
Show me my previous commands:
> history
513 git stash pop
514 rspec spec/some_spec.rb
517 git diff
518 git add -p
Re-run the spec command in 514
> !514
Mass replace and copy by file extension
Problem
I just cloned a Rails project.
There are a bunch of files with the .yml.sample
extension under the config directory.
I’d like to copy all those files without the .sample
prefix.
Solution
zsh functions to the rescue!
Add this to your .zshrc
file:
autoload -U zmv
Then run:
zmv -C 'config/(*.yml).sample' 'config/$1'
By default, zmv will move files.
-C
puts it in copy mode.
For more info:
man zshcontrib
Oh-My-Zsh Plugins List
I feel like I just discovered the Internet when I look at this page:
https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins
Consider using the #public_send method
Prefer the #public_send method to the #send method.
result_date = date.public_send(operation, delta)
In the example above the first parameter to the #public_send method is either “+” or “-“.
Stashing untracked files in Git
Scenario
I have created new files in the process of spiking an implementation, and want to stash them to prevent “Untracked files” from appearing in git status
.
Solution
Use git stash save -u
.
How to view changes from only a particular branch
git log master..
, assuming your branch was based off of master. If based off of something else, use that branch name (ie, git log production..
)
Courtesy of http://stackoverflow.com/a/4649377/814576
Loading Data into ELK
Scenario
I want to load data in to Elasticsearch
Solution
Modify this script.
require "elasticsearch"
require "typhoeus"
require "typhoeus/adapters/faraday"
client = Elasticsearch::Client.new(host: "localhost:9200")
scope = BackgroundTask
.where("created_at > '2015-01-01'")
.where("created_at < '2016-01-01'")
count_so_far = 0
puts "Processing #{scope.count} records"
scope
.find_in_batches do |tasks|
puts "#{count_so_far} of #{scope.count}"
count_so_far += tasks.count
task_array = tasks.map do |task|
{
create: {
_index: "background_tasks",
_id: task.id,
_type: "task",
data: {
task_type: task.type,
created_at: task.created_at,
waiting_time: task.queued_at - task.created_at,
queued_time: task.run_at - task.queued_at,
processing_time: task.completed_at - task.run_at
},
}
}
end
client.bulk(body: task_array)
end
Find all commits by a particular author
Do you want to know quickly about all the commits that a single author has pushed? Easy, just run a git log
command with the --author
` flag, like this:
git log --author="evanb@nulogy.com"
Problems with Reusing Ruby Standard Class Names
You might want to think twice before making a class that reuses the same name of a Ruby Standard Library class. If undetected, you will get strange hard-to-debug behaviour in your app. Let’s explore further with this Ruby file:
module Utils
module String
def self.some_useful_method
# ...
end
end
end
module Utils
module Foo
def self.do_stuff(string)
raise "Argument '#{string}' is not a string" unless string.is_a?(String)
# ...
end
end
end
Utils::Foo.do_stuff("Hello World")
Okay, so “Hello World” is a String. And a String is a String, no questions asked. Right? Well…not quite.
RuntimeError: Argument 'Hello World' is not a string
Since Utils::String
gets loaded by Ruby, all references to the String
constant from code inside the Utils
module will resolve to Utils::String
. This example may seem simple and obvious, but imagine if these two classes were in separate files, even separate libraries. How would it feel like if you keep getting "string".is_a? String => false
in your debugging sessions?
MORAL OF THE STORY: It probably isn’t a good idea to reuse class names from the Ruby Standard Library. Naming the first module to Utils::StringUtils
is likely a better idea.
Stashing only some of your files
If you want to keep some files and stash the others, use “git add” to add the files you want to keep, and type
git stash --keep-index
Add a message to git stash
Problem:
You want to stash a number of patches and add a message to describe what each includes.
Context:
Using git stash
without arguments stacks your code changes on the top of a the stash stack, and adds a default message: “WIP on branchname …”. If you stash multiple patches, you may find it difficult to recall what each stash includes:
$ git stash list
stash@{0}: WIP on 1234_add_new_feature: 1a2b3c4 #1234 - updates new feature template
stash@{1}: WIP on 1234_add_new_feature: 1a2b3c4 #1234 - updates new feature template
Solution:
You can add a message to the the stash by using the save
argument:
$ git stash save "refactors how the UI elements are rendered"
$ git stash list
stash@{0}: On 1234_add_new_feature: refactors how the UI elements are rendered
stash@{1}: WIP on 1234_add_new_feature: 1a2b3c4 #1234 - updates new feature template
stash@{2}: WIP on 1234_add_new_feature: 1a2b3c4 #1234 - updates new feature template
This workflow is especially useful when you’re stashing commits while spiking.
Capybara !has_content? vs has_no_content?
Let’s say you’re using RSpec and Capybara.
What’s the difference between the following:
expect(page).to_not have_content("not on page")
and
expect(page).to have_no_content("not on page")
Assuming that the content “not on page” is expected to disappear from the page:
The first one will wait until the Capybara default wait time is over (2 seconds), then pass the assertion. The second one will pass as soon as “not on page” disappears from the page.
The reason the first one waits is because has_content? waits for the content to appear. When the timeout expires, it returns false, which passes the to_not assertion.
Never use to_not have_content
or !has_content
in Capybara.
Specify Multiple Examples by Line Number to RSpec
I can specify multiple examples as a colon-delimited list of line numbers to RSpec:
ryandv $ rspec my_spec.rb:2:8
Run options: include {:locations=>{"./my_spec.rb"=>[2, 8]}}
..
Finished in 0.00052 seconds (files took 0.08873 seconds to load)
2 examples, 0 failures
Using git stash for spiking
Often, I do a small spike to see if a certain code change makes sense. When it’s time to actually make code changes, I want to start from scratch to do proper TDD. However, sometimes I want to reference the code I spiked out to guide me.
One option is to stash away the spike, and reference it using:
git stash show -v
This will show you the contents of the most recently stashed code.
If it’s not the most recently stashed change, you can specify the stashed change you want to see:
git stash list
git stash show -v @{2}
RSpec option to quickly fix transient failures
Problem:
How do I quickly find the smallest set of tests to reproduce a transient RSpec failure?
Context:
Sometimes, we find non-deterministic RSpec failures in our test suite that we often call transient failures. These tests only fail when they are run in a specific order (aka, using the same RSpec order seed), and they always pass when run in isolation.
Solution:
RSpec provides an option to find the minimum number of tests to run to reproduce the failure by doing bisection.
To use it, run RSpec with the order seed of one of the fail runs, and the –bisect option. For example,
rspec spec/cool_feature_spec.rb --seed 21952 --bisect
and RSpec will find the minimum reproduction command.
....
The minimal reproduction command is:
rspec './spec/cool_feature_spec.rb[1:1:1,1:1:2]' --seed 21952
Quick switching from a class to spec
RubyMine will attempt to open the relevant spec file for a class you’re working with when you use the keyboard shortcut CMD + SHIFT + T
.
Fancy code highlighting in TIL markdown
If you want to have syntax highlighting in your code blocks, put the language you want highlighting for after the opening backticks. This:
```ruby
some = Code.new
```
Gives:
some = Code.new
Also somewhat works for other languages!
UUID Generation in Ruby Standard Lib
No need for fancy gems in order to generate RFC4122 Version 4 compliant UUID strings.
>> require 'securerandom'
=> true
>> SecureRandom.uuid
=> "af04813c-6d80-4277-b4e7-7193f7413876"
Curly braces vs. do/end: Operation Precedence
Choosing whether you use { ... }
or do ... end
around your blocks is more than just a stylistic choice in Ruby. It also affects the way that an operation will be executed because your choice also specifies the Operation Precedence to use. In a nutshell, a block curly braces has higher precedence than a block with do/end.
Consider this example from a great Stackoverflow post:
f param { do_something() }
will execute differently than
f param do do_something() end
The former will bind the block to param
, while the latter will bind the block to f
. The more you know…
Jumping/deleting by matching tags
Let’s say you have the following:
def a_method
"a return value"
end
If you put your cursor on def
and type %
, it goes to end
.
If you put your cursor on def
and type d%
, it deletes the entire method!
Selectively stashing your changes
git stash -p
will allow you to interactively stash changes at a patch level (like other git commands that support the -p
option)
Toggle Do Not Disturb
Option-click the Notification Menu icon to toggle OS X notifications. The icon is most likely in the top right hand corner of your menu bar.
Removing untracked files/directories in git
To remove untracked files/directories, use git-clean.
Running git-clean prints out what it would remove, without actually removing them.
-f flag removes the files and -d flag removes empty directories
So to remove untracked files and directories:
git clean -df
To also remove ignored files:
git clean -dfx
Add a role to all EC2 servers on a Chef Server
knife exec -E 'nodes.find("ec2:*") { |n|
n.run_list << "role[awsrole]" unless
n.run_list.include?("role[awsrole]"); n.save }'
Reverse-search in IRB.
You can reverse-search through previously entered statements in IRB by pressing Ctrl-R:
~
❯ irb
2.1.6 :001 ❯ def something_complicated(x,y); x + y; end
=❯ :something_complicated
2.1.6 :002 ❯ quit
~ 10s
❯ irb
(reverse-i-search)`compli': def something_complicated(x,y); x + y; end
Happy hacking!
Search through git commit messages
Problem:
How do you find the commits associated with a specific story?
Context:
At Nulogy, we use a story tracking system that assigns a number to each story. When we’re developing, we tag each commit message with the story number:
$ git commit -m "#1234 - refactors spec"
Solution:
We can use git log --grep
, which greps the commit messages in the repo:
$ git log --grep="#1234"