Iacutone.rb

coding and things

Level Up With Vim

| Comments

How much time do you spend in your text editor? We spend most of our time reading through text and jumping between files. My goal is to find a tool in order to help me do this more efficiently. I have found that learning Vim is not overwhelming or difficult if you break the units of work down into manageable pieces. The ultimate goal is to use Vim fulltime. Below are my curated steps:

Intro Video
Vimtutor
  • Comprehensive introduction to Vim
  • Type vimtutor in a Terminal session
  • Complete a few sections per day
Screencasts
Advanced
Helpful Links

Filtering Ack Results

| Comments

While setting up my VIM environment, I read a blogpost which states ack can ignore directories. For cleaner ack output you can setup the file below:

.ackrc
1
2
3
4
--ignore-dir=log
--ignore-dir=public/assets
--ignore-dir=vendor/assets
--ignore-dir=tmp/cache

Rails `before_action` Method

| Comments

I did not know you could give a before_action a block argument. This is a benefit because you do not have to create a ruby method and pass the method into the before_action.

This got me thinking, what does before_action look like in Rails? The following is the source code from Rails 4.2.7, from AbstractController::Callbacks::ClassMethods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# :method: before_action
#
# :call-seq: before_action(names, block)
#
# Append a callback before actions. See _insert_callbacks for parameter details.

# Take callback names and an optional callback proc, normalize them,
# then call the block with each callback. This allows us to abstract
# the normalization across several methods that use it.
#
# ==== Parameters
# * <tt>callbacks</tt> - An array of callbacks, with an optional
#   options hash as the last parameter.
# * <tt>block</tt>    - A proc that should be added to the callbacks.
#
# ==== Block Parameters
# * <tt>name</tt>     - The callback to be added
# * <tt>options</tt>  - A hash of options to be used when adding the callback

def _insert_callbacks(callbacks, block = nil)
  options = callbacks.extract_options!
  _normalize_callback_options(options)
  callbacks.push(block) if block
  callbacks.each do |callback|
    yield callback, options
  end
end

[:before, :after, :around].each do |callback|
  define_method "#{callback}_action" do |*names, &blk|
    _insert_callbacks(names, blk) do |name, options|
      set_callback(:process_action, callback, name, options)
    end
  end
end

And I can do cool things like:

1
2
3
before_action -> {
  @foo = Model.find params[:bar]
}

I would like to point out the set_callback method.

1
2
3
4
before_action :authenticate

# can also be called like this
set_callback :process_action, :before, :authenticate

Extend and Include in Ruby

| Comments

I have been trying to clean up some old code with Ruby modules. This post is to help me remember the differences between include and extend in Ruby.

1
2
3
class Foo
  extend ActionView::Helpers::NumberHelper
end
1
2
3
module Foo
  extend ActionView::Helpers::NumberHelper
end
1
2
Foo.number_to_currency 2
 => "$2.00"
1
2
3
class Foo
  include ActionView::Helpers::NumberHelper
end
1
2
3
foo = Foo.new
foo.number_to_currency 2
 => "$2.00"

Find and Replace Text

| Comments

If you find yourself in the situation of needing to find and replace text in multiple files, use the Command Line Interface. I wanted to rename a Phoenix application and ran the below command.

ack pivotal_commentor -l | xargs sed -i '' 's/pivotal_commentor/commentor/g'

Let’s break this command down with a simple example.

1
2
3
4
mkdir test
cd test
touch file1.txt
touch file2.txt

And lets add the text ‘hello’ to both text files.

1
2
3
ack hello -l
file1.txt
file2.txt

ack is like grep and found the files containing the string hello. The -l flag “Only print filenames containing matches”

1
2
ack hello -l | xargs
file1.txt file2.txt

xargs is a Unix utility that constructs argument lists and is smashing the filenames into one line.

Finally, we pipe the arguments from xargs to sed.

1
ack hello -l | xargs sed -i '' 's/hello/bye/g'

The -i flag allows for in place editing on the file. In the regex, the s replaces hello with bye and the g indicates globally, in case hello is found more than once in the file. The ‘’ is sending the change into the correct output file.

JQuery beforeSend Function

| Comments

I have a form which submits a comment via AJAX. The app was throwing validation errors if there was no value in the comment field. My initial solution was to disable the submit button if the comment is blank. However, using the beforeSend function provides a cleaner solution.

1
2
3
4
5
6
7
8
9
10
11
12
  comment = ('.form-field-comment').val()

  $.ajax
    type: 'POST'
    dataType: 'script'
    url: comment_form.attr('action')
    data:
      comment:
        body: comment
    beforeSend: () ->
      if comment is ''
        return false; # do this instead of disabling the submit button 

With the above code, the comment form is never posted if the comment is blank.

ActiveRecord None

| Comments

The .none class method was introduced in Rails 4.0.2 and is helpful when returning a blank array will break.

1
2
3
4
5
Organization.none.paginate(page: '1')
 => #<ActiveRecord::Relation []>

[].paginate(page: '1')
 => NoMethodError: undefined method `paginate' for []:Array

Helpful Links

none

Submitting a Get Request in Rails

| Comments

For the error “WARNING: Can’t verify CSRF token authenticity”, add a CSRF token.

_form.html.haml
1
2
3
4
= form_tag some_path(@organization), method: :get do
  = hidden_field_tag :authenticity_token, form_authenticity_token # this needs to be added!
  = submit_tag "View"
  = link_to_function 'Export', "Javascript function which posts to another route"

The top-level block contains method: :get which doesn’t auto-add the needed authenticity_token.

Helpful Links

Understanding the Rails Authenticity Token

RSpec Example Blocks

| Comments

I recently discovered an interesting test pattern; defining variables in before and after hooks in the rails helper.

rails_helper.rb
1
2
3
  config.before(:example, hook: true) do
    @hook = 'before hook'
  end
some_spec.rb
1
2
3
4
5
6
7
8
  RSpec.describe "some variable I need" do

    describe 'my hook', hook: true do
      it 'runs the hook' do
        expect(@hook).to eq 'before hook' # returns true
      end
    end
  end

A Real Example

Let’s say we are testing a controller and want to make sure only an admin has access to specific views.

rails_helper.rb
1
2
3
4
5
6
7
8
9
  config.before(:example, admin_signed_in: true) do
    current_user_double = Test::User.new :admin => true
    allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(current_user_double)
  end

  config.before(:example, user_signed_in: true) do
    current_user_double = Test::User.new :admin => false
    allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(current_user_double)
  end

When setting admin_signed_in to true in a describe block, we have access to an admin user. I think it is cleaner to set up these users in a hook instead of a shared context or explicitly in the spec.

Helpful Links

Hooks

Using Mocks to Test Mailers in RSpec

| Comments

I was in the situation where I needed to test the delivery of emails based on specific sets of events. I began testing by inspecting sent emails in ActionMailer::Base.deliveries. However, this method of testing felt verbose and sloppy.

RSpec mocks is a great solution when you need to test that a specific method was called. In my case, I want a fundraiser to receive an email after a campaign goal is reached.

donation_funding.rb
1
2
3
4
5
6
7
8
9
10
11
12
class DonationFunding
  attr_reader :donation

  def initialize(donation)
    @donation = donation
  end

  def fund
    # do some work
    CampaignMailer.notify_curator_campaign_goal_reached(donation)
  end
end
donation_funding_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  before do
    donation.amount = campaign.goal_amount + 1
    donation.save!
  end

  # Make a donation that exceeds the funding goal

  let!(:funder) {
    funder = DonationFunding.new donation
    funder
  }

  # set up the donation for funding

  it 'sends email goal amount reached email to the curator' do
    expect(CampaignMailer).to receive(:notify_curator_campaign_goal_reached).and_call_original
    funder.fund
  end

  # Expect a CampaignMailer.notify_curator_campaign_goal_reached email to be sent

The definition for the method and_call_original is, “You can use and_call_original on the fluent interface to "pass through” the received message to the original method.“ What exactly does this mean? It means that when I call funder.fund, I expect CampaignMailer.notify_curator_campaign_goal_reached to be called.

Helpful Links

Calling the original method