MetaSkills.net

The Ultimate OS X Snow Leopard Stack For Rails Development - x86_64, MacPorts, Ruby 1.8/1.9, SQL Server, SQLite3, MySQL & More

Posted On: September 5th, 2009 by kencollins
If you are interested in using RVM with a MacPort base for the SQL Server stack, check out this article.
I have written an updated article on the MacPorts installation of the latest RubyODBC. It includes information pertaining to utf8 support.

This guide is all encompassing but primarily focuses on the benefits of MacPorts, second the development stack for SQL Server and lastly on anything else a rails developer might need on OS X. If you are on a Mac, possibly running Snow Leopard and x86_64 is near and dear to your heart, this article is for you. If you do not "have" to use SQL Server, you can safely skip those sections and get to the Ruby1.9/Apache2/SQLite3/MySQL stuff.

A small forward. If you are developing rails applications on a modern OS such as Snow Leopard and your needs never make it out of the shallow end of the default Ruby and SQLite3, then this how-to might not be for you. However if you find yourself needing more and you want it to be easy and optimized for your architecture, then I highly suggest MacPorts.

Even though this tutorial is based on MacPorts, there are alternatives if you have the guts. One is called Homebrew by Max Howell, which offers a very easy package management system that is closely knit to OS X's own libraries. If your smart enough to manage the sheer amount of dependencies and different ways OS X wants to pull you when using their libraries, then have at it. I failed horribly and I consider myself somewhat smart. This article also focuses on running multiple versions of ruby, specifically 1.8.7 and a flavor of 1.9.x. Again to this end there are other solutions. One recent one is called Ruby Version Manager (rvm) by Wayne Seguin. An incredible library, but something I could not use with my level of compiling source due to the fact that all the dependencies needed for SQL Server to ODBC are hard enough to get in place for one ruby installation. RVM has it's use, but if you just need two versions of ruby with a full 64-bit stack to SQL Server, read on.

Install MacPorts

If you have not done so already, go download MacPorts and run the installer and follow their installation instructions. At the time of this writing, the current version is 1.8 and has tons of new stuff for Snow Leopard. If you use bash, the default shell on OS X, then add this to your ~/.profile.

export PATH="/usr/local/bin:$PATH"
export MANPATH="/usr/local/share/man:$MANPATH"
export INFOPATH="/usr/local/share/info:$INFOPATH"

However, if you have changed your default shell to ZSH, then put this in your ~/.zshenv file. I highly recommend switching your default shell to ZSH.

path=(/opt/local/bin /opt/local/sbin /opt/local/apache2/bin $path)
manpath=(/opt/local/share/man $manpath)
infopath=(/opt/local/share/info $infopath)

Important x86_64 Arch Notice

If you are running Snow Leopard and if your processor supports 64-bit, say a Core 2 Duo (consult your manual), then I highly suggest you set the MacPorts build_arch to force it to x86_64 for all installed ports. Remember, even if you have a unibody MacBook that can not boot the 64-bit kernel yet, that does not mean you are not running 64-bit apps. If your chip supports it and your on Snow Leopard, turn it on. Here is how.

Open up your MacPorts config file located at /opt/local/etc/macports/macports.conf. Around line 59, find the section that has the build_arch and set it to x86_64. I have done this on both my unibody MacBook 13" and Nehalem MacPro and everything has installed and works perfectly. This includes, ruby, git, and everything in between. See screenshots below for proof. Lastly, as a good habit, always run sudo port selfupdate before installing ports. This makes sure you have the latest port files.

Installing Ruby 1.8.7

By now Ruby 1.8.7 is the new 1.8.6. It will be the de-facto low level version that supports the enterprise. Frankly, 1.9.2 is really where it is at, but we all have our day jobs right. Either way it is good to have this version installed. You may ask why, 1.8.7 comes on OS X by default now in Snow Leopard? Correct, but the goal here is to get a base ruby installed whose libs are known and compiled the way we want them for our low level SQL Server libraries and their dependencies. The goal here is to avoid dependency hell.

$ sudo port install ruby  

$ which ruby
/opt/local/bin/ruby

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]

Running that port install may have taken awhile, but let me show you something. Do you see that below? That's right, it's 64-bit ruby just like the default OS X installed 1.8.7. In fact, it's even a bit faster for some reason. So remember, using MacPorts this way means that everything you install that supports it, will be built for 64-bit.

Ruby 1.8.7 64-bit Activity Monitor

Lets get RubyGems package management up and running. Thanks again to MacPorts this is really easy. Some advice. Never use MacPorts to update RubyGems! We just used it to get it installed easily and quickly and in the right scope. If you need to update RubyGems, just use it's own self update feature.

$ sudo port install rb-rubygems

Feeling good? Maybe like me, you wouldn't mind getting side tracked. If so, go ahead and install Subversion and/or Git. I personally like to install both of these since I use Git to manage my Subversion repos too.

$ sudo port install subversion
$ sudo port install git-core +svn

The SQL Server Connection Stack

So back on track. The low level connection stack for SQL Server is pretty easy. We need unixODBC and not OS X's installed iODBC. After that FreeTDS needs to be installed with the +odbc variant so that it prefers the installed unixODBC. If you did not get side tracked above, these two installs could pull in a lot of dependency installs too and take some time. When we are done the final stack for connecting Rails to SQL Server will look something like this. Ruby/Rails => ActiveRecord SQL Server Adapter => DBI Gem w/DBD-ODBC => Ruby ODBC => unixODBC => FreeTDS => SQL Server.

$ sudo port install unixODBC
$ sudo port install freetds +odbc

If all went well, you should see a configuration file notice after FreeTDS installs. This is just the port reminding us that we will ultimately have to configure FreeTDS to point to our SQL Server box. We'll get back to that later, for now, let's check that the install is looking good.

$ which tsql
/opt/local/bin/tsql

$ tsql -C
Compile-time settings (established with the "configure" script)
                            Version: freetds v0.82
             freetds.conf directory: /opt/local/etc/freetds
     MS db-lib source compatibility: no
        Sybase binary compatibility: no
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 5.0
                              iODBC: no
                           unixodbc: yes

$ tsql I
locale is "en_US.utf-8"
locale charset is "utf-8"

See that last line after tsql -C? It says unixodbc is a go! That's important. If for some reason you do not see this, then I suggest reinstalling unixODBC and FreeTDS in that order again. Also note the output of tsql I and check out the locale settings. On Mac OS X, this seems to default to the utf-8 stuff we would expect. Possibly due to the default LANG env var is set to en_US.utf-8. However, on other systems this may note be right. See the configure FreeTDS section below for what to do if this is the case.

Right. That completes the UNIX'y low level parts to get us talking to SQL Server, now to put the focus back on Ruby again by installing a few gems that will be needed. Here are the ones critical to this setup. Please consult the adapter's README for update to date version information on the approved/latest gems for DBI.

$ sudo gem install dbi -v 0.4.1
$ sudo gem install dbd-odbc -v 0.2.4
$ sudo gem install activerecord-sqlserver-adapter

Almost there, we need one more piece, the Ruby ODBC bindings, so we can talk to the low level unixODBC. At the time of this writing, the MacPort portfile for rb-odbc was stuck at 0.9995 while the ruby odbc project page reports that the latest version is 0.9997. So here is a little lesson on how to edit a portfile to get our desired results.

$ port file rb-odbc
/opt/local/var/macports/sources/rsync.macports.org/release/ports/ruby/rb-odbc/Portfile

$ port file rb-odbc | xargs mate

The first command simply shows you how you can get MacPorts to revel where the port file is located. The second shows how you can pipe that result to xargs to get TextMate to open the portfile. Now that we have the port file in front of us, let's edit it so that it pulls the latest. First change all occurrences of the version to latest, in this case from 0.9995 to 0.9997. Lastly, download your target version from the ruby odbc project page and do a MD5 checksum on it. In my case, when I downloaded 0.9997, the md5 checksum is 36d21519795c3edc8bc63b1ec6682b99. Now change the odd md5 in the portfile to this new one, hit save, and close. Let's try it out.

$ sudo port install rb-odbc +utf8

So without little fuss, that should have worked. Did you notice how we have the +utf8 variant there? If your like me and have national/unicode columns in your database, this is a good thing. The adapter has tests and support for unicode as well.

Configure The SQL Server Stack

First, let's configure FreeTDS to point to our server. Assuming you have TextMate a simple mate /opt/local/etc/freetds/freetds.conf should get it open for us. FreeTDS even put in a few examples at the bottom of the file, I typically comment these out and add my own. In this example I am naming my server "my_dev_server". Note that tds version section, I personally use tds version 8.0 and have tested this against my stack on all SQL Server types with the ActiveRecord tests. Some have reported that they have errors unless the use 7.0. Your mileage may vary. Save and close the file. UPDATE: As noted above when running tsql I, if you do not see a utf-8 locale setting, you may have to add this line client charset = UTF-8 to your configuration file. Here is a thread on how to set tsql's client character set.

# A typical Sybase server
# [egServer50]
#   host = symachine.domain.com
#   port = 5000
#   tds version = 5.0

# A typical Microsoft server
# [egServer70]
#   host = ntmachine.domain.com
#   port = 1433
#   tds version = 7.0

[my_dev_server]
  host = 192.168.1.58
  port = 1433
  tds version = 8.0

It has been noted that Windows user may want to include client encodings and character sets that set UTF-8 values. If you are running on Windows, try out this style freetds conf.

[YOURSERVER]
 host             = yourserver.com
 port             = 1433
 tds version      = 7.0
 text size = 64512
 client encoding  = UTF-8
 client charset   = UTF-8

So after you have added your own server here, it is now time to configure unixODBC to use FreeTDS. Let's copy the default distribution files to the correctly named ones that unixODBC will look for.

$ sudo cp /opt/local/etc/odbc.ini.dist /opt/local/etc/odbc.ini
$ sudo cp /opt/local/etc/odbcinst.ini.dist /opt/local/etc/odbcinst.ini

Open up the newly copied /opt/local/etc/odbcinst.ini file. More than likely, this will be the only time you ever edit this file. Add a FreeTDS configuration to it like so. No personal configuration options here, this just links up the MacPort installed unixODBC and FreeTDS.

[FreeTDS]
Decscription = FreeTDS driver for SQLServer
Driver = /opt/local/lib/libtdsodbc.so
Setup = /opt/local/lib/libtdsodbc.so
FileUsage = 1

So the last thing is to create some DSNs in your /opt/local/etc/odbc.ini file. It is very likely that you could edit this file often. Perhaps you do a lot of development and DB server changes. My personal file has over 20 some DSNs here. Here is one example. The name and description of the DSN is up to you. Take note how I made the server name "my_dev_server" line up to that used in the FreeTDS conf file. That is important. Flavor this to your tastes.

[my_dev_server_dsn]
Driver=FreeTDS
Description=My Server Connection
Servername=my_dev_server
Server=my_dev_server
Port=1433
Database=killer_app

Here is an example of what your database.yml will look like. So by now you should be able to connect and work with your database. I have this working on quite a few Macs. If you found any issues, let me know, but a good place to start is running the adapter tests. That is of course if you have the stack setup right.

development:
  adapter: sqlserver
  mode: ODBC
  username: rails
  password: secret
  database: killer_app
  dsn: my_dev_server_dsn

Going The Extra Mile With Ruby 1.9.x

Here is a little trick that I put in an article called MultiRuby The MacPorts Way. Testing Your Rails Apps With Ruby 1.9. Follow the steps in this post to get 1.9.x installed and switchable between your default 1.8.7 install.

Remember, RubyGems already comes in 1.9 and that tutorial leaves your installed gems under 1.9 empty. Do the right thing and install gems on an as needed basis under 1.9. As for the ruby-odbc which is installed in the 1.8's vendor ruby directory, we will need to trick MacPorts to recompile and reinstall that for us. Here is how I did it. First make sure you in the right ruby version.

$ ruby -v                                 
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]

Now we need to trick MacPorts to forget about the previous install so it will build and use the extconf.rb of the ruby 1.9 installation. Here are the commands to softly remove rb-odbc from MacPorts memory. If you want, you can change rm -rf to just mv and move these files to some other place.

sudo rm -rf /opt/local/var/macports/receipts/rb-odbc
sudo rm -rf /opt/local/var/macports/software/rb-odbc
sudo rm -rf /opt/local/share/doc/rb-odbc

Now you can tell MacPorts to reinstall ruby-odbc and it should create a new odbc.bundle in your /opt/local/lib/ruby1.9/site_ruby/1.9.1/i386-darwin10/odbc.bundle.

$ sudo port install rb-odbc +utf8

Here is the proof that I have 1.9 installed, working with SQL Server adapter and 64-bit. Thanks to the chruby ZSH function described in my other post, I can easily switch between my ruby installs.

Ruby 1.8.7 64-bit Activity Monitor

Complete The Marathon!

Installing apache2 and passenger, yes all 64-bit happy.

$ sudo port install apache2
$ sudo gem install passenger
$ sudo passenger-install-apache2-module

How about a more common setup for SQLite3? If you took the side track and installed subversion from above, then you already have SQLite3 installed via MacPorts. If not, that's easy to fix. Here is how to install it and the ruby sqlite3 gem. I have done this for both my 1.8.7 and 1.9.x install above and again I am all 64-bit happy and passing all my tets.

$ sudo port install sqlite3
$ sudo gem install sqlite3-ruby

Installing MySQL and the ruby drivers are a bit more involved. This will get it installed and your launch control setup to act as if your box is a server, ie. load MySQL when it starts up.

$ sudo port install mysql5-server
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
$ sudo -u _mysql mysql_install_db5
$ sudo /opt/local/share/mysql5/mysql/mysql.server start
 Starting MySQL
 SUCCESS!
$ sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

Nice, fully 64-bit and passing all the ActiveRecord tests for me. Note, sometimes you will have to reset your shell for new path binaries to become usable. It's always a good idea to open a new shell post a port install If you get an unfound mysql_install_db5, try opening a new shell. Pay attention to some of the output from that command too. For instance, if you want to set a root user password. I choose not to do this for a dev DB, but I do like to limit the connections so that only local connections can be used by editing the conf file. To create yourself a my.cnf file, copy one of the templates in /opt/local/share/mysql5/mysql, I choose to copy the large conf like so sudo cp /opt/local/share/mysql5/mysql/my-large.cnf /opt/local/etc/mysql5/my.cnf. Then I edit the conf file and uncomment the link that says "skip-networking". That way no one on the local network can hit my DBs. Lastly, here are some helpful aliases that I use.

alias my_stop="sudo launchctl stop org.macports.mysql5"
alias my_start="sudo launchctl start org.macports.mysql5"
alias my_rs="my_stop ; my_start"
alias myconf="mate /opt/local/etc/mysql5/my.cnf"

MySchizoBuddy

  HOMEPAGE  | September 6th, 2009 at 03:57 AM
MySchizoBuddy How about installing ruby dependencies via macports and then compile Ruby Enterprise Edition by Phusion. Just for readers, You can use Porticus http://porticus.alittledrop.com/ its a gui frontend to Macports

Ken Collins

  HOMEPAGE  | September 6th, 2009 at 01:44 PM
Ken Collins

@MySchizoBuddy I'm sure you can do that and it is nice to know there is a MacPort GUI out there. Interesting, but GUI's are not my thing. I'm sure some will find it helpful.

I just updated the article with SQLite3 and MySQL directions. So hopefully others will find that useful too. Lastly, I have never needed REE in my development environment. The RAM savings just do not stack up as a needed thing for me but I'm sure what you suggest would work just fine :)

Nick Tidey

  HOMEPAGE  | September 8th, 2009 at 01:44 AM
Nick Tidey Thank you very much for the comprehensive write up!

Josh

  HOMEPAGE  | September 11th, 2009 at 12:43 PM
Josh Thanks for the guide its great, although I'm getting stuck at the first hurdle... When installing ruby I'm getting this error: ---> Computing dependencies for ruby ---> Activating readline @6.0.000_1+darwin Error: The following dependencies failed to build: readline Error: Status 1 encountered during processing. Any clues to why this is happening?

Dave

  HOMEPAGE  | September 15th, 2009 at 11:51 PM
Dave Thanks for this write up. It works perfectly!

Stephan

  HOMEPAGE  | September 21st, 2009 at 09:34 AM
Stephan almost working :) tsql works but isql gives me : [IM002][unixODBC][Driver Manager]Data source name not found it's like it does not finds the proper odbc.ini file...

essdee

  HOMEPAGE  | September 21st, 2009 at 11:27 AM
essdee tsql and isql work for me. iodbctest does not. I have odbc.ini and odbcinst.ini in /Library/ODBC. Where does freetds.conf have to be located?

Ken Collins

  HOMEPAGE  | September 21st, 2009 at 12:41 PM
Ken Collins

@Stephan & @essdee, if you are using iODBC and anything outside of the /opt directory, you have done something wrong. FreeTDS and especially the ruby ODBC binding want and prefer unixODBC. I think I made this point in my article too.

Azabaj

  HOMEPAGE  | September 25th, 2009 at 11:05 AM
Azabaj Hi, I've foudd and interesting problem. I've used the gems mentioned in the post with freetds to successfully connect to a legacy ms sgq database. After I've upgraded to snow leopard, get the following error when I try to conenct to the database: Product.first /Library/Ruby/Gems/1.8/gems/dbd-odbc-0.2.4/lib/dbd/odbc/statement.rb:41: [BUG] Bus Error ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0] and exits from ruby shell. I've recompiled freetds with unixodbc, recompiled the neccessary gems but it doesn't help. I've recompiled the ruby-odbc bingings but still got errors. tsql -C says it's using the unixodbc. do you have any idea?

Ken Collins

  HOMEPAGE  | September 26th, 2009 at 08:28 PM
Ken Collins @Azabaj That path for ruby is the Mac's ruby, not the ruby that should be installed via MacPorts into /opt/local/bin/ruby. Made sure you have your PATH setup correctly and have "everything" including ruby installed into the /opt dir and make sure your PATH ENV uses that dir.

azabaj

  HOMEPAGE  | September 27th, 2009 at 11:13 AM
azabaj Thanks for your answer. The fact is, I'm using the ruby shipped with leopard and everything was worked fine. After upgrading to snow leo, only the ruby-odbc was messed up (other gems are working fine.). So, if I install ruby from the macports, then I should install rubygems and all the gems I use for that "ported-ruby" and that's what I would like to avoid. However, I've spent 1.5 days trying to figure out whats going on, so it doesn't matter spending another hour on rebuilding my ruyb env from macports if it's truly neccessary:) (no guarantee, I know)

Ken Collins

  HOMEPAGE  | September 27th, 2009 at 12:20 PM
Ken Collins @Azabaj I love Mac! I love Ruby. Take my advice, do not try to mix the ruby that talks to SQL Server with your Mac's ruby. Trust me! Go into /opt and your life will be easier. Regardless of what worked before.

azabaj

  HOMEPAGE  | September 28th, 2009 at 09:14 AM
azabaj I've installed ruby from ports, reinstalled the most improtant gems for that specific project and the ruby-odbc and it works:) Thank you, for your advice! Now, I'm going to install all the other gem for my other projects.

Ted Thibodeau Jr

  HOMEPAGE  | September 29th, 2009 at 11:36 AM
Ted Thibodeau Jr I'm curious to learn whether the iODBC update for Snow Leopard resolves the issues you had with it. http://www.iodbc.org/dataspace/iodbc/wiki/iODBC/Downloads I don't know why you say that RubyODBC prefers unixODBC, when there's no such note anywhere in the RubyODBC docs -- http://ch-werner.de/rubyodbc/ -- and indeed there is more mention of iODBC than unixODBC.... Similarly, what's the basis for your declaration that FreeTDS prefers unixODBC? I'm somewhat disturbed by your creation of new files at /opt/local/etc/{odbc.ini,odbcinst.ini}. This seems very likely to lead to confusion over time. Why not make these links (hard or soft) to the pre-existing /Library/ODBC/{odbc.ini,odbcinst.ini} (recommended, System DSNs and ODBC settings) or ~/Library/ODBC/{odbc.ini,odbcinst.ini} (User DSNs and ODBC settings)?

Ken Collins

  HOMEPAGE  | September 29th, 2009 at 07:28 PM
Ken Collins

@Ted I was mistaken about FreeTDS not liking iODBC. I was quoting from memory and after looking again, I found the reason. It is in DBI's ODBC DBD. The below comment is from that source.

# Requires DBI and the 'ruby-odbc' package to work, and unixodbc (iodbc # WILL NOT WORK).

About your comment on the creation of opt's own odbc.ini and odbcinst.ini to match the MacPort unixODBC install. I do not see anything disturbing about this. Especially since the point of my directions is to stay away from mixing default Mac components.

Like I said to @Azabaj, I love Mac, but this stack is fraught with hidden dangers that newcomers to ruby/rails or users installing from source may not be aware of. If you have the skill, do what you want and feel is right, run the tests and educate us all. Cheers, Ken.

Tom

  HOMEPAGE  | October 13th, 2009 at 11:22 AM
Tom Thanks for the great detail! I followed and understood most everything! Unfortunately, when I launch IRB and try to load a record I get the following error: DBI::DatabaseError: IM002 (0) [iODBC][Driver Manager]Data source name not found and no default driver specified. Driver could not be loaded I'm not sure why it is using iODBC? If I run tsql -C, it shows iodbc NO and unixODBC YES? Where should I be looking?

Ken Collins

  HOMEPAGE  | October 14th, 2009 at 04:37 PM
Ken Collins @Tom We talked on IM about this... but what happened is that you had your /opt/local/bin and /opt/local/sbin at the end of your path vs the beginning.

Ted Thibodeau Jr

  HOMEPAGE  | October 19th, 2009 at 11:20 AM
Ted Thibodeau Jr

@Ken - Can we connect by email or IM or something?

I very much don't understand the motivation to avoid using default components on any OS, nor the preference to install redundant packages for the same task, whether different versions or entirely different packages ... but I hope that you will help us get the default stack working properly, whether or not you then choose to use it.

I'd especially like to at least get the non-native unixODBC vs Apple-chosen iODBC piece straightened out, even if you continue to prefer the build-from-source path to Ruby connection, over the install-pre-built path we documented on RubyForge for the OpenLink ODBC Adapter for Ruby on Rails / Active Record and/or the DBD::ODBC build instructions on iODBC.org.

If there's something not working in that default/native stack, we'd appreciate hearing directly about it, so we can work on getting it fixed, whether the issue lies in our own gear or one of the other packages. Figuring out, writing up, and recommending workarounds just extends the life of such issues and increases confusion, benefiting no-one in the end.

Ken Collins

  HOMEPAGE  | October 19th, 2009 at 11:43 AM
Ken Collins

@Ted I see where you coming from but I still think you are missing my point. Let me walk you thru a series of examples and perspectives on where I am coming from so you can see my view. I certainly see your view and am not saying that yours is wrong or mine is better. We are just coming from different camps. If you have any feedback or want to talk on the side, my email can be found on the colophon/resume page here.

First let's talk about your "workaround" theory. This is so not one of them! I did not come up with this stack because I had issues and needed to work around something in a black-box manner vs solving the real issue. As a matter of fact black-box hacking around is 100% against my nature. I choose to have ruby 1.8.7/1.9.1/REE/etc outside the Mac env because I like it. I like that my 1.8.7 is 15% faster than what is installed by Apple (your mileage may vary). I like not mixing things with their stuff for this particular stack because it suits me and is easy to do and seems to keep me upgrade worry free. I compare this to someone not linking "Preview.app" and just installing "Acrobat Reader". Both are there and both are usable and none is a workaround for the other. FYI, I prefer "Preview.app" :)

Now about the other issue with the DBI's documented issue with iODBC. I've spent quite a bit of my time contributing to the SQL Server adapter code. In fact... it's not even fair to quantify it as contributing. I frankly assumed the project and wrote and maintain quite a bit of the code. Making that adapter run in 2000/2005/2008 in 2.x and in the upcoming 3.x rails is no small task. It is hard work and I have pushed changes and upstream patches when I find the time. I am in the middle of writing my first iPhone application and still maintain enough time to contribute to quite a few OSS projects. All that and still contributing my time to local Ruby/ObjC user groups. I pick my battles and do what I can and feel that I have done a great job so far.

If you have love for iODBC and default components and the skill to contribute to those projects and hence after the fact the SQL Server adapter project, just do it. Now this is not a personal attack on you... but it is a peeve of mine that 95% of the people that contribute to the adapter or middle stack can not even run the tests or frankly care. They just say if I hacked this line it "works" and tell me to take that hack or leave it. This means that my love for my day job kicks in and I have to do it for them. Please do not fall into this category. If you want to help and advocate fixing something then just please do it. But please do not make the assumption that I am performing workarounds or that yours is the best only way. As software developers, we should know better.

Björn

  HOMEPAGE  | October 23rd, 2009 at 04:58 AM
Björn Hello Ken, first of all - thank you very much for this how-to. Actually, this was the first how-to ever that explained the connectivity to SQL Server correctly. I managed to get it working in minutes, as opposed to days like on Ubuntu. The SQL Server connectivity sure needs a lot of things sitting in the right place, doesn't it. You saved me a lot of headaches. It would be great if you could maintain this how-to and update it should the need arise. Also, what I would like to know is a convenient way to start and stop Apache and MySQL-Server in one go, through the command line. I would like to be able to stop my whole web development stack and free the resources. Right now I have Apache (from MacPorts) always "on" through launchctl. Cheers Björn

Ken Collins

  HOMEPAGE  | October 23rd, 2009 at 09:22 AM
Ken Collins

@Bjorn Thanks very much for the positive feedback. I do plan to keep this page updated and more importantly the wiki on the adapter's github site now has contributions on the stack for getting things up and running and that includes Ubuntu to. I published this article mainly to link from that wiki page.

About the stop/start stuff. As most of my friends know, and joke me about, I have a huge profile. Since I use zsh and not bash, it's called my zshkit. Here are a few alias (works in bash too) that I have for managing some things.

# MySQL
alias my_stop="sudo launchctl stop org.macports.mysql5"
alias my_start="sudo launchctl start org.macports.mysql5"
alias my_rs="my_stop ; my_start"
alias myconf="mate /opt/local/etc/mysql5/my.cnf"
# Apache
alias apconf="mate /opt/local/apache2/conf ; sleep 1 ; mate /opt/local/apache2/conf/extra/httpd-vhosts.conf"
alias apstop="echo 'Stopping Apache2:' && sudo apachectl stop"
alias apstart="echo 'Starting Apache2:' && sudo -E apachectl start"
alias apr="apstop ; sleep 3 ; apstart"

Jacob Riff

  HOMEPAGE  | October 26th, 2009 at 03:08 AM
Jacob Riff Thanks for your walk-through. I am having some problems with ruby-odbc. I have compiled it with --with-odbc-dir=/usr/local/unixODBC-2.2.14/lib but when I run the test.rb file in the ruby-odbc folder, it still uses iODBC. Can you explain how ruby-odbc knows witch ODBC to use? Everything else is working perfectly.

Ken Collins

  HOMEPAGE  | October 26th, 2009 at 11:51 AM
Ken Collins

@Jacob It sounds like your working against the grain of my article, perhaps you are using Homebrew? I ask because you have unixODBC in your /usr/local and not opt. If so, then you are running in the dependencies and crossed wires I ran into many times. Having ruby over here, this over there and that over yonder does not work well unless you really know what your doing. Without knowing your path, and where you decided to put your other parts, I'm no where near able to help.

Perhaps start over and do it all in opt?

Jacob Riff

  HOMEPAGE  | October 26th, 2009 at 05:48 PM
Jacob Riff Thanks for your reply. I actually got it to work - I now have stock ruby, unixOBDC, freeTDS and ruby-odbc running on Snow Leopard. I can't believe the amount of hacking I had to do to make it work. I have made a blog post about it here: http://digitaljacob.riff.dk/?p=9 I hope that somebody can use it.

Hugh Evans

  HOMEPAGE  | November 5th, 2009 at 03:17 AM
Hugh Evans I recently set up my new macbook and used Homebrew and RVM for all of this and it was a piece of cake. Best thing was I didn't have to make a single change to the underlying system.

I wrote a half-arsed article about it here, but I really should write a full guide like yours because it is a great set up.

Ken Collins

  HOMEPAGE  | November 5th, 2009 at 11:08 AM
Ken Collins @Hugh Good show, looks like HomeBrew has come around since I used it long ago. FYI, I have added your article under the adapters wiki page. Right now it is marked as untested. If you find the time, fire up the tests and let me know how it goes.

Chris

  HOMEPAGE  | November 20th, 2009 at 06:38 AM
Chris I'm surprised you didn't need to set ARCHFLAGS when installing the mysql gem. Many other blogs recommend:
sudo env ARCHFLAGS="-arch x86_64" \
gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5
I had to do this on my machine or else I got uninitialized constant MysqlCompat::MysqlRes. I think this issue is specific to version 2.8.1 of the gem. That might explain why you didn't run into this problem.

Jon Kinney

  HOMEPAGE  | November 23rd, 2009 at 01:46 AM
Jon Kinney Thanks for the guide Ken, I had some trouble with connecting up with FreeTDS because on a clean install of Snow Leopard the locale is set to us-ascii and not utf-8. I wrote up a quick blog post on how to modify os x's default locale to allow freetds to connect up to SQL Server.

http://jonkinney.com/articles/2009/11/23/change-locale-on-os-x-snow-leopard-for-freetds-functionality

Thanks,
-Jon

Ken Collins

  HOMEPAGE  | November 23rd, 2009 at 01:36 PM
Ken Collins @Jon Kinney Thanks! I just published your article on the SQL Server adapter wiki.

Josh Mckinney

  HOMEPAGE  | November 30th, 2009 at 03:27 PM
Josh Mckinney Great tutorial. Got almost everything to working using MSSQL 2008, basic crud works fine, but tried to get active_record session store going and keep getting the following error: DBI::DatabaseError: 22001 (8152) [unixODBC][FreeTDS][SQL Server]String or binary data would be truncated.: INSERT INTO [sessions] ([data], [created_at], [updated_at], [session_id]) VALUES('BAh7BjoQX2NzcmZfdG9rZW4iMVhWazJXb2ZOUzZiQTJpVDBXZ2ZuWEdOaTJp QnRLRnprYnZKbzJiWGpxNzg9 ', '2009-11-30 20:19:31.435', '2009-11-30 20:19:31.435', 'BAh7CDoQX2NzcmZfdG9rZW4iMVB2RCtuaVBtUUxLT3BrVEFtUExkSHphalpRd0xCQ2IxZE9rVDNadThSeTQ9Og9zZXNzaW9uX2lkIiU0ZDM1ZTI1NmU1MjQyMjM3NGZmMjY3MTU5NTFhZjk1NSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA==--49244d32c588044567f3458bed477038666bdbc9') Double checked the fields in the db were the right data type and all looks good, any ideas what might be going wrong. Thanks,

Josh Mckinney

  HOMEPAGE  | November 30th, 2009 at 05:18 PM
Josh Mckinney So it will work if I remove the session_id index, but this could be a problem when the app starts to see high traffic (which it will).

Jared McFarland

  HOMEPAGE  | November 30th, 2009 at 06:49 PM
Jared McFarland Hey guys Great post and lots of useful comments. When trying to install MacPorts I'm getting: Jareds-MacBook-Pro:~ jaredmcfarland$ sudo port install ruby Password: ---> Computing dependencies for rubyError: Unable to execute port: can't read "build.cmd": Failed to locate 'make' in path: '/opt/local/bin:/opt/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin' or at its MacPorts configuration time location, did you move it? Any thoughts?

software development uk

  HOMEPAGE  | December 1st, 2009 at 10:21 AM
software development uk Hey, that was interesting, Keep up the good work, Thanks for writing, most people don't bother.

Ken Collins

  HOMEPAGE  | December 1st, 2009 at 02:20 PM
Ken Collins

@Josh Mckinney Your issue could be related to the data type. For instance, I think :text types might be varchar(max) in 2008 and you may need to force it to another type for the room to store serialized objects. I might recommend switching to the cookie store however I can help you debug this on the SQL Server Adapter Google Group.

@Jared McFarland It looks like you have a PATH issue. If you have indeed already installed the Apple Developer Tools which are required, make sure you have added $PATH at the end of your /opt additions so that the your old paths are trailing at the end. Reverence the MacPort install page for the correct way to add the /opt stuff to you shell.

Josh Mckinney

  HOMEPAGE  | December 4th, 2009 at 04:58 PM
Josh Mckinney Ok have another issue that I think is more related to setup decribed above. For some reason I can change the database I am using for a test_app. My initial database was created from migrations just test the setup. Now I would like to use a different test database created using real world data from out existing system. Unfortunately despite all my efforts to change all the ODBC.ini file I could find a this my Mac and changing the database.yml when I start the start script/server or script/console rails continues to query the old database. I have no idea what is happening. The fact rails is completely ignoring the database.yml file and why unixODBC is ignoring the updated ODBC.ini is a complete mystery. I even used the 'find' command ( find / -name odbc.ini) and changed every file i that was found to the desired setup and still no dice. Anything would help I can have idea where to look at this point.
Thanks

Ken Collins

  HOMEPAGE  | December 4th, 2009 at 06:04 PM
Ken Collins

@Josh Mckinney: It is kind of confusing, but maybe if I share how my setup works, that might help. Aside from the normal adapter/mode/username/password parts of my database.yml file, I only have a dsn option for each rails env. I find that using DSN's allow my to easily abstract some dynamic aspects of managing that file and pushes all the details to the odbc.ini file.

In that file for each DSN that the database.yml is using, just make sure your "Servername" and "Database" are set correctly and you should be good to go. There is very little that can go wrong here.