Today I Learned

A Hashrocket project

83 posts by viniciusnegrisolo @vfnegrisolo

Redirect outputs with subshell

Today I learned how to use a Subshell to redirect multiple outputs as a single one. This way I can run a bunch of commands and unify all the results as it was a single command.

(git diff --name-only; git diff --staged --name-only) | sort -u

The above example will show me a sorted list of changed files (including the staged ones) in a git project without duplicates.

Here's another example:

$ echo "world"; echo "hello" | sort -u
#=> world
#=> hello

$ (echo "world"; echo "hello") | sort -u
#=> hello
#=> world

Get selected element in Chrome Console

Today I learned that you can use $0 to grab the selected element inside chrome console:

screen shot 2016-09-30 at 10 21 41 am

Here's a list of more useful chrome-commands.

h/t @joshuadavey

From VIM to Tmux

There's a really good plugin tslime for sending text from VIM to another Tmux session/window/pane. In addition, sometimes it's super useful to map short cuts like this:

:vmap <buffer> \t <Plug>SendSelectionToTmux

In this example I'm mapping \t for sending all visual selected text in VIM to Tmux.

Check this out:

tmux

h/t @joshuadavey

Vim collapse/expand code

Today I learned to collapse/expand code in VIM using the indent fold strategy.

To enable that we need to set foldmethod:

set foldmethod=indent
set foldlevel=5

To toggle code collapse/expand just use: za.

Project Specific VIM Configuration

I learned that if you want to have a project specific .vimrc file you first need to enable it:

" ~/.vimrc
set exrc

And then you can create your specific project .vimrc file configuration in the root of your project folder.

When enabling exrc you should also consider to set secure flag as well (h/t @ali_aliev).

PostgreSQL "RETURNING"

Today I learned that PostgreSQL INSERT/UPDATE/DELETE has a RETURNING clause that returns the computed values.

We can use it to get values that are generated by database such as sequences or defaults.

Check this out:

DROP TABLE IF EXISTS users;

CREATE TABLE users (
  id    SERIAL PRIMARY KEY,
  email VARCHAR NOT NULL UNIQUE
);

INSERT INTO users (email) VALUES ('user1@example.com');
-- INSERT 0 1

INSERT INTO users (email) VALUES ('user2@example.com') RETURNING *;
--  id |       email
-- ----+-------------------
--   2 | user2@example.com
-- (1 row)

h/t @joshuadavey

Vim undo tree

Vim has an undo tree and there's two different ways to iterate with your changes.

One way to undo/redo changes is with: u and <Ctrl>r. This moves the current state based on the current branch in the tree.

The other way is using g- and g+. In this case it moves based on the timestamp of that change.

So here's an example to follow:

  1. add a line: added_line_1
  2. update this line: updated_line_1
  3. undo this change: u
  4. add another line: added_line_2

If you run through these steps your undo tree will be something like:

 o  [3] "added_line_2" <= "current_state"
 | *  [2] "updated_line_1"
 |/
 *  [1] "added_line_1"
 *  [0] "empty_file"

Now, if you undo with u will be in this state:

 *  [3] "added_line_2"
 | *  [2] "updated_line_1"
 |/
 o  [1] "added_line_1" <= "current_state"
 *  [0] "empty_file"

Otherwise if you undo with g- will be in this part of the tree:

 *  [3] "added_line_2"
 | o  [2] "updated_line_1" <= "current_state"
 |/
 *  [1] "added_line_1"
 *  [0] "empty_file"

You can check gundo vim plugin for tree visualization.

Aggregate Expressions with FILTER in Postgresql

Today I learned to use FILTER on aggregate expressions such as COUNT in postgresql.

See this example:

SELECT u.login,
       COUNT(1) FILTER (WHERE r.language ilike 'ruby') as ruby,
       COUNT(1) FILTER (WHERE r.language ilike 'javascript') as js,
       COUNT(1) FILTER (WHERE r.language ilike 'elixir') as elixir,
       COUNT(1) as all_langs
FROM users u
LEFT JOIN repositories r ON (u.id = r.user_id)
GROUP BY u.id;

-- login | ruby | js | elixir | all_langs
---------+------+----+--------+------------
-- bill  |    5 |  2 |      3 |         15
-- karen |    2 |  7 |      4 |         19
-- bob   |    9 |  1 |      2 |         23

h/t @joshuadavey

Using Ruby Hash in `gsub`

Ruby String#gsub method also accepts a hash as second argument. This is perfect for some situations like mapping a phone-word to phone number:

phonewords = {
  'a' => 2, 'b' => 2, 'c' => 2,
  'd' => 3, 'e' => 3, 'f' => 3,
  'g' => 4, 'h' => 4, 'i' => 4,
  'j' => 5, 'k' => 5, 'l' => 5,
  'm' => 6, 'n' => 6, 'o' => 6,
  'p' => 7, 'q' => 7, 'r' => 7, 's' => 7,
  't' => 8, 'u' => 8, 'v' => 8,
  'w' => 9, 'x' => 9, 'y' => 9, 'z' => 9,
}
phone = "1-800-map-gsub"
puts phone.gsub(/[a-z]/, phonewords)
# => 1-800-627-4782

h/t @joshuadavey

Rails Enum with prefix/suffix

Today I learned that Rails 5 released new options for enum definition: _prefix and _suffix.

class Conversation < ActiveRecord::Base
  enum status:          [:active, :archived], _suffix: true
  enum comments_status: [:active, :inactive], _prefix: :comments
end

conversation.active_status!
conversation.archived_status? # => false

conversation.comments_inactive!
conversation.comments_active? # => false

h/t @joshuadavey

Rails Enums and PostgreSQL Enums

Today I learned that Rails Enum works pretty well with PostgreSQL Enum.

Enum in PostgreSQL work as a new type with restricted values and if you need to guarantee data integrity there's no best way to do that than in your database. Here is how we create a new enum in PostgreSQL and use in a new column:

class AddEnumToTrafficLights < ActiveRecord::Migration
  def up
    ActiveRecord::Base.connection.execute <<~SQL
      CREATE TYPE color AS ENUM ('red', 'green', 'blue');
    SQL

    add_column :traffic_lights, :color, :color, index: true
  end

  def down
    remove_column :traffic_lights, :color

    ActiveRecord::Base.connection.execute <<~SQL
      DROP TYPE color;
    SQL
  end
end

In Rails models I prefer to use Hash syntax when mapping Ruby symbols to database values.

class TrafficLight < ApplicationRecord
  enum color: {
    red: 'red',
    green: 'green',
    blue: 'blue',
  }
end

And now Enum in action:

TrafficLight.colors
#=> {
#=>   "red"=>"red",
#=>   "green"=>"green",
#=>   "blue"=>"blue"
#=> }
TrafficLight.last.blue!
TrafficLight.last.color
#=> "blue"

h/t @ joshuadavey

Dealing with exit signals on Ruby

When working on CLIs it's useful to treat if the application exists. Image you have a long application and even if the user hits a <Ctrl+c> to kill the process you still want to display the results so far.

There is a Ruby Kernel method at_exit that runs the block passed to it if the current process exists. Here is an example:

# print_at_exit.rb
at_exit { puts "Come back later!" }
puts "sleeping for 5 secs"
sleep 5

If you run this file and wait it until it finishes you'll get:

ruby print_at_exit.rb                                                                                                                {130}
#=> sleeping for 5 secs
#=> 
#=> Come back later!

But now, if you run it and hit <Ctrl+c> for finishing the process earlier you'll get:

ruby print_at_exit.rb
#=> sleeping for 5 secs
^C
#=> Come back later!
#=> print_at_exit.rb:6:in `sleep': Interrupt
#=>         from print_at_exit.rb:6:in `<main>'

h/t @nikkypx

Elixir with macro `<-` and `=`

So Elixir with macro accepts Matching clauses <- and Bare expressions =. Both match patterns and do not leak variables assigned inside these structures.

with {:ok, width} <- Map.fetch(%{width: 10}, :width),
  do: {:ok, 2 * width}
#=> {:ok, 20}

with {:ok, width} = Map.fetch(%{width: 10}, :width),
  do: {:ok, 2 * width}
#=> {:ok, 20}

So what is the difference between these?

When a match fails, matching clauses <- returns failed result but bare expressions = raises a MatchError:

with {:ok, width} <- Map.fetch(%{height: 10}, :width),
  do: {:ok, 2 * width}
#=> :error

with {:ok, width} = Map.fetch(%{height: 10}, :width),
  do: {:ok, 2 * width}
#=> ** (MatchError) no match of right hand side value: :error

Another difference is that when guard is only available for matching clause.

with {:ok, width} when is_number(width) <- Map.fetch(%{width: 10}, :width),
  do: {:ok, 2 * width}
#=> {:ok, 20}

Markdown link references

Today I learned that we can use link references in markdown like this:

# Link by Reference with `alt` option
[Link by reference][my-link]

[my-link]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#links "My Link"

# Regular link
[Regular link](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#links)

In this case the first link will be displayed as: Link by reference

Elixir Exceptions are Structs

Elixir Exceptions are actually Structs:

Map.keys %RuntimeError{}
#=> [:__exception__, :__struct__, :message]

%RuntimeError{}.message
#=> "runtime error"

This is also true when you define an Exception with defexception.

Pattern Match and ++ operator

Today I learned that ++ operator should not be used on pattern matching.

This works with Lists of integers, but fails on compilation time for other content type.

[1] ++ [2] = [1, 2] #=> [1, 2]

[:foo] ++ [:bar] = [:foo, :bar] #=> ** (CompileError): illegal pattern
[foo: 1] ++ [bar: 2] = [foo: 1, bar: 2] #=> ** (CompileError): illegal pattern

Ruby defined? method evaluation

Today I learned that Ruby Object method defined? evaluates if the argument is anything recognizable, not just if the variable are set. Here are some examples:

undefined_foo #=> NameError: undefined local variable or method `undefined_foo'
defined? undefined_foo #=> nil

defined? nil #=> "nil"

defined? "foo" #=> "expression"
defined? [] #=> "expression"
defined? def x; end #=> "expression"
defined? class Foo; end #=> "expression"

defined? @foo = :bar #=> "assignment"

@foo = :bar
defined? @foo #=> "instance-variable"

foo = :bar
defined? foo #=> "local-variable"

def foo; end
defined? foo() #=> "method"

class Foo; end
defined? Foo #=> "constant"

h/t @VidalEkechukwu

Elixir Binaries and Bit Strings

Today I learned that in Elixir Binary is a sub type of Bit String with all elements using a multiple of 8 bits.

"a" # => "a"
?a # => 97
<<97>> # => "a"
is_bitstring <<97>> # => true
is_binary <<97>> # => true
is_bitstring <<97::4>> # => true
is_binary <<97::4>> # => false
is_binary <<97::16>> # => true
  • So String is a UTF-8 Binary.
  • And Binary is a multiple 8 bits Bit String.

Ruby try shortcut - Safe Navigation Operator

Today I learned that ruby (2.3.0) has an operator called Safe Navigation &. and this is like a short cut for that Rails try method:

foo = nil
foo.bar
# NoMethodError: undefined method `bar` for nil:NilClass
#   from (irb):18
foo&.bar
# => nil

class Foo
  def bar
    :barzzz
  end
end
foo = Foo.new

foo.bar
# => :barzzz
foo&.bar
# => :barzzz

h/t @mattpolito

How to get memory used by a Ruby object

Today I learned how to get the spaced used by a ruby object using ObjectSpace.memsize_of:

require 'objspace'
ObjectSpace.memsize_of('@')
# => 40
ObjectSpace.memsize_of('@'*23)
# => 40
ObjectSpace.memsize_of('@'*24)
# => 65
ObjectSpace.memsize_of('@'*25)
# => 66

The memory your Ruby process is taking

Today I learned how to get the memory taken by a Ruby process from inside a Ruby code:

def mem
  `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split[1] + ' KB'
end
mem
# => "61772 KB"

By the way in Ruby $$ is the same as Process.pid.

Add Css to Browser Console Log

Today I learned how to print to browser console a message with some background color and text color

console.log('%c Hello World!', 'background: #073642; color: #EEE');

One query with Select In

Today I learned that if you pass an ActiveRecord::Relation as param to where Rails will create a single query using IN and an inner SELECT:

Repository.where(user_id: User.active.select(:id))
=>  Repository Load (1.1ms)
        SELECT "repositories".*
        FROM "repositories"
        WHERE "repositories"."user_id" IN (
          SELECT "users"."id"
          FROM "users"
          WHERE "users"."status" == 1
       )

h/t @mattpolito

Ordering Issues on Github Milestones

Github released a long waited feature and now we can order issues inside a milestone.

ordering-issues

Collapsable content in Github issues

Today I learned that we can use HTML 5 detail tag to wrap a bunch of lines. This is specially useful when reporting errors and its backtrace in a repository in Github.

<details>
  <summary>`foo`</summary>
  `` `ruby
  bar
  baz
  `` `
</details>

detail-tag

h/t by @ericclemmons

Ember nested routes and it's active class

Ember adds automagically a css class active to all link-to elements under the current route.

So let's say you have this in your router:

// app/router.js
Router.map(function() {
  this.route('blog', function() {
    this.route('post', { path: ':slug' });
  });
});

If you access a page like http://localhost:4200/blog/last-post, all the following links will have the active css class.

{{#link-to 'blog'}}Blog{{/link-to}}
{{#link-to 'blog' post}}{{post.name}}{{/link-to}}
<a id="ember661" href="/blog" class="ember-view active">Blog</a>
<a id="ember663" href="/blog/last-post" class="ember-view active">Last Post</a>

So far so good, but now, if by any reason you just want either child link or parent link with the active class you can change the parent link-to to use .index.

{{#link-to 'blog.index'}}Blog{{/link-to}}

So both blog and blog.index links to the same url, but they act differently with active class.

ActiveJobs callbacks with conditionals

Today I learned that ActiveJobs callbacks accept filters, so it's easy to do conditionals like:

class SyncUserJob < ApplicationJob
  queue_as :default

  after_perform(if: :recursive) do
    SyncOrganizationJob.perform_later(user, recursive: true)
    SyncRepositoryJob.perform_later(user)
  end

  attr_accessor :user, :recursive

  def perform(access_token, recursive: false)
    @access_token = access_token
    @recursive    = recursive
    @user         = sync_user
  end

  def sync_user
    ...
  end

More context with git diff

So if you want to see more (or less) context when running a git diff command you can use -U<number_of_lines>.

Here it is a regular git diff (3 lines as default):

vnegrisolo@home:~/my-app(master)% git diff
index modified: app/jobs/github/sync_organization_job.rb
@ sync_organization_job.rb:24 @ module Github
      organization.login       = data['login']
      organization.description = data['description']
      organization.avatar_url  = data['avatar_url']
-      organization.user        = @user
+      organization.user        = user

      organization.save
      recursive_sync(organization) if @recursive

Now just showing the changed lines:

vnegrisolo@home:~/my-app(master)% git diff -U0
index modified: app/jobs/github/sync_organization_job.rb
@ sync_organization_job.rb:27 @ module Github
-      organization.user        = @user
+      organization.user        = user

Finally with 5 lines of context instead of 3:

vnegrisolo@home:~/my-app(master)% git diff -U5
index modified: app/jobs/github/sync_organization_job.rb
@ sync_organization_job.rb:22 @ module Github
      organization = Organization.find_or_initialize_by(github_id: data['id'])

      organization.login       = data['login']
      organization.description = data['description']
      organization.avatar_url  = data['avatar_url']
-      organization.user        = @user
+      organization.user        = user

      organization.save
      recursive_sync(organization) if @recursive
      organization
    end

Ruby Method arity

Today I learned that Method#arity does not consider blocks.

Also it returns negative with splat arguments.

Finally, all keyword arguments counts 1.

class Foo
  def one; end
  def two(a, b); end
  def three(a, *b); end
  def four(a, &b); end
  def five(a, b:, c:); end
end

puts Foo.instance_method(:one).arity
# => 0
puts Foo.instance_method(:two).arity
# => 2
puts Foo.instance_method(:three).arity
# => -2
puts Foo.instance_method(:four).arity
# => 1
puts Foo.instance_method(:five).arity
# => 2

h/t @higgaion

Rails reset counter caches

Today I learned that Rails has an easy way to reset counter caches

You just need to call reset_counters(id, *counters) method

irb> Organization.reset_counters(4, :repositories)
  Organization Load (0.3ms)  SELECT  "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
   (0.5ms)  SELECT COUNT(*) FROM "repositories" WHERE "repositories"."organization_id" = $1  [["organization_id", 4]]
  SQL (2.1ms)  UPDATE "organizations" SET "repositories_count" = 6 WHERE "organizations"."id" = $1  [["id", 4]]
=> true

Git log => turbo mode

Today I learned that I can combine -S 'my-search' and -p in git log command. Here is an example:

git log -p -S 'create_or' app/models/*.rb

command dissecting:

  • -p => equivalent to git diff for each commit found on log
  • -S 'my-seach' => filtering by commits that add/remove this content

Rails autoload paths

Today I learned that I can see Rails autoload_paths running:

puts ActiveSupport::Dependencies.autoload_paths
/Users/vnegrisolo/projects/my-rails-app/app/business
/Users/vnegrisolo/projects/my-rails-app/app/channels
/Users/vnegrisolo/projects/my-rails-app/app/controllers
/Users/vnegrisolo/projects/my-rails-app/app/controllers/concerns
/Users/vnegrisolo/projects/my-rails-app/app/jobs
/Users/vnegrisolo/projects/my-rails-app/app/mailers
/Users/vnegrisolo/projects/my-rails-app/app/models
/Users/vnegrisolo/projects/my-rails-app/app/models/concerns
/Users/vnegrisolo/projects/my-rails-app/app/serializers
/Users/vnegrisolo/projects/my-rails-app/app/services
/Users/vnegrisolo/projects/my-rails-app/test/mailers/previews

You can always add more paths with:

# config/application.rb
config.autoload_paths << Rails.root.join('lib')

By the way, that's why concerns (model/controller) do not have Concern as namespace.

Ember queryParams default value has to be static

Today I learned that Ember queryParams do not work with computed properties. They intend to be static values and here is an issue discussion about that.

So this code will not work properly:

export default Ember.Controller.extend({
  queryParams: ['start'],
  start: new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-' + new Date().getDate();
});
export default Ember.Route.extend({
  queryParams: {
    start: { refreshModel: true }
  },
  model(params) {
    console.log('start', params.start);
  }
});

In this example the default value is cached and if you try to change it manually, or use a computed property with volatile, you'll see a delegate is not a function error message.

Date javascript

Date javascript function on chrome is weird:

new Date('2016-10-3')
Mon Oct 03 2016 00:00:00 GMT-0400 (EDT)
new Date('2016-10-10')
Sun Oct 09 2016 20:00:00 GMT-0400 (EDT)

Why? Anyway, this is my alternative approach for that:

new Date('2016-10-10 0:0')
Mon Oct 10 2016 00:00:00 GMT-0400 (EDT)
new Date('2016-10-3 0:0')
Mon Oct 03 2016 00:00:00 GMT-0400 (EDT)

Custom QUnit assertions

QUnit is the test framework on Ember land. It's really good, but there are just 14 assertions to be used. We have ok() and notOk() so it seems that we can do whatever we want, but when some test fails the message are not good enough.

A simple string includes example:

// tests/acceptance/home-test.js
assert.ok(homePage.title.includes('Welcome to TIL'));
// => failed, expected argument to be truthy, was: false

To improve that I created this new custom assertion:

// tests/helpers/custom-asserts.js
import QUnit from 'qunit';

QUnit.assert.includes = function(text, expected) {
  let message = 'expected: "' + expected + '" to be included on: "' + text + '"';
  this.ok(text.includes(expected), message);
};

And imported in:

// tests/helpers/module-for-acceptance.js
import '../helpers/custom-asserts';

And here it is the new message on error:

// tests/acceptance/home-test.js
assert.includes(homePage.title, 'Welcome to TIL')
// => expected: "Welcome to TIL" to be included on: "Welcome to Today I Learned!"

Rails and HttpAuthentication Token

Rails has some controller helper modules for authentication:

So you can have on your controller like that:

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  include UserAuthentication

  before_action :authenticate, only: %i(show)

  def show
    render json: current_user, status: :ok
  end
end

And a controller concern like this:

# app/controllers/concerns/user_authentication.rb
module UserAuthentication
  # you might need to include:
  # include ActionController::HttpAuthentication::Token::ControllerMethods

  def authenticate
    head :forbidden unless current_user
  end

  def current_user
    @current_user ||= authenticate_or_request_with_http_token do |token|
      Session.find_by(token: token).try(:user)
    end
  end
end

Then your controller will read and parse the token from the header:

{
  headers: {
    "HTTP_AUTHORIZATION"=>'Token token="82553421c8f4e5e34436"'
  }
}

Rails 5 token ActiveModel type

Rails 5 has a new ActiveModel type token. To define it you can use: has_scure_token.

So I had this class:

class Session < ApplicationRecord
  belongs_to :user

  before_validation(on: :create) do
    self.auth_token = SecureRandom.urlsafe_base64(24)
  end
end

And then I started to use the new has_secure_token and the code is way simpler now:

class Session < ApplicationRecord
  belongs_to :user
  has_secure_token :auth_token
end

If you use generators for models you can run:

rails generate model session auth_token:token

By the way the current implementation uses SecureRandom.base58(24), so it is url safe.

Print call stack on Javascript

If you want to print the javascript call stack you can use:

console.log(new Error().stack);

Here it is an example:

function firstFunction() {
    secondFunction();
}
function secondFunction() {
    thridFunction();
}
function thridFunction() {
    console.log(new Error().stack);
}
firstFunction();

//=> Error
//    at thridFunction (<anonymous>:2:17)
//    at secondFunction (<anonymous>:5:5)
//    at firstFunction (<anonymous>:8:5)
//    at <anonymous>:10:1

h/t @rondale_sc

Rails 5 - Array Inquirer

Rails 5 has a new wrapper class for Array called ArrayInquirer the same way StringInquirer does, but with arrays.

irb> colors = [:blue, 'green'].inquiry
=> [:blue, "green"]
irb> colors.class
=> ActiveSupport::ArrayInquirer

This will create nice question like methods such as:

irb> colors = [:blue, 'green'].inquiry
=> [:blue, "green"]
irb> colors.blue?
=> true
irb> colors.green?
=> true
irb> colors.red?
=> false

It also creates the method any? for you:

irb> colors = [:blue, 'green'].inquiry
=> [:blue, "green"]
irb> colors.any?('blue', :yellow)
=> true
irb> colors.any?('red', :yellow)
=> false

By the way we use StringInquirer already:

irb> Rails.env
=> "development"
irb> Rails.env.class
=> ActiveSupport::StringInquirer
irb> Rails.env.development?
=> true

references

Ember prevent nested actions to be called

If you have an element that is affected by multiple actions you can use bubbles=false to prevent that action to bubble up to the next on the hierarchy.

<div class="container-fluid" {{action 'hideNav'}}>
  <div class="navbar-header">
    <button {{action 'toggleNav' bubbles=false}} type="button" class="navbar-toggle collapsed" aria-expanded="false">
      <span class="sr-only">Toggle navigation</span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
    {{link-to name 'index' class="navbar-brand"}}
  </div>

  <div class="collapse navbar-collapse">
    {{yield}}
  </div>
</div>

Enable commands history on rails console and irb

In order to enable commands history on rails console or irb you can just add the following to your ~/.irbrc file:

IRB.conf[:SAVE_HISTORY] = 200
IRB.conf[:HISTORY_FILE] = '~/.irb-history'

So if you close your rails console or irb the history is persisted. So next time just use the arrows UP/DOWN to get your history back.

reference

IRB Context documentation

Ember transitionTo or transitionToRoute?

They are basically the same thing, but transitionTo is supposed to be used by a Route, meanwhile transitionToRoute should be used inside a Controller.

//app/routes/application.js
this.transitionTo('blogPosts');
//app/controllers/application.js
this.transitionToRoute('blogPosts');

Rails 5 db schema and its indexes

Rails 5 changed the way they register db indexes on db/schema.rb file. Now it's nested to create_table method.

rails 5

create_table "users", force: :cascade do |t|
  ...
  t.index ["username"],
    name: "index_users_on_username", using: :btree
end

rails 4

add_index "users", ["username"],
  name: "index_users_on_username", using: :btree

Foreign keys are registered the same way as before:

ActiveRecord::Schema.define(version: 20160524224020) do
  add_foreign_key "sessions", "users"
end

Rails 5 - Use limit on ActiveRecords with OR

Rails 5 comes released a new ActiveRecord or but it still have some constraints you should know.

limit, offset, distinct should be on both queries, otherwise:

irb(main):001:0> Session.where(user_id: 1).or(
                   Session.where(provider: 'github').limit(10)
                 ).to_sql
=> ArgumentError: Relation passed to #or must be structurally compatible.
   Incompatible values: [:limit]

You need to add limit to both sides of the query, like:

irb(main):002:0> puts Session.where(user_id: 1).limit(10).or(
                   Session.where(provider: 'github').limit(10)
                 ).to_sql
=> "SELECT  "sessions".*
    FROM "sessions"
    WHERE ("sessions"."user_id" = 1 OR "sessions"."provider" = 'github')
    LIMIT 10"

Ruby Here Documents - "squiggly"

Today I learned that ruby 2.3.0 has released the squiggly heredoc <<~HEREDOC, like:

sql = <<~SQL
SELECT *
FROM users
WHERE users.status = 'active'
SQL

ActiveRecord::Base.connection.execute(sql)
  • <<HEREDOC => plain text
  • <<-HEREDOC => plain text, may indent the closing identifier
  • <<~HEREDOC => plain text, could indent the content

reference

Ruby Literals - Here Documents

Does CoffeeScript has a ternary operator?

Javascript has a ternary operator condition ? expr1 : expr2 like:

var x = true;
x ? 'yes' : 'no'
//=> "yes"
x = false;
x ? 'yes' : 'no'
//=> "no"

What about CoffeeScript?

#is-it-ternary.coffee
x ? 'yes' : 'no'

will be compiled to the following:

//is-it-ternary.js
if (typeof x !== 'undefined' && x !== null) {
  x;
} else {
  ({ 'yes': 'no' });
}

Why? Because of The Existential Operator

So there is no ternary operator on CoffeeScript. The best you can do is to have an one-line if-else statement:

if x then 'yes' else 'no'

h/t @mwoods79

Mirage v0.2.0

Ember cli mirage has just launched a new version: 0.2.0.

Run this command to update and migrate:

npm install --save-dev ember-cli-mirage
ember generate ember-cli-mirage

A lot of changes like:

  • Move /app/mirage to /mirage
  • new JsonApiSerializer
  • new mirage models

Generate your mirage models with:

ember g mirage-model user

Reference

Vim tree view mode

In folder/file structure if you type i you'll change the way you see the folders and files.

There are 4 different view modes and one of them is something like that:

../
my-app/
| app/
| bin/
| config/
| | environments/
| | | development.rb
| | | production.rb
| | | test.rb
| | initializers/
| | locales/
| | application.rb
| | boot.rb
| | database.yml
| | environment.rb
| | routes.rb
| db/

So yes, We don't need nerdtree

Vim add text surrounding

So you have in vim one line with: Hello World!.

You can add <b> and </b> surrounding Hello by typing on normal mode:

ysiw<b>
# from: Hello World!
#   to: <b>Hello</b> World!

For the whole line:

yss<b>
# from: Hello World!
#   to: <b>Hello World!</b>

You'll need vim-surround plugin

Rails 5 API and CORS

So if you have your frontend and backend on different domains you'll need to allow CORS (cross-origin HTTP request).

Rails 5 with --api mode will prepare the setup for you. You just need to uncomment the following:

# Gemfile
gem 'rack-cors'
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:4200'
    resource '*',
      headers: :any,
      methods: %i(get post put patch delete options head)
  end
end

Move current VIM pane to a new tab

To move the current a VIM pane to a new tab:

<Ctrl>wT

The Ruby % notation

So ruby have this % notation inspired by Perl to define a string.

Here are some different ways to generate the same string:

%{hello world}
%<hello world>
%(hello world)
%[hello world]
'hello world'
"hello world"

=> "hello world"

Git list changes on files

If you want to list all changes to a file you can run:

git log -p app/controllers/training_*

h/t @greis

Time Travel by Rails

Rails have travel, travel_to, travel_back Testing Helper Methods to travel in time and then test your app with exact dates and times.

include ActiveSupport::Testing::TimeHelpers

Time.current
=> Tue, 17 May 2016 12:31:52 UTC +00:00

travel_to Time.new(2004, 11, 24, 01, 04, 44)
Time.current
=> Wed, 24 Nov 2004 06:04:44 UTC +00:00

travel_back
Time.current
=> Tue, 17 May 2016 12:32:17 UTC +00:00

Another nice alternative is to use gems like:

Rails 5 API mode

You can build a rails API with the --api mode on Rails 5.

rails _5.0.0.rc1_ new rails5-api --api

Gems removed with api mode:

  • coffee-rails
  • jquery-rails
  • sass-rails
  • uglifier
  • turbolinks
  • jbuilder

Files removed with api mode:

  • app/assets
  • lib/assets
  • vendor/assets
  • app/helpers
  • app/views/layouts/application.hmtl.erb

ApplicationController

app/controller/application_controller.rb has changed to inherit from ActionController::API

Rack middleware list changed with api mode:

5 middlewares were removed, including Cookies and Flash.

use Rack::MethodOverride
use WebConsole::Middleware
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash

Check their changelog

Rails 5 changed belongs_to default validation

New Rails 5 applications comes with this initializer:

# config/initializers/active_record_belongs_to_required_by_default.rb
Rails.application.config.active_record.belongs_to_required_by_default = true

So now, belongs_to associations require presence by default.

In order to make this relation optional you can change the initializer value for the whole app, or add optional: true to your relation:

belongs_to :user, optional: true

That's the code change.

How to take next elements with Enumerator

So we had this logic to get the next 10 Tuesdays and Thursdays:

date = Time.current
(1..10).map { date = next_available_day(date) }

def next_available_day(date)
  loop { return date if tuesday_or_thursday?(date += 1.day) }
end

def tuesday_or_thursday?(date)
  date.wday == 2 || date.wday == 4
end

With Enumerator it seems cleaner:

next_available_dates(Time.current).take(10)

def next_available_dates(date)
  Enumerator.new do |enumerator|
    loop { enumerator.yield date if tuesday_or_thursday?(date += 1.day) }
  end
end

def tuesday_or_thursday?(date)
  date.wday == 2 || date.wday == 4
end

h/t by @mwoods79

Rails 5 deprecation warning for Controller tests

Rails 5 has changed its ActionController::TestCase::Behavior to methods we use in controller tests and now you need to specify params key to the requests.

So if you had this in you tests:

get :show, id: 1

You'll need to change to:

get :show, params: { id: 1 }

There is a warning message like this:

ActionController::TestCase HTTP request methods will accept only
keyword arguments in future Rails versions.
Examples:
  get :show, params: { id: 1 }, session: { user_id: 1 }
  process :update, method: :post, params: { id: 1 }

Even if you use Rpsec you will need to change because rspec-rails uses this module to create the requests to the controllers.

Auto Complete with vim snippets

There is a vim plugin called vim-snipmate that lets to auto complete a bunch of code for you. So you type some snippet trigger and hit <tab> and that's it.

Also there is another vim plugin vim-snippets with a lot of snippets for a lot of languages or file types.

For example this snippet for if in shell files:

snippet if
    if [[ ${1:condition} ]]; then
        ${0:#statements}
    fi

reference

Global git hooks

There are no global git hooks.

But you can create global hook templates and for every project you can use them.

Create a folder for your global templates:

mkdir -p ~/.git-templates/hooks

Configure git to use this templates folder:

git config --global init.templatedir '~/.git-templates'

Create an executable hook, for example `~/.git-templates/hooks/pre-commit

#!/bin/sh
echo "This happens before the commit"

For every project you want to use these templates restart git project running:

git init

These will create symbol links like:

lrwxr-xr-x   pre-commit -> /Users/vnegrisolo/.git-templates/hooks/pre-commit

Vim arglist => replace text to multiple files

  • :arg => list files in arglist
  • :argdelete * => clean arglist
  • :argadd **/*.rb => add files to arglist
  • :argdo %s/foo/bar/gc => replace foo by bar in arglist
  • :argdo update => save changes to arglist
  • :argdo undo => undo changes to arglist

Navigation in arglist

  • [a => go to the previous file in arglist
  • ]a => go to the next file in arglist
  • [A => go to the first file in arglist
  • ]A => go to the last file in arglist

Vim Registers and Macros

Vim Macros and yanked texts are actually stored in the same Vim Registers.

So you can do crazy things like record a macro and paste it. Or copy (yank) a piece of code and play it as a macro.

It seems that this does not ever makes sense to mix them, but it's crazy!

Github Reactions and Merge Strategy

Recently Github has launched 2 new features:

Reactions to comments

Now users can add few reactions to Issues, Pull Requests or Comments. This will reduce a lot of noise on issues like the 👍 (:+1:) for new feature. Really cool.

Squash and rebase as a new merge strategy

Github always create a new commit merging a branch into another one (usually master).

So now we can choose to squash commits and merge. So all commits in a branch will become just one and this one will be rebased into the branch. Sounds cool for a few situations.

Check it out!

Rails nested forms

You can use rails Nested Forms even with plain form objects.

You just need to use form.fields_for and then declare the params name and the object for validation errors.

view

= form_for @foo_form, as: :foo, url: foo_path do |form|
  = form.text_field :name
  = form.fields_for :bar_params, @foo.bar do |nested_form|
    = nested_form.text_field :description

form

class FooForm
  include ActiveModel::Model

  attr_accessor :name, :bar_params, :bar
  validates :name, presence: true

  def initialize(attributes = {})
    super attributes

    self.bar  = BarForm.new(bar_params)
  end

  def save
    valid? && Foo.create(name: name)&& bar.save
  end
end
class BarForm
  include ActiveModel::Model

  attr_accessor :description
  validates :description, presence: true

  def save
    valid? && Bar.create(description: description)
  end
end

controller

class FooController < ApplicationController
  def edit
    @foo_form = FooForm.new
  end

  def create
    @foo_form = FooForm.new(params[:foo])
    if @foo_form.save
      redirect_to root_path
    else
      render :edit
    end
end

So the bar params will be scoped into bar_params node, and the validations will work.

Vim registers

When copy/cut some code you are already using registers. To see them:

:registers

Or simply :reg

You can also define which one to use, including any letter.

For example, to copy the current line and store it into the register T:

"Tyy

in order to paste it:

"Tp

Capybara tests on a Rails Engine

If you have a Rails Engine you probably have a dummy app attached in test/dummy or spec/dummy to run and manual test the engine, right?

So you can use this dummy app to have some feature tests with capybara.

The trick is to change the RAILS_ROOT to point to the correct file.

For cucumber tests add the following into features/support/env.rb:

ENV["RAILS_ROOT"] ||= File.expand_path(File.dirname(__FILE__) + '/../../spec/dummy')

For rspec tests add the following into spec/rails_helper.rb:

ENV["RAILS_ROOT"] ||= File.expand_path(File.dirname(__FILE__) + '/dummy')

Jump to cucumber step definitions in VIM

There is an amazing vim plugin vim-cucumber that allows you to jump from step (.feature file) to its definition (_steps.rb file).

In vim normal mode put the cursor on any step inside a .feature file and:

  • [d or ]d => split pane
  • <CTRL-w><CTRL-d> => split pane and change cursor focus
  • [<CTRL-d> or ]<CTRL-d> => replace pane

h/t @mrmicahcooper

Ruby Keyword Arguments - mandatory params

If you do not set a default value for a keyword argument it will become mandatory and will raise an ArgumentError.

an example:

def mandatory_keyword(bar:)
  "foo=#{bar}"
end

def default_keyword(bar: nil)
  "foo=#{bar}"
end

and its test:

describe 'keyword_arguments' do
  it { expect{mandatory_keyword()}.to raise_error(ArgumentError) }
  it { expect(mandatory_keyword(bar: 'bar')).to eq('foo=bar') }

  it { expect(default_keyword()).to eq('foo=') }
  it { expect(default_keyword(bar: 'bar')).to eq('foo=bar') }
end

In case you don't want this behavior you can always set a default to nil.

VIM Insert in paste mode

We can copy a text from anywhere and paste into vim using the insert mode with the paste option by just typing: yo or yO:

yo
<paste>

this is equivalent to:

:set paste
o
<paste>
:set nopaste

Cucumber step inception

I learned that you can call a cucumber step inside another one. Super cool!

Image a simple step like this:

Then /^I should see "(.*)"$/ do |text|
  expect(page).to have_content(text)
end

Now you have modals on your web app and you need to restrict this assertion to inside the modal.

So you can start to duplicate the step above to match the within modal and all the ones that could be reusable with modals.

Or you can create a new generic step that scope into the modal and calls your original step, such as:

And /^(.*?) within the modal$/ do |step_definition|
  within ".modal", visible: true do
    step step_definition
  end
end

Now you can call both steps in your gherkin files:

Then I should see "Hello World!"

or

Then I should see "Hello World!" within the modal

Just be careful with generic and reusable steps. The idea is to help developers and not confuse them.

reference: Cucumber wiki - call step from step definition

h/t Taylor Mock

Capybara's RackTest driver limitation

By default, if you click a link through Capybara and it takes you into an external site, the current_url will work fine, but the content on the page does not change.

RackTest is the Capybara's default driver and it has its limitations.

you cannot use the RackTest driver to test a remote application, or to access remote URLs

If you really need to do that know other drivers features and try them.

h/t by Nick Palaniuk

Ruby array shortcuts - "&:" and "&method"

Call a method on every items with &:

So this:

[:foo, :bar].each do |item|
  item.to_s
end

Can be reduced to:

[:foo, :bar].each(&:to_s)

But, what if you want to call a method for each item in an array, and this item should be a parameter for this method?

Call a method with every items as a parameter with &method

So this:

[:foo, :bar].each do |item|
  puts(item)
end

Can be reduced to:

[:foo, :bar].each(&method(:puts))

Replace text in VIM and keep the case

If you use the vim plugin vim-abolish you can replace some text keeping the original case. You just need to use S instead of s in find/replace vim command.

In order to change foo to bar and keep the case use:

:%S/foo/bar/gi

This will apply the following changes:

FOO => BAR
foo => bar
Foo => Bar

Fixing a past commit

To add some code changes to a past commit you can commit with the fixup option and then rebase it.

# add the code changes you want to add to the past commit
git add .

# get the git commit you want to add the changes and copy its reference
git log

# commit the changes with the options `fixup`
git commit --fixup <COMMIT_REF>

# rebase the commits to apply the fixup from one commit before the starter commit
git rebase -i <COMMIT_REF>~1

This will open your editor (vim) with the rebase plan, so you can apply it.

Advanced Search with Textacular

Textacular exposes full text search capabilities from PostgreSQL, extending ActiveRecord with scopes making search easy and fun!

We wanted an advanced search, but that should also work as autocomplete.

So we end up using the gem textacular and the PostgreSql tsquery with the :* for prefixed searches

Game.advanced_search(title: 'street fi:*')

Thanks @mrmicahcooper!

references

Next file or next search result in Vim

We can jump to next file just typing:

  • ]f => go to next file in the same folder, or next folder
  • [f => go to previous file in the same folder, or previous folder

We can also jump to next search results, for example after a :grep my-search-text .

  • ]q => go to next search result
  • [q => go to previous search result

Running same Vim command into multiple lines

We can run the same vim command for multiple lines using the norm, like:

:%norm cs'"

This will replace every single quote with double quote:

  • % => for every line
  • norm => repeat the following command in normal mode
  • c => change
  • s => surround
  • ' => delimiter char, in this case single quote
  • " => replaced char, in this case double quote

Tabularize in VIM - changing whitespaces count

In order to tabularize texts based on comma character use the tabular vim plugin:

:Tabularize /,

This will by default add at least 1 whitespace to the left and exactly 1 whitespace to the right.

You can change this adding /l<NUM>r<NUM> to the end of command.

For 0 to the left and 1 to the right:

:Tabularize /,/l0r1

example:

# original
resources :posts, path: 'blog_posts', only: [:index, :show, :create]
resources :comments, path: 'user_comments', only: [:index, :show]

# :Tabularize /,
resources :posts    , path: 'blog_posts'    , only: [:index , :show  , :create]
resources :comments , path: 'user_comments' , only: [:index , :show]

# :Tabularize /,/l0r1
resources :posts   , path: 'blog_posts'   , only: [:index, :show , :create]
resources :comments, path: 'user_comments', only: [:index, :show]

reference

Difference betweent `to_a` and `to_ary`

  • to_a => called for explicit conversions
  • to_ary => called for implicit conversions

example:

class Coordinates
  attr_reader :x, :y
  def initialize(x, y)
    @x, @y = x, y
  end

  def to_a
    puts "to_a called"
    [x, y]
  end

  def to_ary
    puts "to_ary called"
    [x, y]
  end
end

coordinates = Coordinates.new(5, 7)

puts "splat"
a = *coordinates
# => to_a called

puts "multiple assignment"
x, y = coordinates
# => to_ary called

puts "Implicit conversion into block params"
[coordinates].each { |(x, y)| puts x }
# => to_ary called

Go to file under the cursor in Vim

Let's say in a file you reference another one, requiring that code. Vim has an very easy way to open the required (imported, loaded, etc) file. Great tip for adding external dependencies code.

Put the cursor in the file name you want to open and:

gf

If you want to go back: <Ctrl> o.

To find the file Vim uses an option called path, and you can check your current path with:

:set path

So if you expect a file is not being found you can check the path and add values to it.

:set path+=some_special_folder/

Finally, as Vim looks for a lot of paths, it may find more than one, and gf will bring the first one. To get the second match, type g2f, for the third g3f and so on.

Also, check this article to restrict Vim options by file extensions and to add file suffixes.

Vim macro is amazing!

If you want to repeat a bunch of vim commands for running multiple times, record them in a macro and run wherever you want.

To record a macro you need:

  1. type q followed by any char: [a-z]
  2. type your vim commands
  3. type q again to finish recording

Finally, to run the macro that you just created type:

@ followed by the same char you chose to store the macro.

Ruby String Mutability

Until Ruby 3 we need to explicitly call the method freeze on literal strings, so they become immutable. And, if you have a lot of literal strings in a file, this will be very repetitive and verbose. In order to let our code cleaner there is a magic comment that can be added in the top of each file.

the magic:

# frozen_string_literal: true

And it is done, all literal string are frozen now :)

example:

class Unfrozen
  def foo
    'bar'
  end
end
class StringFrozen
  def foo
    'bar'.freeze
  end
end
# frozen_string_literal: true
class ClassFrozen
  def foo
    'bar'
  end
end

To test that:

require 'spec_helper'

describe 'Ruby String Mutability' do
  it 'validates string mutability' do
    expect(Unfrozen.new.foo.frozen?). to be false
    expect(StringFrozen.new.foo.frozen?). to be true
    expect(ClassFrozen.new.foo.frozen?). to be true
  end
end
Randomized with seed 51265
.

Finished in 0.00179 seconds (files took 0.45396 seconds to load)
1 example, 0 failures

\o/

Vim change case of words

If you want to switch the case in Vim:

gu => lowercase

gU => uppercase

g~ => toogle case

You can also combine with Vim motions like:

g~ip => toogle case for the current paragraph.