ray_apps_blog

May 21, 2008

Using mod_rails with Rails applications on Oracle

Filed under: mac, oracle, rails, ruby — Raimonds Simanovskis @ 11:49 pm

As many others I also got interested in new mod_rails deployment solution for Rails applications. And when I read how to use it for development environment needs I decided to try it out.

As you probably know I am using Mac for development and using Oracle database for many Rails applications. So if you do it as well then at first you need to setup Ruby and Oracle on your Mac.

After that I installed and did setup of mod_rails according to these instructions and these additional notes.

One additional thing that I had to do was to change the user which will be used to run Apache httpd server as otherwise default www user did not see my Rails applications directories. You should do it in /etc/apache2/httpd.conf:

User yourusername
Group yourusername

And then I started to fight with the issue that ruby which was started from mod_rails could not load ruby-oci8 library as it could not find Oracle Instant Client shared library. And the reason for that was that mod_rails launched ruby with very minimal list of environment variables. E.g. as DYLD_LIBRARY_PATH environment variable was not specified then ruby-oci8 could not find Oracle Instant Client libraries.

The issue is that there is no documented way how to pass necessary environment variables to mod_rails. Unfortunately mod_rails is ignoring SetEnv settings from Apache httpd.conf file. Therefore I needed to find some workaround for the issue and finally I did the following solution.

I created executable script file /usr/local/bin/ruby_with_env:

#!/bin/bash
export DYLD_LIBRARY_PATH="/usr/local/oracle/instantclient_10_2:$DYLD_LIBRARY_PATH"
export SQLPATH=$DYLD_LIBRARY_PATH
export TNS_ADMIN="/usr/local/oracle/network/admin"
export NLS_LANG="AMERICAN_AMERICA.UTF8"
/usr/bin/ruby $*

and then in Apache httpd.conf file I changed RailsRuby line to

RailsRuby /usr/local/bin/ruby_with_env

As a result in this way I was able to specify necessary environment variables before Ruby and Rails was started and after this change ruby-oci8 libraries were successfully loaded.

You can use this solution also on Linux hosts where you will deploy Rails applications in production.

Currently I still have issue with mod_rails that it fails to execute RMagick library methods (which is compiled with ImageMagick). I get strange errors in Apache error_log:

The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
[error] [client ::1] Premature end of script headers:

When I was running the same application with Mongrel then everything was running correctly. If anyone has any ideas what could be the reason please write some comment.

April 24, 2008

How to setup Ruby and new Oracle Instant Client on Leopard

Filed under: mac, oracle, ruby — Raimonds Simanovskis @ 1:52 pm

Introduction

We waited for it long, long time and finally it has arrived - Oracle Instant Client for Intel Mac. I was lucky to test beta version of the client already for the last couple of weeks and so far everything was working OK. Therefore as the final version is now available to everybody I am here rewriting my previous instructions on how to get Ruby working with Oracle on Mac.

Installing Oracle Instant Client for Intel Mac

At first you need to download Oracle Instant Client for Intel Mac. Download “Instant Client Package - Basic” and “Instant Client Package - SDK” and also I suggest “Instant Client Package - SQL*Plus” if you would like to have command line sqlplus utility.

Unzip downloaded archives and move it where you would like to have it - I am keeping it in /usr/local/oracle/instantclient_10_2. Then go to this directory and make symbolic links for dynamic libraries

sudo ln -s libclntsh.dylib.10.1 libclntsh.dylib
sudo ln -s libocci.dylib.10.1 libocci.dylib

Then I recommend to create and place somewhere your tnsnames.ora file where you will keep your database connections definitions - I place this file in directory /usr/local/oracle/network/admin.

Then finally you need to set up necessary environment variables - I place the following definitions in my .bash_profile script:

export DYLD_LIBRARY_PATH="/usr/local/oracle/instantclient_10_2"
export SQLPATH="/usr/local/oracle/instantclient_10_2"
export TNS_ADMIN="/usr/local/oracle/network/admin"
export NLS_LANG="AMERICAN_AMERICA.UTF8"
export PATH=$PATH:$DYLD_LIBRARY_PATH

Use your path to Oracle Instant Client if it differc from /usr/local/oracle/instantclient_10_2. And as you see I also define NLS_LANG environment variable - this is necessary if your database is not in UTF8 encoding but in Ruby you want to get UTF-8 encoded strings from the database. Specifying this NLS_LANG environment variable you will force that Oracle Instant Client will do character set translation.

After these steps relaunch Terminal application (so that new environment variables are set), specify database connection in tnsnames.ora file and try if you can access your database with sqlplus from command line.

Ruby installation

If you are using Leopard then I assume that you are using preinstalled Ruby which is the simplest option. I tried to compile Ruby from sources on Mac OS X Leopard but when I compared performance then original Ruby was a little bit faster on some benchmarks and therefore I sticked with original one.

Compile and install ruby-oci8

Download the latest version of ruby-oci8 (version 1.0.0 at time of writing this post).

As Oracle Instant Client is available just for Intel i386 architecture you need to change in file /usr/lib/ruby/1.8/universal-darwin9.0/rbconfig.rb line 17 to:

'-arch i386'

Then go to directory where you extracted ruby-oci8 source and execute ruby-oci8 standard installation sequence:

ruby setup.rb config
make
sudo make install

After that you can change back file /usr/lib/ruby/1.8/universal-darwin9.0/rbconfig.rb line 17 to:

'-arch ppc -arch i386'

Now try

ruby -r oci8 -e "OCI8.new('scott', 'tiger','orcl').exec('select * from emp') do |r| puts r.join(','); end"

or similar to verify that you can access Oracle database from ruby.

That’s it! Please write in comments if something is not working according to these instructions.

April 5, 2008

Video from Euruko 2008

Filed under: mac, oracle, rails, ruby — Raimonds Simanovskis @ 11:22 pm

I made short video from Euruko 2008 conference where you can see Matz, Koichi, JRuby guys, DrNic ar me as well :)

I posted my presentation slides in my previous post.

August 27, 2007

How to setup Ruby and Oracle client on Intel Mac

Filed under: mac, oracle, ruby — Raimonds Simanovskis @ 1:01 am

!!! Update !!!

New version of this instruction for Intel Macs with Leopard is available here.

Introduction

I have been using Oracle technologies for many years but just some time ago discovered Ruby and Rails. As I had ideas how to make Ruby on Rails frontends for existing Oracle based systems I started to explore how to use Ruby on Rails together with Oracle databases.

Just recently I switched from PC notebook to MacBook Pro and unfortunately found out that Oracle Instant Client is not yet released for Intel Macs. As there is no promise when it will be released and as I could not wait for that I decided to make old PowerPC version of Oracle Instant Client to run on Intel Mac. As I didn’t find any good description how to do that I decided to write description of it by myself - hopefully it will help others.

Universal or “fat” binary Ruby

The first thing is that you need to get “universal” or “fat” binary installation of Ruby - it means that it contains both Intel and PowerPC (PPC) binary code. You will need PPC version of Ruby when you will work with Oracle and you will need Intel version of Ruby when you will do other things. PPC code is running in emulation mode on Intel processors and therfore is slower as well as there are some compatibility issues with some other libraries (I will mention later what issues I found out).

It is possible to get and install precompiled Ruby either from MacPorts or using Ruby One-Click Installer. But I prefer to compile Ruby from source code as it gives me more control what is installed and where. I used Hivelogic guide to compile Ruby from source code.

Here are my additional notes what I changed to Hivelogic guide to make “fat” binaries.

Installing “readline”

At first you need to install “readline” shared libraries. At first I tried to make them from “readline” library source code but I always got just Intel binaries. Therefore I found and downloaded “readline” library installer package with universal binaries and installed it. If you previously installed Intel binary of “readline” library then it is better to restart Mac to ensure that new dynamic library will be loaded.

Compiling Ruby

Next you need to download and extract Ruby 1.8.6 source code.

Before running “configure” command I made the following change in “configure” file:

# Choose a default set of architectures based upon platform.
case "$target_os" in
darwin*)
    TARGET_ARCHS="ppc i386"
    ;;

You can specify this also on command line but this change ensures that you will not forget it :) Then you need to run “configure” script with additional parameter at the end:

./configure --prefix=/usr/local --enable-pthread --with-readline-dir=/usr/local \
--enable-shared --enable-fat-binary

After running “make” hopefully you will get everything compiled and you should get “fat” ruby binary. You can verify it with the following command and should see the following result:

$ file ruby
ruby: Mach-O universal binary with 2 architectures
ruby (for architecture ppc):    Mach-O executable ppc
ruby (for architecture i386):   Mach-O executable i386

If you do not see that ruby binary contains both ppc and i386 executables then something went wrong. If it is OK then you can do “sudo make install” to install binaries in target directories.

Make PPC and “fat” versions of Ruby

As you will need to be able to force to run PPC version of Ruby later then we need to extract PPC executable in a separate file and store original “fat” binary in another file:

ditto -arch ppc /usr/local/bin/ruby /usr/local/bin/ruby_ppc
mv /usr/local/bin/ruby /usr/local/bin/ruby_fat

Then I recommend to create simple scripts that will help you to switch between “fat” and PPC versions of Ruby:

ppc_ruby.sh:

#!/bin/bash
sudo ln -fs /usr/local/bin/ruby_ppc /usr/local/bin/ruby

fat_ruby.sh:

#!/bin/bash
sudo ln -fs /usr/local/bin/ruby_fat /usr/local/bin/ruby

So when you need to have PPC version of Ruby then run “ppc_ruby.sh” script and when you need “fat” version (which will actually run Intel binary) then run “fat_ruby.sh” script.

Install Oracle Instant Client for PPC

Install Oracle Instant Client according to the following description.

Compile and install ruby-oci8

I used the following description as a basis but some additional changes were needed for ruby-oci8-1.0.0-rc3 compilation.

Open ruby-oci8 README file and find section “=== Intel Mac” where are described what to do to compile ruby-oci8 on Intel Mac.

Before running any ruby scripts you need to run ppc_ruby.sh script to switch to PPC binary.

If you compiled “fat” Ruby from source code then you need to modify file /usr/local/lib/ruby/1.8/fat-darwin8.10.1/rbconfig.rb according to README file (make backup of file before modifications). If you installed Ruby from binary distribution then find where is located your rbconfig.rb file.

  • find lines with CONFIG["CFLAGS"] and CONFIG["LDFLAGS"] and CONFIG["ARCH_FLAG"]
  • remove “-arch i386″ if present (was not present in my case)
  • and add “-arch ppc” to all of these lines.

Make and install ruby-oci8 and if it finishes successfully then restore rbconfig.rb file from backup.

Try

ruby -r oci8 -e "OCI8.new('scott', 'tiger','orcl').exec('select * from emp') do |r| puts r.join(','); end"

or similar to verify that you can access Oracle database from ruby.

Congratulations! You have managed to connect to Oracle DB from Ruby on Intel Mac! If you got some issues at some point then please write it in comments and I will try to help with that.

Post installation notes

If you previously installed (or if you will install in future) any Ruby gems with native extensions (e.g. Mongrel or MySQL C API) then you need to reinstall these gems with “fat” Ruby (i.e. running “fat_ruby.sh” script and then “sudo gem install”). It will ensure that all gems will also have “fat” native extensions so that you can run them both in PPC Ruby and Intel Ruby.

Known issues with PPC Ruby

So far I have got the following issues with running PPC version of Ruby:

  • Capistrano is failing to make SSH connection when running in PPC Ruby (I was testing with new Capistrano 2.0). Therefore you need always to switch to “fat” Ruby before running “cap deploy”.
  • As I also wanted that MySQL is running under PPC I got some issues with MySQL native extensions compilation - I solved them using the following description.
  • ruby-ldap connections were failing when running in PPC Ruby within Ruby on Rails. I managed to fix it by putting “require ldap” as a first line in config/environment.rb file.

Blog at WordPress.com.