Skip to content


Rails recognize_path with Engines

It turns out that Rails #recognize_path doesn’t recognize the path if it points to an Engine.

Here’s my solution: https://gist.github.com/jtanium/6114632

Posted in Rails, Tips and Tricks.


Copy Files from iTunes Playlist Util Script

A while ago, I found myself wanting to copy the files of an iTunes playlist. If the files are not in the same directory, or handful of directories, this can get tedious in a hurry.

Fret not: here’s a script to make your life easier. First, export your playlist as “Unicode Text“. Next, put the script below in a file such as “cp_it_pl.rb“. Then run it like:

$ cp_it_pl.rb my_playlist.txt cool_music/

Note: this script runs on Ruby 1.9+

require 'fileutils'
 
 
playlist = File.read(ARGV[0], mode: 'r', binmode: true, external_encoding: Encoding::UTF_16LE)
dest = Dir.new(ARGV[1])
 
if dest.nil? || dest == ""
  STDERR.puts "destination can't be blank"
  exit 1
end
 
utf8_playlist = playlist.encode("UTF-8")
 
utf8_playlist.each_line("\r") do |line|
  path = line.split("\t")[-1].chomp.split(":")[1..-1].join("/")
  next if path.nil? || path == ""
  abs_path = "/" + path
 
  puts "copying "+abs_path.inspect+" to "+dest.path
  FileUtils.cp abs_path, dest
end

Posted in Ruby, Tips and Tricks.


Untangle SQL Util Script

Have you ever wanted to check the values being inserted into a table?

Here’s a quick little script which parses an SQL insert statement and prints out the column name and corresponding value:

sql = <<-EOSQL
PASTE YOUR SQL HERE!
EOSQL
 
sql_matches = sql.match(/[a-z `]\((.*)\) values \((.*)\)/i)
columns = sql_matches[1].split(/, ?/)
values = sql_matches[2].split(/, ?/)
 
columns.each_with_index do |column_name, i|
  puts "#{column_name}: #{values[i]}"
end

Note: Consider the use of this script a code smell. If your table has so many columns this becomes necessary, consider normalizing your data.

Posted in Ruby, Tips and Tricks.


ActiveRecordError: items_count is marked as readonly

Yesterday, I was trying to add some counter caches to some of my objects, and ran into a problem. The problem is obvious now that I understand what was happening, but getting there took a while.

I couldn’t remember the syntax and everything so when I Googled rails cache counter one of the top results was the ASCIIcast Episode 23 Counter Cache Column.

The ASCIIcast said to run something like the following in the migration to populate the counter column:

Order.all.each { |o| o.update_attribute(:items_count, o.items.count) }

But it failed with this:

ActiveRecord::ActiveRecordError: items_count is marked as readonly
	from /Users/youruser/.rvm/gems/ree-1.8.7-2011.03@yourproject/gems/activerecord-3.0.12/lib/active_record/persistence.rb:121:in `update_attribute'

Sometime between the posting of the original Railscast and Rails 3.0.12, ActiveRecord started marking the counter column read only, for an obvious reason: you shouldn’t be updating it.

I modified the code to update the record without instantiating the object, like so:

Order.all.each { |o| Order.update(o.id, :items_count => o.items.length) }

… and wouldn’t you know it, it works now.

Posted in Rails, Ruby, Software Development, Tips and Tricks.

Tagged with , , .


ActiveRecord #build_association Does Not Construct a New Object

I learned valuable tidbit about belongs_to and #build_association: if there is already an associated object, a new one isn’t constructed.

Let’s consult the docs:

build_association(attributes = {})
Returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key, but has not yet been saved.

It says it “[r]eturns a new object of the associated type,” but that’s only true if the association is nil. If there is already an associated object, it just sets all the attributes to nil.

Let’s check it out:

example_app $ rails console
Loading development environment (Rails 3.0.10)
1.8.7 :001 > note = Note.find(2)
 => #<Note id: 2, account_id: 42444, note_text: "Magni et soluta repellendus voluptatem placeat volu...", ...> 
1.8.7 :002 > orig_account = note.account
 => #<Account id: 42444, dba_name: "Spinka, Conroy and Emmerich", ...> 
1.8.7 :003 > orig_account.object_id
 => 2207807220 
1.8.7 :004 > note.build_account
 => #<Account id: nil, dba_name: nil, ...> 
1.8.7 :005 > orig_account
 => #<Account id: nil, dba_name: nil, ...> 
1.8.7 :006 > note.account.object_id
 => 2207807220 
1.8.7 :007 > 

Fun, huh? Fortunately, it’s not too difficult to work around, simply construct your own object, *but* don’t forget to add the association by foreign key!

Posted in Rails, Ruby, Software Development, Tips and Tricks.

Tagged with .


Bash Prompt for RVM and Git

I’ve seen a lot of examples where people have a cool Bash prompt showing their Ruby version, RVM gemset, and/or their Git branch.

What I couldn’t find is a complete example that helped me understand what was going on and worked properly on OS X.

Here’s what I did, and maybe you’ll find it useful.

ESC="\033" # This is the escape sequence
NO_COLOR="$ESC[0m"
IRED="$ESC[1;31m" # ANSI color code for intense/bold red
IGRN="$ESC[1;32m" # ANSI color code for intense/bold green
 
# From http://railstips.org/blog/archives/2009/02/02/bedazzle-your-bash-prompt-with-git-info/
# I had to change 'git-symbolic-ref' to 'git symbolic-ref'
function parse_git_branch {
  ref=$(git symbolic-ref HEAD 2> /dev/null) || return
  echo " ["${ref#refs/heads/}"]" # I wanted my branch wrapped in [], use () or <> or whatever
}
 
# from http://ariejan.net/2010/04/25/ruby-version-and-gemset-in-your-bash-prompt-yes-sir
function rvm_version {
  local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}')
  [ "$gemset" != "" ] && gemset="@$gemset"
  local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}')
  [ "$version" != "" ] && version="$version"
  local full="$version$gemset"
  [ "$full" != "" ] && echo "${full}:" # the colon at the end is a delimiter, you could use a space instead
}
 
#PS1="\h:\W \u\$" # For reference, here's the default OS X prompt
#export PS1="\$(rvm_version)\W \$(parse_git_branch)\$ " # Without the colors
 
# I had to put the \[ and \] down here, as opposed to $IRED, to avoid wrapping funkiness.
export PS1="\[$IRED\]\$(rvm_version)\[$NO_COLOR\]\W\[$IGRN\]\$(parse_git_branch)\[$NO_COLOR\] \$ "

I encountered all kinds of weirdness getting the colors to work. The problems all centered around getting the \[ and \] correct. If you’re having problems where the wrapping is wrong, or arrow keys or the backspace causes your prompt to disappear, check your \[\]‘s. The rule of thumb is the characters you’re escaping should be wrapped in them. Keep in mind, the color codes don’t seem to include a ] at the end.

I got my color codes from here. At the bottom of that page is a dandy script which prints out all the colors and backgrounds making it easy to find a good color combination for your terminal.

References:
Ruby version and gemset in your Bash prompt? Yes sir!
Bedazzle Your Bash Prompt with Git Info

Posted in Bash, Git, OS X, Ruby.

Tagged with , , , .


Service-Oriented Design with Ruby and Rails

I got a copy of this book recently because I want to explore using web services more in some of my projects.

If you are going to work through the examples, just be warned, they aren’t going to work out of the box. I don’t know who was supposed to be checking they work, but they dropped the ball.

This is where I’m going to keep track of all the things I had to change/tweak/massage to get it to work.

Chapter 1: Implementing and Consuming Your First Service

  • You also need Rack-Test gem install rack-test
  • The Rackfile and spec/service_spec.rb won’t work. I have created a gist where you can view my comments about what I had to add.

Posted in Rails, Ruby, Software Development, Tips and Tricks.


Apache, WordPress, Passenger, and You

I was trying to get a web application running here along side WordPress, but, in essence, Apache wasn’t letting mod_rails handle the request.

Several Google searches turned up precisely zero answers. After poking around I found the .htaccess file that WordPress so kindly generates for you:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

What this little guy is doing is displaying a nice pretty 404 page, instead of a plain old ugly Apache page. It does this by looking to see if there is a file or directory matching the file name in the request.

Obviously, there aren’t files and directories to correspond with your web app urls. The solution is, quite simply, to tell Apache not to go looking for files and directories when the request needs to go to your web application. So how do you that? Like this:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/myrailsapp.*
RewriteRule . /index.php [L]

Voila! Now Apache won’t try looking for any files or directories when the request begins with “myrailsapp.”

Posted in Apache, Rails, Tips and Tricks.


OS X Server SUS Hack

I’ve been having a problem with the Software Update Server on OS X, it never generates the catalog files. As far as I can tell, the swupd_syncd process seems to get “stuck” and never generate the catalog file.

Here’s how I “fixed” it. I added the following to root’s crontab:

17 3 * * * /bin/cat /var/db/swupd/html/content/catalogs/index.sucatalog.apple | /usr/bin/sed 's/swcdn.apple.com/10.0.5.100:8088/' > /var/db/swupd/html/content/catalogs/index.sucatalog
19 3 * * * /bin/cat /var/db/swupd/html/content/catalogs/index-leopard.merged-1.sucatalog.apple | /usr/bin/sed 's/swcdn.apple.com/10.0.5.100:8088/' > /var/db/swupd/html/content/catalogs/index-leopard.merged-1.sucatalog
23 3 * * * /bin/cat /var/db/swupd/html/content/catalogs/index-leopard-snowleopard.merged-1.sucatalog.apple | /usr/bin/sed 's/swcdn.apple.com/10.0.5.100:8088/' > /var/db/swupd/html/content/catalogs/index-leopard-snowleopard.merged-1.sucatalog

Keep in mind this is the crontab for the root user (I used sudo crontab -e), not the system crontab, which is normally located in /etc/crontab. Speaking of which, where the hell did that go?

Seriously, Apple, WTF? Why is it so friggin’ hard to make a service that pulls a bunch of files off the web and generates an XML file? If I weren’t pressed for time, I’d replace swupd_syncd with a hundred lines of Ruby code.

When it comes to OS X Server, I’m aghast at how difficult it is to get the simplest things to work. The “enterprisey” Apple stuff is awesome in theory, but horrible in practice. It took days to get the OpenDirectory stuff to work properly.

Even still I have all kinds of problems. For some reason OpenDirectory decides it’s just going to take a nap, and it will take three minutes (or more) for anyone on the network to do anything. Imagine how fun it is trying to change tabs in Workgroup Manager and it takes three minutes between each mouse click.

Here’s another: periodically OpenDirectory will decide to disable a mobile user. For those of you who’ve never experienced this, when that happens, the client machine will disable the local user account. And good luck getting that re-enabled (after you enable it in WGM). You can run this command a bunch of times:

sudo pwpolicy -a LOCAL_ADMIN_SHORTNAME -n /Local/Default -u USER_SHORTNAME -enableuser

But it only works 25% of the time. The rest of the time you get messages about user not being disabled or not having a shadowhash. Sometimes if you just reset the user’s password that will re-enable the account. Otherwise reboot it a whole bunch of times until it finally figures out the account is enabled in OpenDirectory.

Posted in OS X, Rant, Tips and Tricks.


Queue Wait Spikes with Passenger and NewRelic

So I’ve been struggling with “Queue Wait” spikes on NewRelic. I think I have pretty much determined that the spikes are caused by Passenger spinning up new threads to handle additional requests. Here’s what I did.

First I restarted my app, and let it run for a bit, then I used “passenger-status” to see what the threads were doing:

----------- General information -----------
max      = 30
count    = 3
active   = 0
inactive = 3
Waiting on global queue: 0

----------- Domains -----------
/srv/rails/myapp/current: 
  PID: 9734    Sessions: 0    Processed: 48      Uptime: 18m 54s
  PID: 9704    Sessions: 0    Processed: 49      Uptime: 19m 5s
  PID: 9706    Sessions: 0    Processed: 57      Uptime: 19m 2s

I’d basically just run it again every few minutes to see what was happening, and then I got this:


----------- General information -----------
max      = 30
count    = 4
active   = 0
inactive = 4
Waiting on global queue: 0

----------- Domains -----------
/srv/rails/myapp/current: 
  PID: 9822    Sessions: 0    Processed: 34      Uptime: 4m 57s
  PID: 9706    Sessions: 0    Processed: 103     Uptime: 26m 43s
  PID: 9704    Sessions: 0    Processed: 107     Uptime: 26m 46s
  PID: 9734    Sessions: 0    Processed: 75      Uptime: 26m 35s

Mon May 17 13:54:20 MDT 2010

(I actually started running passenger-status; date so I could have the time I ran the command). The above tells us that at roughly 13:49 Passenger spun up another thread. Refreshing NewRelic, I saw this:

I spent more time investigating, and it does seem that the queue wait spikes, roughly correspond to times that Passenger starts more threads.

Posted in Rails, Ruby, Software Development.

Tagged with , , , .