Rubriigiarhiiv: Programming

Faster RubyMine RSpec with Vagrant

I use RubyMine and Vagrant for my Rails development and run RSpec specs from RubyMine for convenience. The problem is that every time I start rspec, it takes a few seconds to connect to the box, before actually doing anything. This is especially annoying when running single spec which should be fast.

vagrant ssh is slow to connect

That’s probably because vagrant ssh-config takes most of that time to sort things out:

When researching this issue, some people mention DNS or other Vagrant provider specific issues, but they complain of an order of magnitude slower (30-40 sec) connection. Might just be that I have everything set up correctly and it just takes that much time to get the configuration.

But what this means is that if you run RSpecs from RubyMine, they are slow to start, because RubyMine executes vagrant ssh-config every time (RUBY-16186).

Direct SSH to the rescue

Fortunately, direct SSH with keypair authentication is blazing fast:

So, to take advantage of that you need to:

  1. set up SSH configuration
  2. configure RubyMine remote ruby over SSH, not Vagrant
  3. Add RubyMine helpers to RUBYLIB to be able to start persistent spring instance.

Set up SSH configuration

Vagrant might be using their vagrant_insecure_private_key for the SSH or, in my case, Parallels custom keypair, as I don’t use VirtualBox. So run this command to find out which key is in use:

Now we know the IP address of the box and what keyfile is used. For easier access, I symlinked the key file to my .ssh folder:

You can try out SSH connection:

Configure RubyMine to use remote ruby over SSH

Next step is to configure new Ruby SDK for the project. Open Preferences and navigate Language & Frameworks > Ruby SDK and Gems, click + button and pick New remote…. Then fill in the data as shown in the screenshot and when closing dialog, ensure that the newly added ruby is selected as active.

Configure Remote Ruby Interpreter

Now specs should still run (but take several seconds every time to boot up Rails, because spring is shut down after every connection).

Note: I actually use landrush to manage development boxes names and so I can configure remote ruby with a domain name and not worry about IP address changes when recreating the devbox.

Add RubyMine helpers to RUBYLIB

The problem above is that spring closes itself down every time SSH connection is closed. One could start a long-running spring from terminal SSH, but that would result in RubyMine complaining that it can not load teamcity formatter:

This is because RubyMine injects a special formatter into rspec so that it can parse the output better. Thanks to Oleg at Jetbrains (RUBY-16324) I discovered that the required formatters are present in the vagrant box and all I need is to add them to ruby load path, before starting spring.

So, I added following lines to my /home/vagrant/.bashrc:

This sets up RUBYLIB variable with RubyMine helpers. I skipped over testunit folder, as I do not use that, but feel free to add that also if you need it.

Let the specs fly

Now, just SSH into your Vagrant box, start Spring, e.g. by running:

And then RubyMine can re-use the already running Spring server to speed itself up.

GIT merge-svn

How to use GIT to merge two SVN branches

TL;DR: Download the git-merge-svn script here

I’ve been using git for years now but had to start using SVN for some projects. I found that GIT is good enough Subversion client too, especially as I retain the ability to commit often and rebase my work on top of commits from other devs (on the SVN side).

The only question arose – can I merge two SVN branches so that GIT log will show the merge?

The git-svn manual states that one should avoid all git clone|merge|pull|push activity when using git-svn.

But git log does show merge history that was created in Subversion – how does it do that?

svn:mergeinfo

Subversion does not support actual merge of branches (more like cherry-picking), but since version 1.5 Subversion supports the svn:mergeinfo property that is used to track what has been merged into this folder previously.

Digging some more into the matter, I found out that GIT supports setting svn:mergeinfo property on the SVN branch when dcommit‘ing:

NB! the svn:mergeinfo is overwritten with whatever is given on the command-line, so be careful to list previous merges too.

While more recent git version added the config parameter to automatically set this property:

I had some troubles with the automatic mergeinfo – for one reason or the other GIT calculated it wrong and I couldn’t get it to work.

SOLUTION: git-merge-svn

To automate the process, I wrote a shell script git merge-svn which can be used to merge two SVN branches with correct svn:mergeinfo set on the dcommit.

The script handles both situations:

  • the branch is not merged in git – will do git merge beforehand
  • the branches have been already merged in git (but not in SVN) – will traverse until previous ancestor for the merged commit revisions.

UPDATE: Thanks theantway and haraldreingruber for patches – the script now:

  • always does full merge (no fast-forward) so that SVN can fully understand and
  • does not die on first merge (no previous mergeinfo)

Download the git-merge-svn script here

Example usage

With this script I was able to produce these merges solely on git-side and retain the merge info so that GIT graph shows the log nicely:

git-merge-svn result

  1. Make some commits on devel6
  2. dcommit devel6 to SVN (required to get SVN revision numbers for the commits)
  3. check out testtunk6 – yes, I know I made a typo in the name ;-)
  4. git merge-svn devel6

The last commant outputs:

Safari New Window

Safari New Window icon

Previously I have written AppleScripts to open new windows for TextMate, Sublime Text 2 and also Safari. But the latter was somehow corrupt when using with Mac OS X 10.8.3, so I rewrote it based on previous two, adding features in the process:

  1. Checks if Safari is already running and creates new window (without switching spaces)
  2. Activates Safari if it’s not running yet.

The full source code is here:

Go a head and download the updated script here:

 

Download Safari New Window

 

Rails redirect_back_or_default

In a recent project I found myself writing recirect_to :back alot, and then found myself worrying that what if for some reason there is no :back.

Drawing inspiration from this blog, I wrote two helpers in my application_controller.rb.

The store_location stores current URI (or referer URI in case of non-GET request) into session[:return_to] for later usage:

And redirect_back_or_default tries its best to redirect the user to somewhere, in the following order:

  1. previously stored session[:return_to]
  2. Referer URI
  3. Given default URI
  4. or root_url if all else fails

The code itself

I’ve found that when rewriting redirect_to :back, notice: 'something' into redirect_back_or_default-call, adding this alias helps:

But of course, if you are testing your code (and you should be), it’s better to stick to one variant of above and use tests to catch all erroneous incarnations.

Rails 3: Merge scopes

I run into a case where I had User.search method and I wanted the GroupMember model be searchable by the user’s attributes. The most DRY way to accomplish this in Rails 3 is to merge scopes. In the User model:

NB! It’s important to have the User’s field names fully qualified so that they won’t be applied to the GroupMember table. And in the GroupMember model:

Now it’s possible to search for GroupMembers by the User attributes:

This results in SQL query:

Sublime Text 2 New Window (via AppleScript)

Building upon my older post on opening new window in Text Mate 2, I now threw together small script to do the same in Sublime Text 2.

While Sublime Text 2 is superb text editor, it is not Mac native, thus it’s even less probable that a new Mac-style Dock icon menu will appear in near future, that allows opening new window quickly. Thus a helper application is in order.

SublNewWindow

Based on the original TMNewWindow code, only small modifications were needed. One unexpected behavior was with detecting working state of the application. For whatever reason the original script gave errors when run against Sublime Text 2.

Again, the AppleScript application is linked below and feel free to send me updates and patches if needed.

 


 

uses of Ruby’s Object#tap

Ruby 1.9’s Object#tap method has always seemed useful to me, but until now I hadn’t met the chance to use it. Every other time it seemed like abusing it in some way.

Now I came to an old code. Consider this:

I needed to turn that maxlength into a conditional attribute (omiting it if it’s nil).
One way would have been extracting the attributes into a separate variable:

But this separates visually the cgi.text_field() call from it’s arguments, which I don’t like. Tap to the resque:

Now, isn’t that nice! (OK, maybe it isn’t, but at least it is encompassed in the method call and makes it easy to spot all attributes).

Restore DBD::MySQL::Database#quote method

For whatever reason, Ruby DBI and DBD have axed the quote method from their midst, breaking compatibility with previous versions. Sadly I couldn’t find any clues as to why it was removed (actually, bluntly commented out).

Fortunately I was able to unearth some hints how to restore this method and with an added fix to NilClass, the result seems to be working fine:

Just place this in some file and require it in your code.

 

Mount partitions like a boss (AppleScript)

How to quickly mount partitions when the need arises? A small AppleScript to help you out.

The need

No good comes without little drawbacks. When I swapped ODD with HDD, I noticed that it was quite a bit noisier than SSD and even compared to similar MBP with HDD in original bay (probably because ODD bay has a slot that lets noise out easily). So, now I tend to eject the secondary disk when I don’t need it, so my Mac can spin it down. All nice and dandy, but reattaching it when needed was a bit tedious.

The Script

This script asks for which of the partitions to mount and then iterates with diskutil through the selection.

Download

You can copy-paste the above script to AppleScript Editor and adjust it to your needs, or you can download this as a ready to use application.

MountPartitions.zip

 

Ruby (on Rails) toolchest for Windows users

Setting up solid Ruby on Rails developer box based on Windows can be tedious task. More so than on other platforms, because vanilla Windows is meant for end user and lacks proper development tools that exist on other platforms. But fear not, there are many good people out there that have jumped through multitude of hoops to get different parts of the ecosystem working. All that remains is to build a solid foundation for developmer from them. Jätka lugemist