Blog
what did i learn today

For my current job we have two 2.3.5 rails sites, of which I already succesfully upgraded one to rails 4. For the other we still need to start the migration, and we were asked to install new windows servers to run the rails servers on in the meantime (let's not digress why they choose windows, in a business environment Windows servers are still preferred, and let's be honest; they are easier to maintain and manage then *nix servers at first sight).

So whatever: I had to install the rails 2.3.5 on a new Windows 2012 server.

This proved problematic, since the new ruby 1.8.7 comes with the new rubygems, and this does not work nicely with rails 2.3.5.

So step 1: install the old ruby 1.8.7 (p302), the old gems and run the rails server. This worked.

But then I saw this one thing I really needed to improve. So I migrated the project to the latest 1.8.7 and rails 2.3.18, use bundler for gem dependencies. On my development box this worked like a charm (Macbook Pro). So then I deployed this back on the server, and then the following happened:

C:/Ruby187/lib/ruby/1.8/pathname.rb:290:in `[]': no implicit conversion from nil to integer (TypeError)
    from C:/Ruby187/lib/ruby/1.8/pathname.rb:290:in `chop_basename'
    from C:/Ruby187/lib/ruby/1.8/pathname.rb:343:in `cleanpath_aggressive'
    from C:/Ruby187/lib/ruby/1.8/pathname.rb:331:in `cleanpath'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rails-2.3.18/lib/rails/rack/log_tailer.rb:9:in `initialize'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:54:in `new'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:54:in `use'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:73:in `call'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:73:in `to_app'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:71:in `inject'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:73:in `each'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:73:in `inject'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.1.6/lib/rack/builder.rb:73:in `to_app'
    from C:/Ruby187/lib/ruby/gems/1.8/gems/rails-2.3.18/lib/commands/server.rb:95
    from script/server:3:in `require'
    from script/server:3

What was going on here? Apparently in the rails/rack/logtailer.rb is the following code:

class LogTailer
  def initialize(app, log = nil)
    @app = app

    path = Pathname.new(log || "#{::File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath

And the cleanpath is somehow crashing. I tried googling this, to no avail.

Of course:

  • rails 2.3.18: who uses that still?
  • ruby 1.8.7 is deprecated
  • and deploying on windows servers

So I was on my own. I tracked the error down to the cleanpath_agressive which called the chop_basename recursively to remove superfluous . and .. redirections.

I am guessing the problem is that on windows, a path starts with a drive-letter, like D:\ or C:\ which messes up the ending of the cleanpath_aggressive loop.

Instead of really diving in, the path handed down to cleanpath in my case, did not need any cleaning, and furthermore, an uncleaned path would still work.

So I added an initializer config\cleanpath_bug_fix.rb with the following code:

if RUBY_PLATFORM =~ /mingw/
  # on windows the Pathname.cleanpath crashes on windows paths, instead of fixing it thoroughly
  # just ignore it
  class Pathname
    def cleanpath_aggressive
      self
    end
  end
end

Now my rails 2.3.18, using ruby 1.8.7p374 runs on Windows Server 2012R2. Woot ;)

actionmailer attachments on windows

I have been having troubles sending e-mails using ActionMailer on windows. The simple code-sample: [ruby] my_filename="my_image.jpeg" attachment "image/jpeg" do |a| a.body = File.read(my_filename) a.filename = File.basename(my_filename) end [/ruby] did not work. I did find an attachment inside my e-mail, but it was corrupt. It took me a while to figure out it could be something related to my development platform, which unfortunately still is windows (not for long). On windows reading binary files is less obvious, apparently, so you need to write: [ruby] my_filename="my_image.jpeg" attachment "image/jpeg" do |a| a.body = File.open(my_filename,'rb') { |f| f.read} a.filename = File.basename(my_filename) end [/ruby] ... and this will work! :) I you have to combine normal e-mail content and one or more attachments, this then becomes something like: [ruby] # we send a mail to respond to a mention def mention_response(given_subject, addressee, pdf_attachment = nil) from APP_CONFIG["mail"]["from"] recipients addressee.to_a subject given_subject content_type "multipart/mixed" part "text/html" do |p| p.body = render_message("mention_response", :thr_name => thr_name) end attachment :content_type => "application/doc" do |a| a.filename File.basename(pdf_attachment) a.body File.open(pdf_attachment, "rb") { |f| f.read } end unless pdf_attachment.nil? end [/ruby] Nice :)

mongrel_service beta troubles with space

I am switching back from using thin inside a service to mongrel_service, because when my thin-process is killed somehow, the service stills seems to be running. Mongrel_service can cope with this much better: it also keeps a check on your ruby process and restarts it if needed (at least in the old version, i hope the 0.4.beta3 prerelease version behaves the same). When using the mongrel_service (gem install mongrel_service --pre) on ruby 1.8.7 you can no longer have a space inside the name. So if you run the following command: [bash] mongrel_rails service::install -N "Name with a space" -c c:\path\to\your\app -p 4000 -e production [/bash] there will be no output as to whether it succeeded or not on XP, on Windows Server 2008 a more appropriate error is shown; but the service will not be created. The trouble is the name: it contains a space, and apparently that is no longer allowed. On the old MRI and previous mongrel_service it was not a problem. The old version, however, does not work in ruby 1.8.7 from rubyinstaller.org, due to a dependency to some very specific Visual C++ code regarding service communication (and now the ruby is compiled using gcc). Luckily there is an easy fix, as suggested by Luis Lavena himself: [bash] mongrel_rails service::install -N name_without_space -D "Name with a space" -c c:\path\to\your\app -p 4000 -e production [/bash]

So i am developing and deploying Ruby on Rails applications on Windows. Recently i started experimenting with the newer versions of ruby (mingw32platform). One of the side-effects is that the mongrel-service, which i always used to deploy my rails-applications no longer works on mingw32. And aside of that, i have read on various instances [ref] that thin should be better (more efficient) than mongrel. But i still want to install it as a service. First off, you need to download and install the Windows Resource Kit. This contains the executables to make a service of any executable or script. Then create the service running (in the console): [bash] C:\Program Files\Windows Resource Kits\Tools> instsrv "[my_service_name]" "c:\program files\Windows Resource Kits\Tools\srvany.exe" The service was successfuly added! Make sure that you go into the Control Panel and use the Services applet to change the Account Name and Password that this newly installed service will use for its Security Context. [/bash] This will add an empty entry in the registry, which actually still does nothing. To get it working, we have to start regedit, and navigate to the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services[my_service_name] Create a new key (folder) named Parameters. This will contain the settings of our actual application that will be run as a service. Add the following String Values: [bash] [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services[my_service_name]\Parameters] Application=c:\ruby\bin\ruby.exe AppDirectory=[my_ruby_app_folder] AppParameters=c:\ruby\bin\thin start -p 4000 -e production [/bash] Assuming that c:\ruby\bin is your ruby folder, and you want your thin to listen to port 4000. Once that is done, start the service, and your rails application should be up and running :)

... but Windows Server 2008

Unfortunately, to do this on Windows 2008 you need to perform some extra steps. As you can't install the resource kit on Windows Server 2008R2 for some peculiar reason, and at the time of this posting, i have not found a Windows Server 2008 Resource Kit Tools, so i took the following steps:

  1. copy the "srvany.exe " from the "Windows Server 2003 Resource Kit Tools " to a suitable location on your Win2008 server (e.g. C:\Windows\System32\ )
  2. use "sc " to create a new service that launches "srvany " (e.g. sc create MyService binPath= C:\Windows\System32\srvany.exe DisplayName= "My Custom Service" )
  3. using RegEdit create a "Parameters " key for your service as before and fill it with the 3 string values A bit more work, but not too much.

mongrel-service?

And just today I discovered an update of mongrel_service was announced, so you can still work using mongrel_service instead of using thin and manually creating the service. What you need to do:

  • install mongrel service: gem install mongrel_service --prerelease
  • create the service as before: mongrel_rails service::install -N myapp -c c:\my\path\to\myapp -p 4000 -e production That is much easier of course.

working on Windows Server 2008R2 64-bit, installing ruby 1.8.7, ruby-oci8 ran into the following error, after requiring 'oci8' : LoadError 193: %1 is not a valid Win32 applicationOn this machine a 64bit version of Oracle was installed. So the OCI.dll was a 64-bit version. The fix seemed easy: copy a 32-bit version of the OCI.dll. But I had to copy (from another 32-bit machine)

  • OCI.dll (32-bit)
  • MSVCR71.dll
  • ... and ORAOCIEI10.dll

to my ruby\bin folder, and then everything worked. Copying just the OCI.dll and MSVCR71.dll gave the puzzling error OCIError: OCI library initialization error.