Distributing Rails Applications, with migrations
Creating a executable file (.exe for windows for example) from a Ruby on Rails application isn’t something really new. There enough informations about that on the net, the best one can be found here.
Well, then why am I writing this blog? Well the manual from Erik Veenstra ist quite good, but what I didn’t find there anywhere was how to get the migrations done! I want to be able to give this .exe file to someone (or actually I was forced to do it this way) and they should be able to use the application, but when you keep updates in mind then you must have some way to also get migrations working.
I will be repeating some steps that are already mentioned in the “Distributing Rails Applications” tutorial.
First add this to the top of your environment.rb, this is a bit different then mentioned in the tutorial. Basically it should be working as mentioned in the tutorial, but in the last two days I was trying to solve this problem until late in the night and can’t really remember why I changed it
module Rails class Configuration def database_configuration conf = YAML::load(ERB.new(IO.read(database_configuration_file)).result) if defined?(TAR2RUBYSCRIPT) conf.each do |k, v| if v["adapter"] =~ /^sqlite3/ v["database"] = oldlocation(v["database"]) if v.include?("database") v["dbfile"] = oldlocation(v["dbfile"]) if v.include?("dbfile") end end else YAML::load(ERB.new(IO.read(database_configuration_file)).result) end end end end
Create a init.rn in the root of your application folder, you can remove the three “puts” lines, just added them for debug purposes.
at_exit do require "irb" require "drb/acl" require "sqlite3" end puts "Running as an RBA." if defined?(TAR2RUBYSCRIPT) puts "Runing from: " + oldlocation puts "Runing in: " + newlocation load "mig.rb" load "script/server"
As you can see there is a new “load” line which load mig.rb before starting the server. Here is where the magic happens.
Actually the mig.rb is nothing but a copy of the rake script with a extra line.
require 'rubygems' require 'rake' version = ">= 0" ARGV<<"db:migrate" gem 'rake', version load 'rake'
So what happens is that tar2rubyscript executes init.rb on startup, then the mig.rb is called which always does a rake db:migrate. This is done but manually adding “db:migrate” to ARGV, this has to be done so the script can be started with “load”, starting the script with a system command won’t work!
This is because the environment set up by tar2rubyscript will be missing and your migrations just won’t work.
Thats all! Incredible that for this answer I spend 2 long long nights. But now it works as it should, when starting it without tar2rubyscript it work’s as usual and with tar2rubyscript it works also great and I can have migrations when I send out new software versions.
The idea is that the same application is intended to run in two different environments, one being a usual ruby on rails environment on Linux with a MySQL Database and the other being sent out via CD and it must run on windows.
I could have made complete installer to install Ruby, Rubygems, SQLite, the Gems I need … and much more. This way it is much much easier and nobody has to install anything, just click the exe, open the browser and start working.
Telecommunications data retention (aka Vorratsdatenspeicherung)
As more and more countries have implemented laws about Telecommunications data retention, I would like to share my thoughts about this. So Big Brother thinks they can stop Terrorism by the use of Telecommunications data retention. But it is so easy to communicate without leaving a trace. It’s possible for everyone with a PC and a Internet connection to act as a Phone company without being registered anywhere, without anybody knowing that you even exist.
You can buy phone numbers from every corner of the world, the server can also be in any corner of the world where some laws may or may not apply.
Let me explain this with an example. Bart and Homer are a evil Terror organization
they are planing to blow something up. So Bart wants to call Homer and ask for some details about the Bomb. Let’s assume Big brother is only recording call details but not the call itself. So Bart calls an access number, this number is connected to a SIP Server (like asterisk).
Once connected to the server he enters Homers number, the server dials his number with a fake caller ID and deletes the CDR (call detail records) after the call. The call is being initiated via a company based in Germany (just an example) and the server with asterisk is somewhere else, let’s say in China.
So, what will data retention tell us after collecting all this data?
- Bart has made a call to some number, it is unknown whom this number belongs to. The number has been bought through one of several legal DID Exchnage platforms on the net where you can pay with PayPal or Credit card (which could be stolen), to find out where the number was connected would take a lot of time.
- Ask the regulation agency, of the country the number belongs to, whom this number belongs
- Ask the company owning the number who bought the number from them and the IP of the server it was connected to.
- After big brother has got this Data they would know that the number was connected to a server in China so the searching can begin once again.
- Ask the provider for Details about the owner of the server
- Ask for access to the server to search for CDR.
- No results where found since the server has been already cleaned up or destroyed etc etc.
- On the other side, big brother knows Homer got a phone call on his cell, from a number in Namibia (which of course it’s fake)
So in the end, big brother knows nothing! Of course if they record the content of the call they could have some information but there are ways of avoiding this. Like using a Softphone on a laptop with mobile internet conected to the SIP server via VPN. There are so many ways and all you need is a creditcard, no ID, no personal data, nothing.
So the state is trying to convince us that their intention is to “protect” us? I mean come on, you don’t need to be a genius to come up with something like this.
[HowTo] Installing Ruby Enterprise Edition and Passenger on Debian Etch
Install some stuff we will need
apt-get install build-essential apache2 ruby1.8 zlib1g-dev libssl-dev mysql-server mysql-common libmysqlclient15-dev libmysqlclient15off apache2-prefork-dev
Create a link for ruby else the installer won’t work
ln -s /usr/bin/ruby1.8 /usr/bin/ruby
get Ruby Enterprise edition (http://www.rubyenterpriseedition.com/download.html)
tar xzvf ruby-enterprise-X.X.X.tar.gz ./ruby-enterprise-X.X.X/installer
Delete the Ruby link and create new links
rm /usr/bin/ruby ln -s /opt/ruby-enterprise-1.8.6-20081215/bin/rake /usr/bin/rake ln -s /opt/ruby-enterprise-1.8.6-20081215/bin/gem /usr/bin/gem ln -s /opt/ruby-enterprise-1.8.6-20081215/bin/rails /usr/bin/rails ln -s /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /usr/bin/ruby
Install Passenger
/opt/ruby-enterprise-1.8.6-20081215/bin/passenger-install-apache2-module
if you have this error
cd /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6 /opt/ruby-enterprise-1.8.6-20081215/bin/ruby -S rake clean apache2 /opt/ruby-enterprise-1.8.6-20081215/bin/ruby: No such file or directory -- rake (LoadError)
then it looks like the Rake GEM was not installed, just install it now. and don’t forget to create the symlink in /usr/bin !
/opt/ruby-enterprise-1.8.6-20081215/bin/gem install rake
Add this to /etc/apache2/apache2.conf
LoadModule passenger_module /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so PassengerRoot /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6 PassengerRuby /opt/ruby-enterprise-1.8.6-20081215/bin/ruby
That’s it ! Now you can configure your vhosts.
<VirtualHost 192.168.0.1:80> ServerName foo.com DocumentRoot /var/rails/ RailsBaseURI /project1 RailsBaseURI /project2 RailsBaseURI /project3 Alias /docs "/opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6/doc/Users guide.html" </VirtualHost>
An finaly, the capistrano config in deploy.rb
set :application, "project1" set :repository, "https://svn.foo.com/project1" set :user, 'root' set :use_sudo, false # If you aren't deploying to /u/apps/#{application} on the target # servers (which is the default), you can specify the actual location # via the :deploy_to variable: set :deploy_to, "/var/rails/#{application}" after "deploy:update_code", "deploy:chown" role :app, "foo.com" role :web, "foo.com" role :db, "foo.com", :primary => true namespace :deploy do desc "Change owner" task :chown, :roles => :app do run "chown www-data:www-data -R #{latest_release}" end desc "Restart Application" task :restart, :roles => :app do run "touch #{current_path}/tmp/restart.txt" end end
in case you have this error:
script/console production Loading production environment (Rails 2.1.0) /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/completion.rb:10:in `require': no such file to load -- readline (LoadError) from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/completion.rb:10 from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/init.rb:252:in `require' from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/init.rb:252:in `load_modules' from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/init.rb:250:in `each' from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/init.rb:250:in `load_modules' from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb/init.rb:21:in `setup' from /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/1.8/irb.rb:54:in `start' from /usr/bin/irb:13
Then some things where missing during install. Let’s install that and compile readling.
cd /root/ruby-enterprise-1.8.6-20081215/source/ext/readline ruby extconf.rb checking for tgetnum() in -lncurses... no checking for tgetnum() in -ltermcap... no checking for tgetnum() in -lcurses... no checking for readline/readline.h... no apt-get install libncurses5-dev libreadline5-dev
Check once again if everything is installed
ruby extconf.rb . . creating Makefile
and now compile
make make install
Bye bye 2008, hello 2009
So, 2008 is finally over. A new year, a new challenge, new ideas and lot’s of changes ahead, I think it will be a interesting year. But let me get back to the end of 2008.
This time we have been for a couple of days over Christmas in Romania and this usually means, food, food, more food and even more food. We survived this and returned back to Vienna before new year.
On the 31. we went to see the fireworks in Vienna which where fired from Prater. I usually like fireworks, I like looking at them but that’s about it. I hate firecrackers! The only thing they make is noise so I think they are kind of pointless.
But what I hate the most is firecrackers in the hands of idiots and unfortunately this year there where plenty of them.
The “bangs” started a few days before Christmas and there still are some “bangs” even these days. But the 31. Decembers was a nightmare. A lot of kids throwing one firecracker after the other, people throwing firecrackers where a lot of people are standing.
From my point of view they could forbid firecrackers completely.
But we survived this also, probably with a bit more damage to my hearing then I would want.
The first day from the new year started as a normal day until someone rang at the dor. Hmm… a fireman, what could be going on?
It seems like the neighbor upstairs called for the ambulance and then lost the connection. So Ambulance, Police and a couple of firemen came and wanted to enter her apartment from our balcony.
They succeeded to enter after breaking the glass of the balcony door just to find our upstairs neighbor drunk as hell on the floor.
Let’s see what else will happen this year
AJAX validation on Rails
I had a ajax form to add languages in the system in one of my projects. A pretty simple form with just one text field. The problem I had was with validations and display the error message if something goes wrong.
After search the net for a while I came across this blog from bigsmoke which could solve my issues, but after looking a bit it kind of looks a bit complicated and I wanted something more simple.
I took some ideas from bigsmoke and did my own thing.
So here is my implementation of Ajax validation on Rails:
My controller has a “new” action which looks like this
def new @language = Language.new(params[:language]) if @language.save @language.reload return if request.xhr? else render :partial => 'error', :status => 444 end end
The view where the languages are displayed I have added a hidden div which will display the error message if present
Here is where the most stuff happens, in the _error.rjs
page.replace_html 'errors', "Language could not be created. Reason: #{@language.errors.full_messages}" page.delay(5) do page.visual_effect :fade, 'errors' end page["errors"].toggle
This replaces the errors div with a message and the errors returned from the validation, it starts a fade with a delay so that the error message will disappear after a while and finally, the div is set to visible.
That’s it! It really is that simple.
Installing RMagick2 on Debian Etch on AMD64
There are plenty of installation howto’s but in none of them I found how to get it running with debian Etch.
So here is how I did it
You can stick with the original installation guide for the beginning. Get the sources of ImageMagick > 6.3, unfortunately the debian etch packages are to old so you have to compile it yourself!
After installing ImageMagick and RMagick you will have this problem:
1 2 3 4 5 6 7 8 9 10 11 12 | irb -rubygems -r RMagick /usr/lib/ruby/gems/1.8/gems/rmagick-2.8.0/lib/RMagick2.so: libMagickCore.so.1: cannot open shared object file: No such file or directory - /usr/lib/ruby/gems/1.8/gems/rmagick-2.8.0/lib/RMagick2.so (LoadError) from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:32:in `require' from /usr/lib/ruby/gems/1.8/gems/rmagick-2.8.0/lib/RMagick.rb:11 from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:32:in `gem_original_require' from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:32:in `require' from /usr/lib/ruby/1.8/irb/init.rb:252:in `load_modules' from /usr/lib/ruby/1.8/irb/init.rb:250:in `each' from /usr/lib/ruby/1.8/irb/init.rb:250:in `load_modules' from /usr/lib/ruby/1.8/irb/init.rb:21:in `setup' from /usr/lib/ruby/1.8/irb.rb:54:in `start' from /usr/bin/irb:13 |
To solve this problem create a new ld.so config by creating a file /etc/ld.so.conf.d/local.conf and add these 2 lines:
1 2 | /usr/lib /usr/local/lib |
and run ldconfig


Comments(1)
