Tuesday, June 21, 2011

The most useful VIM plugin

So I've been researching more about VIM recently. I took a look at a few plugins used by a certain unnamed company and found one that I think is extremely useful, although the syntax for the command is a bit onerous. Here goes anyway. It's called Surround.vim (find it here)

If you have text that looks like this:
"Some text"
you can change the double quotes to single quotes by issuing the following command:
cs"'
Pretty powerful, huh? That's only a fraction of what it allows you to do. Check out the vimscripts site for more info on it

Friday, June 17, 2011

Unfickle: A new constant way

Through my programming in Ruby I see a lot of people doing things like this:



I really don't like this.. It just seems messy. So, I wrote a gem that I think solves it in a somewhat elegant way. The gem is called Unfickle and can be used like so:



The result is somewhat the same, only it's stored in a hash. This gives users the ability to iterate over that hash to find the constant they want. Example:



You can even traverse the constants using the '.each' method provided by the Hash class :D

The entire code for this gem is very simple:



The first method, 'set_const' just creates a new hash, if it doesn't exist, and adds the key/value pair to that hash. 'const_missing' is the method that retrieves the hash value based on the key passed in.

I extended the 'Forwardable' module and delegated four methods to the Hash instance created by the set_const method. This means I don't have to re-implement that.

One of the issues with this code is optimization. Using 'const_missing' means we have to go through a begin/rescue block to figure out a constant is missing. This is a performance hit. The other speed issue comes with the use of delegators. Although these two things can slow down code, I think the speed hit is negligible. If you have a better way, don't hesitate to let me know.

You can find this code on github here.
Install the gem like normal:
gem install unfickle

Monday, June 13, 2011

VIM Searching

Every once in a while I'll want to find the second occurrence of a match in command mode so I can edit from that point. An example would be a line like this:
gem 'haml',             '3.0.25'
gem 'my_own_gem',       '0.1.10', path: "/path/to/my_own_gem"
gem 'pg',               '0.10.1',     :require => false

Say my cursor is at the beginning of the second line and I want to comment out the 'path' part cuz I pushed my code and don't need to develop from my local directory anymore. I used to have to hit 'l' tons of times till I got to the comma just before the path.

I tried using this search pattern '/\,', but that matches the first comma. I'd still have to hit 'l' a bunch of times to get the next one, or I could hit enter and 'n'.

I finally figured out that if I hit '2/\,/' that will find the second match in the expression :D That works with any number, 5, 9 10, etc. VIM is great. the end.

So this is how it ends up
`in command mode`
2/\,
gem 'haml',             '3.0.25'
gem 'my_own_gem',       '0.1.10' #, path: "/path/to/my_own_gem"
gem 'pg',               '0.10.1',     :require => false

Wednesday, May 25, 2011

undefined method task

There's been a few people struggling with the dreaded 'undefined method task' when installing rails 3 with rake 0.9.0.beta4 (currently the latest version of rake that comes with rails automatically). You can get around this issue by putting the following in your Rakefile


Just make sure the modules are added before the Application.load_tasks call.

Monday, May 23, 2011

splat

Found a nifty way to convert arrays to hashes and vise-versa,
ruby-1.9.2-p0 :037 > data = [["a", 1], ["b", 2], ["c", 3]]
 => [["a", 1], ["b", 2], ["c", 3]] 
ruby-1.9.2-p0 :039 > h = Hash[*data.flatten]
 => {"a"=>1, "b"=>2} 
and back
ruby-1.9.2-p0 :048 > ar = *h
 => [["a", 1], ["b", 2]] 

Wednesday, May 18, 2011

in_groups vs in_groups_of

I was looking through the methods for arrays in active support and found in_groups. I already knew about in_groups_of so, naturally, I thought, "what does in_groups do?"
%w(a b c d e f g h i j k l m).in_groups(4)
splits an array into 4 groups of 4 elements (use on bigger arrays to really get a feel for what it does.
[["a", "b", "c", "d"], ["e", "f", "g", nil], ["h", "i", "j", nil], ["k", "l", "m", nil]]

%w(a b c d e f g h i j k l m).in_groups_of(4)
splits the array into groups of 4 elements (again, bigger arrays will give you a better idea)
[["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i", "j", "k", "l"], ["m", nil, nil, nil]]

If you wanted all those nil values to go away, just pass false as a second parameter to either of these functions. You can also just fill in nil with any other object by passing that object instead of false.

Thursday, May 12, 2011

Flyrb

Found a nifty gem the other day called utility_belt. It's actually pretty old, back to about 2006 or so. I thought the idea of being able to use VI to edit some code and have it run in the console without ever really leaving the console was an excellent idea. Only problem was the library hadn't been updated since 2008, which means I couldn't use it in Ruby 1.9.. Gay.
I eventually found a new little gem called FlyRB, which is a fork of utility_belt but it's 1.9 compatible.
Now, I need to figure out how to get flyrb to work in the rails/daemon_kit console without having to put it in the Gemfile (~/.irbrc doesn't seem to do the trick in anything but irb).

Utility Belt
FlyRB

Thursday, February 24, 2011

Ruby array sorting

I recently had to come up with a way to sort an array of objects that looked something like this,
  ["a", "c", "b", "1", "10", "3", "thing4", 
   "thing3", "thing30", "thing2"]

We needed the text only strings first and the strings with numbers in them sorted by their numbers. The example arrays explain it better. Here's what I came up with:


This will sort that array so it comes out looking like this:
  ["a", "b", "c", "1", "thing2", "3", "thing3", 
   "thing4", "10", "thing30"]

Pretty, huh?

Wednesday, February 23, 2011

Inject

I just learned something awesome. I'm always doing something like this in Ruby,
  [4, 5, 6, 7].inject(0) {|t,v| t + v}

I could clean this up and do something much simpler using inject, like so,
  [4, 5, 6, 7].inject(:+)

What's more, you can run this too
  [4, 5, 6, 7].inject(:-)
  [4, 5, 6, 7].inject(:*)
  [4, 5, 6, 7].inject(:/)

And check this out, say I want the average of the numbers in this array. I just run this:
  [4, 5, 6, 7].instance_eval { inject(:+) / self.size.to_f }

Simply brilliant.

Monday, February 21, 2011

decent exposure

I was recently introduced to a nifty little gem called decent_exposure. This allows me to do something like the following in my controller

If this is my user controller, I can replace
  def index
    @users = User.all
  end
with
  expose(:users)

This definitely cleans up the code quite a bit. When things start getting hairy, you can redefine your expose method using a block, like so:
  expose(:users) do
    User.active
  end
This will grab all active users in your database (assuming you have a scope, in your model, that grabs all active users).
The gem does a lot more than I'm gonna cover here, I suggest taking a look at decent_exposure's github page for more info.

Wednesday, February 16, 2011

top!

I learned something really useful just now. I'm always opening up top and hitting 'c', 'M', every time. I did something few of us do today, though, I looked at the Man page :)

Do this
  - open up top
  - hit your favorite commands
  - now hit shift+w
This'll save your configuration info to ~/.toprc.

Now you don't have to hit a whole bunch of annoying letters every time you open up top. I did a bit of analysis on the amount of times I hit a command, out of the default whatever amount of saved commands, I hit top 166 times. hmm..
So I alias'd top to t, just 'cause I'm a bad mofo.

Friday, February 11, 2011

Makandra - Comparing two arrays

I recently came across a website called makandra.com. They have notes publicly available that they would normally only use internally. One not caught my eye, Check if two arrays contain the same elements with and without RSpec. The code for RSpec is straight-forward and simple but the code to duplicate that functionality is somewhat more than is needed. This function:

def difference_between_arrays(array1, array2)
  difference = array1.dup
  array2.each do |element|
    if index = difference.index(element)
      difference.delete_at(index)
    end
  end
  difference
end

could go away completely without any problem. Without this function, the second could be re-written like this and achieve the exact same functionality:

def same_elements?(array1, array2)
  extra_items = array1 - array2
  missing_items = array2 - array1
  extra_items.empty? & missing_items.empty?
end

I'm not sure if Henning Koch will come across this or not, but maybe it'll help him out (or anyone else that comes across this).