Just released: git-style-binaries ruby gem. Checkout the README on github.
Checkout the screencast.
Modified from Rob Seaman’s post.
multiruby is a great way to make sure your ruby code runs on the multitude of ruby versions (it’s part of ZenTest). It doesn’t install macruby by default. Here are instructions on how to set it up.
Since I installed macruby from the package installer my macruby files are in /Library/Frameworks/MacRuby.framework/Versions/0.4/. If your macruby files are somewhere else, adjust accordingly.
First make sure you already have multiruby setup for other versions (don’t proceed if this doesn’t work):
multiruby_setup the_usual
One problem I had with the above command was that I had RUBYOPT set in my .profile. This was calling each of these ruby versions with RUBYOPT=rubygems when trying to install. This won’t work because rubygems is one of the things you’re trying to install. Make sure you unset this variable etc. before trying to setup multiruby.
ln -s /Library/Frameworks/MacRuby.framework/Versions/0.4/usr ~/.multiruby/install/macruby-0.0.4 sudo ln -s ~/.multiruby/install/macruby-0.0.4/bin/macruby ~/.multiruby/install/macruby-0.0.4/bin/ruby sudo ln -s ~/.multiruby/install/macruby-0.0.4/bin/macgem ~/.multiruby/install/macruby-0.0.4/bin/gem touch ~/.multiruby/versions/macruby-0.0.4.tar.gz # fake-out
Now try:
multiruby -e "p 1+1"
One of the nice things about the Twitter web-interface is that it gives you feedback on the number of characters you’ve typed so far.
Since I use the command-line twitter gem (by John Nunemaker) I miss out on this feature and find myself using echo and wc to make sure I’m not over the limit.
To fix this problem, I’ve written a small, immediate-feedback utility called tweet. It shows you the number of characters typed so far and colorizes them accordingly.
Screenshots:
Just download this script and save it as tweet somewhere in your $PATH
I do not claim to be a wiz at git, and I do not ensure what I am writing about, but it seemed to work for me, and I appreciate any comments.
My goal was to temporarily revert one or many commits that I had pushed to the remote server.
http://cheat.errtheblog.com/s/git — specifically the “Fix mistakes / Undo” section was helpful.
What I found:
git revert -n <sha>
#run this for each commit you would like to “undo”
(the -n makes it so that you are not actually creating a commit, but staging the reverse of the changes made by your <sha> commit in your index. git status will show you this)
git ci -a # apply your revision git push #origin to master (these steps effectively created one commit that was the product of reversing all the commits you picked in the git revert -n step)
now your index looks like:
now, lets say, the time has come to reapply your commits. Because you didn’t just do
git reset --hard <commit3>
or something like that, all you have to do is git reset –hard <sha1> which will “undo your undo”
then
git push #origin masteragain and you are back to where you were.
wresting with the command line, and some cool cli programs I learned on the way
I want desperately to know how to detach a process from one terminal, and re-attach it to another, without using screen from the get-go. The more I read about it, the more I figure that the answer (you can’t) probably has more to do with my lack of understanding of how processes and terminals work. I read a great post here that introduced me to disown -h (careful) and nohup, some really great bash builtins. I thought, ok, lets try it. This is where I got stuck.
I tried
while true; do sleep 10; done & disown -h %1 exit
The disown builtin handles a problem with background processes: From the bash man page (and also the above blog)
The shell exits by default upon receipt of a SIGHUP
therefore killing your process you ‘thought’ you put in the background, and then logged out to go home for the night. Disown tells the jobspec not to accept a SIGHUP, and the -h switch tells it to remain in the jobs table. I thought, cool, maybe if it stays in the the jobs table, I could also transfer it to another jobs table of another tty. (no, you can’t…)
but now I had a process on my hands that wasn’t attached to a terminal, and would just run forever unless I rebooted.
The while loop itself didn’t have a process ID, which is interesting, and because of the nature of while, the sleep commands PID kept changing, so a normal ps aux | grep slee[p] | awk ‘{print $2}’ | xargs kill -9 wasn’t working. (This post is loosing topic fast, but the slee[p] in the above command was a cool trick I learned so that I didn’t need a grep -v grep in there).
I *did* find that I could use ps to figure out the ppid (parent process ID) and just kill -9 that, but I was also interested in knowing for sure that it wasn’t in charge of doing something else important. A little digging around, and I came across the UNIX utility pstree which of course didn’t come on my mac, but I quickly figured out that it could be installed with
sudo port install pstree
Yesterday, I had done a similar thing with the UNIX command watch, which also nicely installed using port
And, for those who don’t know, the UNIX command watch is a great poller utility, that will display the first screen’s worth of output of any command, and update it on a regular basis.
I used ps | grep to find the ppid of the sleep process, then ran this command:
watch "pstree $PPID"This was way cool, as every ten seconds, I watched as the PID of sleep (the child process of this bash process I had just found) changed.
Take away:
sudo port install watch sudo port install pstree
I realized a while ago that I wanted to invoke my shell as a login shell when starting screen. This of course gives me immediate access to things in my .profile like aliases, etc.
shell -bash
Everywhere I read said to put that in your .screenrc file. On my Mac, OS X 10.5, however it seemed to have the (extremely) unwanted circumstance of changing my cwd whenever I started screen to my $HOME folder.
I was able to do some testing my remoting into a *fairly* vanilla fedora box and running the command:
cd /; screen -s -bash
This started bash as a login shell
shopt login_shell #=> login_shell on
but did not change my cwd.
I tried moving my .profile file to see if it was the culprit.
I finally came up with this hackish solution.
create file
screen_shell
and place in it the line
$SHELL -lI knew from other testing that
shell 'bash -l'didn’t work, course, now, having remembered that I had a similar experience with vi… I wonder if
shell bash\ -l
would work… (nope…)
so, I then changed my .screenrc file to read
shell /Users/bhenderson/.screen_shell
made sure that I did a
chmod u+x ~/.screen_shell
and off I went.
If anyone would like to add to my understanding of what was going on, or a better solution, please feel free to comment. thanks.
rsync -a /path/to/bar/ /path/to/foo/ # => /path/to/foo/[contents of bar] rsync -a /path/to/bar /path/to/foo/ # => /path/to/foo/bar/[contents of bar] cp -a /path/to/bar/ /path/to/foo/ # => /path/to/foo/bar cp -a /path/to/bar /path/to/foo/ # => /path/to/foo/bar
why can’t cp have the same source behavior as rsync?
btw, I found the solution on this blog:
mkdir target_directory cd source_directory cp -a . target_directory
(on the blog, the author does cp -ap, but that looks redundant according to the man page)
def x 5 end if false x = 3 end puts x # => ?
Ruby has a great method for enumerations called #each_with_index. It’s a handy way to iterate over a list of elements and and know where you’re at while doing it.
Erlang has a group of highly optimized list operations in the lists module (Try erl -man lists to see them all). We’re going to be using those to build our Erlang version of #each_with_index.
There are two methods from list we’re going to use: lists:seq and lists:zip. lists:seq simply returns a list of integers between a given range. For instance:
1> Seq = lists:seq(0, 9). [0,1,2,3,4,5,6,7,8,9]
lists:zip takes two lists (of equal length) and returns a list of tuples. Like so:
2> lists:zip([a,b,c], [1,2,3]).
[{a,1},{b,2},{c,3}]The last thing we need is a list comprehension, which is similar to each with a block in Ruby. For instance, in Ruby:
>> [:a, :b, :c].each { |element| puts element } a b c => [:a, :b, :c]
In Erlang we would do the following:
3> [io:format("~p~n", [Element]) Element <- [a,b,c]].
a
b
c
[ok,ok,ok] There is one difference here: the Erlang list comprehension returns a new list which is the value of each call to io:format. In this way an Erlang list comprehension is closer to Ruby’s #collect rather than #each.
We now have all the pieces to build our Erlang version of #each_with_index.
4> EachWithIndex = fun(L, X) -> [ X(Element, Index){Element, Index} <- lists:zip(L, lists:seq(1, length(L))) ] end.
Whats going on here?
lists:zip(L, lists:seq(1, length(L)))
creates a list of tuples with each tuple containing an element of L and a companion integer.
[X(Element, Index){Element, Index} <- lists:zip(L, lists:seq(1, length(L)))]
tells us to take that list of tuples and do a list comprehension on each of the elements, calling fun X in turn.
EachWithIndex = fun(L, X) -> ... end.
creates a fun (think lambda) and assigns it to EachWithIndex. You could just as easily create this as a regular function in a .erl file somewhere.
Now we can call our new EachWithIndex function by passing in a list and a fun:
5> EachWithIndex([a,b,c,d,e], fun(Element, Index) -> io:format("~p at ~p~n", [Element, Index]) end).
a at 1
b at 2
c at 3
d at 4
e at 5
[ok,ok,ok,ok,ok]A new plugin install and mount s3fs volume on an instance using PoolParty.
git clone git://github.com/jashmenn/poolparty-s3fs-plugin.git
NOTICE You must have already created your S3 bucket. This plugin will not
create it for you.
cloud(:app) ... s3fs(:bucket => "my-fun-bucket") ... end
This will be mounted at /mnt/my-fun-bucket
You can mount multiple buckets and/or change the mount point:
s3fs do bucket "my-fun-bucket" bucket "my-other-bucket", "/mnt/a-disk" end
I’ve created a PoolParty plugin that makes it dead-simple to install GitHub Repo is here.
or git clone git://github.com/jashmenn/poolparty-mrtg-plugin.git
Usage:
Declare mrtg in your cloud block
mrtg do monitor :cpu, :uptime, :memory, :open_files, :processes, :apache, :network_interfaces end

Today I gave a presentation and workshop titled “Getting Started with PoolParty and EC2″. The goal was to 1) be an introduction to the myriad of terms used in Amazon’s cloud computing infrastructure and to 2) be a practical introduction to PoolParty configuration and provisioning.
Posted below are the slides. The slides alone certainly are not enough for a complete introduction to PoolParty. However, I hope they have some information that is helpful to beginners.
Check out the PoolParty wiki for more documentation.
Nice little one liner to obtain your WAN IP address.
curl http://www.whatismyip.com/automation/n09230945.asp ; echo
Then alias that badboy E.g.:
alias whatsmyip='curl http://www.whatismyip.com/automation/n09230945.asp ; echo'
Happy day.
Today I wanted to copy a symlink to many different directories. So I tried the following:
for f in `find . -regex ''.*cp.*snippets''` ; do cp bbb.html $f/ ; done
Which returned:
cp: cannot stat `bbb.html': No such file or directory
bbb.html is a symlink and the default behavior of cp (I think) is to try and copy the actual file, which didn’t exist from the current directory. So just adding the -R made cp copy it as a symlink with the final command being:
for f in `find . -regex ''.*cp.*snippets''` ; do cp -R bbb.html $f/ ; done
I learned the other day about a neat shortcut for tilde expansion in bash.
$ ls ~-/
The neat thing about this expansion is that it does tab completion. What this lead me to discover is that you can also do ~N, where n is a number refering to your directory stack. (the bash man page says you can use the command `dirs’ to view the stack, but it doesn’t seem to work for me. When you put in a 0 (zero), it is the current working dir. Combined with tab completion, this gave me a great way for creating symlinks. Before, I had to do something like
$ ls `pwd`/
Which does do tab completion. But if you want to save a whopping 3 key strokes!, you can do something like this:
$ pwd /Users/bhenderson/programming/ruby/guides.rubyonrails.org $ ln -s ~0/index.html ~/Sites/ruby_guides $ ls -l !:$ ls -l ~/Sites/ruby_guides lrwxr-xr-x 1 bhenderson staff 68 Jan 12 08:47 /Users/bhenderson/Sites/ruby_guides -> /Users/bhenderson/programming/ruby/guides.rubyonrails.org/index.html $
Guide spidered from here.
I found this method the other day. Unfortunately, I forget where.
$ for f in `ls -1 | grep string`; do mv $f ${f/string/replace};done
I’d like to find a method of using the bash command `find’, but this is pretty clean, and I don’t yet know how to manipulate the `{}’ in find -exec {} \;
great site for explaining bash variable manipulation.
Just a quick tip:
If you’re having trouble getting do_mysql to install on Mac OS X. Try the following:
$ locate mysql_config /usr/local/mysql/bin/mysql_config
The directory /usr/local/mysql above is your mysql directory. Then try to install do_mysql with the following command (split for readability):
$ gem install do_mysql -- \ --with-mysql-dir="/usr/local/mysql/" \ --with-mysql-config="/usr/local/mysql/bin/mysql_config"
This solution was found here. I experienced the problem while trying to get merb to run with datamapper on mysql.
sake is a tool for system-wide rake tasks. It was created by Chris Wanstrath and is now maintained by postmodern. It provides a handy way to distribute generally-useful rake tasks. The advantage of sake over, say, a script in ~/bin is that 1) you have a predictable interface and 2) its easy to distribute tasks with sake -i http://any-url (in theory).
Ben Schwarz has written a great sake task for installing a ssh-public-key on a remote server. You can install it with sake -i http://github.com/benschwarz/sake-tasks/tree/master%2Fssh%2Fssh.sake?raw=true . (If you haven’t seen highline before, check it out. It’s a nice abstraction and clean alternative to using gets and puts.)
Based on Ben’s task I’ve created a task for installing remote git repos.
The above task will do two things:
There’s a bug in the above authentication code, did you catch it? For authentication, it will use your ssh keys if it finds it otherwise it will ask you for a password. However, if your ssh keys aren’t valid then it simply fails. Ideally it would ask you for a password and retry in this case.
I’m not too concerned about this however; if you’re creating a git repo remotely, you probably want to clone it and you also probably have your ssh keys setup to do so. (I probably shouldn’t be checking for a password at all.)
I believe sake is a great idea, but there is some rough edges in the current implementation.
Today, if you gem install sake there is a bug such that sake wont even run. Your best bet is to clone drnic’s repo sake >= 1.0.16 and install from there.
My guess is that this is because sake’s creator recently put out a request for someone to take over the project and the person who took it over hasn’t upgraded the rubyforge gem.
Another bug that seems to be specific to this version of sake, when I run sake -i the task names and namespaces are created but the ~/.sake file contains no code.
Again, this just seems to be a minor bug with the current version and as such I see it as temporary. I’m planning on working on a patch on for this, though I’m not sure I’ll fix it before someone else.
The built-in way to do sake task development is to write a little bit, then sake -i your file, then write a little bit more etc. This gets old fast. Because of that drnic has written a great project for sake task development. In that project you run sake testrun taskname.
drnic’s project is handy and makes sake task development a snap. However, I think this fact could slow the adoption of sake; it’s a barrier to entry if you have to install a second project just to develop the first.
I still think that the idea of sake is solid. There is definitely a need for easily distributable, reusable, system-wide rake tasks. Despite its current shortcomings, sake is definitely worth a look.
In order for a system to reproduce itself, it seems necessary for it to hold an encoded form of itself somehow. This idea, and the inevitability of the existence of DNA-like structures within living cells, is well-illustrated using computer code.
Here’s a quick and simple tip for using threads and Rakefiles:
task :one do puts "start one" sleep 10 * rand puts "one done" end task :two do puts "start two" sleep 10 * rand puts "two done" end task :three do puts "start three" sleep 10 * rand puts "three done" end desc "Submit all feed to amazon for SITE" task :do_all do threads = [] %w{one two three}.each do |number| threads << Thread.new(number) do |my_number| Rake::Task[my_number].invoke end end threads.each { |thread| thread.join } end
Running it gives something like the following:
$ rake do_all start one start two start three three done one done two done
Apparently my canon scanner-driver has a built-in music player.
The guys at Plugin-a-week have written a nice ActiveRecord state machine gem called state_machine.
One of the great things about state machines is that they often can be visualized. To that end I’ve written a small utility that will load a class that uses state_machine and produce dot output which you can use with graphviz.
This gem is currently used by the spree shopping cart. Let’s look at an example of how this can be used to visualize the Order object in this project:
Save the gist below to visualize.rb and chmod +x visualize.rb. The arguments are 1) the path to RAILS_ROOT of the project using state_machine and 2) the class you want to visualize. Try visualize.rb –help to see all the options.
ruby visualize.rb . Order | dot -Tsvg -Grankdir=LR > graph.svg
Gives us the following image:
Download the raw code (Requires ‘trollop’ gem).
Last night I gave a talk on my new gem Apriori.rb at the LA Ruby Meetup. Here are the slides from that presentation. Coby Randquist from Confreaks recorded the talk on his MacBookPro. I’ll see if I can get a copy and post it up here in the next couple of weeks.
Apriori.rb is a library to efficiently find item association rules within large sets of transactions. The goal is to find regularities in buying behavior. This library provides a thin ruby wrapper around Christian Borgelt’s C implementation of this algorithm.
Finding items that are frequently purchased together can be very useful in learning how to position products in your store or website. If you find that customers who buy product a also buy product b then you know to put a and b close together, thus increasing revenue.
An association rule is something like:
If a customer buys wine he buys cheese too.
require 'apriori' transactions = [ %w{beer doritos}, %w{apple cheese}, %w{beer doritos}, %w{apple cheese}, %w{apple cheese}, %w{apple doritos} ] rules = Apriori.find_association_rules(transactions, :min_items => 2, :max_items => 5, :min_support => 1, :max_support => 100, :min_confidence => 20) puts rules.join("\n") # Results: # beer -> doritos (33.3/2, 100.0) # doritos -> beer (50.0/3, 66.7) # doritos -> apple (50.0/3, 33.3) # apple -> doritos (66.7/4, 25.0) # cheese -> apple (50.0/3, 100.0) # apple -> cheese (66.7/4, 75.0) # NOTE: # beer -> doritos (33.3/2, 100.0) # means: # * beer appears in 33.3% (2 total) of the transactions (the support) # * beer implies doritos 100% of the time (the confidence)
More information and code samples available in the documentation (rdoc).
Install the gem:
gem install apriori
Get the source:
git clone git://github.com/jashmenn/apriori.git
Or view the source on github.
requires rubygems >= 1.2.0 . This is a requirement that hopefully will be changed in the future. But for now, know that if you don’t have rubygems >= 1.2.0 it will fail silently on the install. To update your rubygems version do:
gem update --system
Organize all files in a given folder by date. This is commonly used to organize a “Downloads” folder. Currently this script will only move files more than 24 hours old. This is to protect against moving a file as it is downloaded.
I love SafariStand. One of the features that I love is the sort-downloads-by-date feature. Now that I have moved to Firefox I really miss this feature. I been unable to find a good extension that will sort my downloads in a similar way. This script was written as an simple way to fill that gap.
I keep a ~/bin directory where I keep simple scripts such as this. Then setup a crontab such as the following:
*/10 * * * * /usr/local/bin/ruby /Users/nathan/bin/organize_folder_by_date.rb /Users/nathan/Desktop/Downloads
It is available on github: here (raw).
or
git clone git://github.com/jashmenn/download_sort.git
I really dislike getting screen-shots in the format of power-point files. Thankfully, 10.5’s Quick Look can help me preview power-point files. What I needed was a way to have Firefox automatically Quick Look all power-point files that I downloaded. Here’s how to do it:
Open up Script Editor and paste this:
on open filelist repeat with i in filelist do shell script "qlmanage -p '" & POSIX path of i & "' >& /dev/null &" end repeat end open
File > Save As…. Choose “Application” and save it somewhere it won’t move. I choose /Applications/ql.app.
Now simply choose ql.app next time you download a power-point file or set it up in Firefox’s Preferences > Applications.
qlmanage is the command-line tool to open files in Quick Look. By using AppleScript you are able to create this thin “application” that Firefox will trust and give a downloaded file (As opposed to a shell script, which Firefox will not let you choose as a file handler).
We’ve been using lftp for years here. It’s stable and has a volume of options. I just found out today that lftp has an option to set the order in which files are uploaded if you are using the mirror command. You can set it like so:
set mirror:order ‘*.jpg *.gif *.png *.js *.css * */’
This will send first jpg, then gif, then png files etc. This is very handy if you are mirroring an entire website and you want the images to go live before the html does.
Just wanted to make a note, string interpolation is faster than printf in Ruby. Example:
$ irb >> require 'benchmark' => true >> Benchmark.measure { 100000.times { "%s" % ["hello world"] } }.total => 0.21 >> Benchmark.measure { 100000.times { "#{'hello world'}"} }.total => 0.04
This post is an upgrade to the previous post about the unmarshalling of XML and JSON strings into rails objects, with arbitrarily deep object associations. As you may know if you are reading this, there doesn’t seem to be a way in rails to reverse to_xml and to_json when associations are included.
Example usage:
xml = firm.to_xml :include => [ :account, :clients ] firm = Firm.from_xml xml
firm.account and firm.clients will behave as intended (by default there does not seem to be a direct way in rails to unmarshall them.)
Here’s how to get from_xml and from_json defined for your ActiveRecord classes:
Create a file lib/extensions.rb with the following code:
module ActiveRecord class Base def self.from_hash( hash ) h = hash.dup h.each do |key,value| case value.class.to_s when 'Array' h[key].map! { |e| reflect_on_association( key.to_sym ).klass.from_hash e } when /\AHash(WithIndifferentAccess)?\Z/ h[key] = reflect_on_association( key.to_sym ).klass.from_hash value end end new h end def self.from_json( json ) from_hash safe_json_decode( json ) end # The xml has a surrounding class tag (e.g. ship-to), # but the hash has no counterpart (e.g. 'ship_to' => {} ) def self.from_xml( xml ) from_hash begin Hash.from_xml(xml)[to_s.demodulize.underscore] rescue ; {} end end end # class Base end # module ActiveRecord ### Global functions ### # JSON.decode, or return {} if anything goes wrong. def safe_json_decode( json ) return {} if !json begin ActiveSupport::JSON.decode json rescue ; {} end end
At the bottom of config/environments.rb, insert the line:
require 'lib/extensions' # custom class extensions
You can name the “extensions.rb” file anything else you want; just update the environments.rb file accordingly.
This is an improvement over the previous post, in that it can work even when your associations use the :class_name parameter, you’re not editing the vendor/rails files directly, and it can deal with hashes of the rails class HashWithIndifferentAccess.
Since my upgrade to OS X 10.5 I have been having a terrible time getting colors to work with git.
Originally I was using OS X 10.5.4, git version 1.5.3.1, and iTerm or Terminal.app. $TERM=xterm or xterm-color. I have color with PS1, ls, vim and most git tasks. However, git diff (or git show) always screws up the diff by showing the ESC[ characters instead of colors. For instance:
[nathan@nate ~/s3]$ git show 67d254ec17f ESC[33mcommit 67d254ec17fdc507765ddee1feb2a14e5896e79fESC[m
I searched and searched wasn’t able to figure out how to fix this. It was suggested on the github forum that I upgrade to git 1.5.6.4. Unfortunately not only did it not fix the color in git diff, it broke the color in git status which was working previously.
After about a week of poking around on and off I discovered that the problem was not git, but my GIT_PAGER which is more. If I tried GIT_PAGER=cat git-diff then the color output just fine. less and more use the same environment variable LESS (man less for details). And less was outputting the colors as raw escape codes.
man less shows that the option -R is defined as follows:
-R or --RAW-CONTROL-CHARS
Like -r, but only ANSI "color" escape
sequences are output in "raw" form.
That would do it.
After perusing the man page for a while I settled on adding this to my
~/.profile:
export LESS="-erX"
At the end of the day, this tip is really about less and how it interprets colors and probably has little to do with git. Even so, I only found this odd behavior while using git. Hopefully this post will help someone who is having similar issues.
As a side note, below is an example of how to configure your colors for git-diff and other commands.
[user]
name = Your Name
email = y...@yours.com
[color]
branch = auto
status = auto
diff = auto
[color "diff"]
meta = yellow
frag = cyan
old = red
new = green
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "status"]
added = yellow
changed = green
untracked = cyan
[alias]
st = status
ci = commit
co = checkout
br = branch
Next,
Recent Comments