Iterators are one of the least used features in Javascript. But, when used correctly, it gives very powerful abilities.

What is the Iterator pattern?

When an object responds to a

1
next()
function which produces the next value in a sequence every time it is called, then it follows the iterator pattern. The return value should also specify if the end of the sequence has been reached, so the return value of the function is not just the value but, an object with a
1
value
and a
1
done
properties.

Consider a function which generates a sequence of even numbers till 10. Which would look like,

let EvenNumbers = function() {
  let value = 0;
  return {
    next: function() {
      if (value > 10) {
        return { done: true };
      }
      return { value: value + 2, done: false };
    }
  }
}

Now, this can be used like,

let evenNumbers = new EvenNumbers();
evenNumbers.next().value  // 2
evenNumbers.next().value  // 4
evenNumbers.next().value  // 6
evenNumbers.next().value  // 8
evenNumbers.next().value  // 10
evenNumbers.next()        // { done: true }

The real power with this is the ability to store the state of the sequence and call

1
next()
to get the next number in the sequence.

Do you remember when I said that iterators are one of the lease used features in JavaScript? Well, I lied. All

1
for...of
loops use iterators to loop around.
1
Array
is one of the very widely used example of Iterators. Which means for us, we can loop around the above sequence using a
1
for...of
loop.

let evenNumbers = new EvenNumbers();
for (var x of evenNumbers) {
  console.log(x);		// 2,4,6,8,10
}

Now, what are Generators?

Generators are a syntactical sugar for writing custom iterators. They remove the need for writing careful code for explicitly maintaining the internal state of the iterator.

For example, the above

1
EvenNumbers
generator can be written as,

function * evenNumbers(start = 0) {
  for (let i = start + 2; i < 10; i += 2) {
    yield i;
  }
}

let evenNumbersGenerator = evenNumbers();

evenNumbersGenerator.next().value 	// 2
evenNumbersGenerator.next().value 	// 4
evenNumbersGenerator.next().value 	// 6
evenNumbersGenerator.next().value 	// 8
evenNumbersGenerator.next().value 	// 10
evenNumbersGenerator.next()		 	// { done: true }

for (var x of evenNumbers()) {
  console.log(x);		// 2,4,6,8,10
}

If you compare the generator example with the iterator example, you will see that both of them achieve the same thing, but the generator uses very less code.

1
yield
takes care of returning the Object with
1
value
and the
1
done
flag. Once the function execution stops, the
1
{ done: true }
is returned as well.

Generators vs Iterators

Generators have a huge advantage over the traditional iterators in many ways.

  • No need to maintain internal state which leads to Lesser code.
  • No need to return an object with value and done flags.
  • Almost looks like a normal function.

Hope you would be very eager to start using generators in your project. Please comment how you are using / planning to use them below.

I was working on client side searching in an ember application. The requirements was very simple, consider the following array of strings,

"We aim to be simple to integrate with any modern Rails application",
"We need an application that can display the current state of the orders",
"The intent behind it was to keep setup as easy as possible"

and I search for the query

1
"application"
, I should get the following as output.

"We aim to be simple to integrate with any modern Rails application",
"We need an application that can display the current state of the orders"

But, if I search for

1
"current orders"
, I should get the following as output,

"We need an application that can display the current state of the orders"

So clearly, it was keyword based searching.

I ended up finding just the right library, lunr.js. I wanted it to work with my ember model’s very robustly. So I ended up creating a ember-addon for it and named it (according to the pseudo addon naming convention) as ember-cli-lunr.

Hope you all find this addon useful in your ambitious search applications. And please help me make this ember addon better by submitting PR, feature request, issues or just a thank you (your appreciation moves me forward).

Recently, In Paperclip (4.1.1) I had to change the

1
hash_secret
, which is used for the purpose of URI Obfuscation. But, the problem was that there had been many files in production generated with the old
1
hash_secret
. Simply just changing the
1
hash_secret
would invalidate all the old URL’s as paperclip does not store the URL’s of the files instead it generates using the
1
path
option given to it (which would obviously contain the
1
:hash
interpolation).

It was evident that I had to write a migration to move the already existing files from old location to new location (We were storing the files in S3). Also, I wanted the moving part to simply look like

old_object = bucket.objects[attachment.file.old_path]
new_object = bucket.objects[attachment.file.path]

old_object.move_to(new_object)

In order for

1
file.old_path
to work I had to override
1
Paperclip::Attachment
and add
1
old_path
method to it. Although, it turned out that I had to override three more functions, it was worth it. Besides, this override was just a temporary one.

# config/initializers/paperclip_override.rb

require 'openssl'

module Paperclip
  class Attachment

    # Old path overrides
    def old_path(style_name = default_style)
      path = original_filename.nil? ? nil : interpolate(old_path_option, style_name)
      path.respond_to?(:unescape) ? path.unescape : path
    end

    def old_path_option
      # Replace this with your :path option replacing :hash with :old_hash
      "file_attachments/:id/:old_hash.:extension"
    end

    def old_hash_key(style_name = default_style)
      data = interpolate(@options[:hash_data], style_name)
      OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@options[:hash_digest]).new,
        "<YOUR OLD HASH_SECRET>", data)
    end
  end

  module Interpolations
    def old_hash attachment=nil, style_name=nil
      if attachment && style_name
        attachment.old_hash_key(style_name)
      else
        super()
      end
    end
  end
end

Here is the rake task which moves the file from old location to the new location just as I wanted it to be,

# lib/tasks/paperclip_hash_secret_migration.rake

namespace :paperclip do
  task :s3_migration => :environment do
    Attachment.all.each do |attachment|
      s3 = AWS::S3.new(AWS_S3["credentials"])
      bucket = s3.buckets[AWS_S3["bucket_name"]]

      old_object = bucket.objects[attachment.file.old_path]
      new_object = bucket.objects[attachment.file.path]

      puts "Moving object from #{attachment.file.old_path} to #{attachment.file.path}"
      old_object.move_to(new_object, { :acl => :public_read })

      # Perform any additional operations you want with
      # old_object and new_object here.
    end
  end
end

If you are using a File Storage, then you could find appropriate ruby code to move file from one path to another on Google.

It all started with a project in which I was working on, it contained too many constant tables like Country, City etc. It was a team of 3 people including me. We had tough time querying to check if the user belonged to a certain country.

if user.country.name == "India"
  # Some logic
else
  # Some logic
end

The above code was present all over the place. Being obsessed with elegance, we all wanted something like the following,

if user.country.india?
  # Some logic
else
  # Some logic
end

Additionally, there were many places in which we had to query for the country record.

  Country.find_by_name("United States of America")

And again we felt something wrong and wanted it to be more elegant and easy to read, so we decided we wanted to replace it with this,

  Country.united_states_of_america

We wrote a module to be included in all the constant model’s and being open source enthusiasts we extracted it into a gem which is hosted in github.

This module is young, so we need support from people to make it better. So feel free to contribute to the repo.

Clearly everybody using rails will have this problem. When your model gets bigger and bigger, you will find it difficult to spot your attributes in the rails console. So let’s clear this messed up console and format it a little bit. We have a gem called ‘awesome_print’. Install it using

gem install awesome_print

Then open your ~/.irbrc file and add these lines to it.

# load libraries
require 'rubygems'
$LOAD_PATH<< '/path/to/awesome_print-x.x.x/lib'
require 'awesome_print'

usually if you use RVM and ruby 1.9.3 your path to awesome_print gem will be like

/home/username/.rvm/gems/ruby-1.9.3-p448/gems/awesome_print-x.x.x/lib

now fire up your rails console and try to print any object prepended with ‘ap’

ap User.first

Hooray!!! We formatted the console. But wait, we missed something. Printing everything with ‘ap’ prepended seems inappropriate. So let’s make awesome_print our default formatter. Now, open your ~/.irbrc again and add this line after requiring awesome_print.

AwesomePrint.irb!

Now you will be able to format everything you print beautifully. And you can add options to awesome print. See the documentation for more details.

Enjoy hacking !!!