By Rupert
Posts tagged ruby on rails
Rails Note #14: QuickStart Tutorial
Feb 7th
If you haven’t installed ruby, follow this post
Part 1: Installation and Configuration (Rails and Passenger)
1. Upgrade existing ruby gems
sudo gem list sudo gem update --system
UPDATE: Took me 4 hours figuring this out. There was a problem when i run script/console that it will say the “gem” detected was 1.0.1 although the current gem version is 1.3.5 after gem update –system. Google didn’t helped out. But I was able to nail down the problem from this post:
https://wincent.com/wiki/Upgrading_to_RubyGems_1.0.1_on_Mac_OS_X_10.5.1
In the post above, notice that rubygems 1.0.1 was installed in /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin. I guess this gem was being referenced first before the actual /usr/local/bin/gem. So I deleted this directory /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr.
Possible sources of gem installations:
/Users/rupert/.gem/ruby/1.8/gems /Library/Ruby/Gems/1.8/gems
rupert:1.8 rupert$ gem env RubyGems Environment: - RUBYGEMS VERSION: 1.3.5 - RUBY VERSION: 1.8.6 (2008-08-08 patchlevel 286) [i686-darwin9.5.0] - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8 - RUBY EXECUTABLE: /usr/local/bin/ruby - EXECUTABLE DIRECTORY: /usr/local/bin - RUBYGEMS PLATFORMS: - ruby - x86-darwin-9 - GEM PATHS: - /usr/local/lib/ruby/gems/1.8 - /Users/rupert/.gem/ruby/1.8 - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :benchmark => false - :backtrace => false - :bulk_threshold => 1000 - REMOTE SOURCES: - http://gems.rubyforge.org/
2. Install rails. Download from ruby-forge. Link?
gem install -V rails-2.3.3.gem gem install -V mysql
3. Install and configure passenger for Apache2
gem install -V passenger cd /Users/rupert/.gem/ruby/1.8/gems/passenger-2.2.5/bin passenger-install-apache2-module
469 LoadModule passenger_module /Users/rupert/.gem/ruby/1.8/gems/passenger-2.2.5/ext/apache2/mod_passenger.so 470 PassengerRoot /Users/rupert/.gem/ruby/1.8/gems/passenger-2.2.5 471 PassengerRuby /usr/local/bin/ruby 472 473 <VirtualHost *:80> 474 RailsBaseURI /rails/travelsiteph 475 </VirtualHost>
4. Create a sample rails project (“travelsiteph”) in your project directory (“/Users/rupert/projects/rails”).
$ cd /Users/rupert/projects/rails $ rails travelisteph create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments ..... $ ls -la travelsiteph drwxr-xr-x 15 rupert admin 510 2 Sep 21:14 . drwxr-xr-x 5 rupert admin 170 30 Sep 16:31 .. -rw-r--r-- 1 rupert admin 10011 2 Sep 21:14 README -rw-r--r-- 1 rupert admin 307 2 Sep 21:14 Rakefile drwxr-xr-x 6 rupert admin 204 2 Sep 21:14 app drwxr-xr-x 9 rupert admin 306 2 Sep 21:14 config drwxr-xr-x 4 rupert admin 136 2 Sep 21:18 db drwxr-xr-x 3 rupert admin 102 2 Sep 21:14 doc drwxr-xr-x 3 rupert admin 102 2 Sep 21:14 lib drwxr-xr-x 6 rupert admin 204 2 Sep 21:14 log drwxr-xr-x 11 rupert admin 374 2 Sep 21:14 public drwxr-xr-x 11 rupert admin 374 2 Sep 21:14 script drwxr-xr-x 8 rupert admin 272 2 Sep 21:55 test drwxr-xr-x 6 rupert admin 204 2 Sep 22:07 tmp drwxr-xr-x 3 rupert admin 102 2 Sep 21:14 vendor
I have /wwwroot as my document WebRoot. Its running cf, php and mapserv (cgi-bin). Since I want to mix it with rails development, I’ll just make a rails subdirectory. Inside the rails subdirectory, I can create symbolic links to my rails applications located in my projects directory. This way, rails configuration is not exposed from Apache.
cd /wwwroot mkdir rails ln -s /Users/rupert/projects/rails/travelsiteph/public travelsiteph $ ls -la total 8 drwxr-xr-x 3 rupert admin 102 2 Sep 14:09 . drwxrwxr-x 60 root admin 2040 2 Sep 14:08 .. lrwxr-xr-x 1 rupert admin 42 2 Sep 14:09 travelsiteph -> /Users/rupert/projects/rails/travelsiteph/public
5. Restart Apache to take the new configuration
sudo /Library/StartupItems/Apache2/Apache2 restart
6. Open http://127.0.0.1/rails/travelsiteph/
But for development purposes, it is better to use http://127.0.0.1:3000/ to see immediately any changes in code.

Part 2: Rails Development
MySQL Prerequisites:
GRANT ALL PRIVILEGES ON *.* TO rupert@'%' IDENTIFIED BY '*************' WITH GRANT OPTION; $ mysql -u rupert -p
1. Create three databases:
mysql> CREATE DATABASE travelsiteph_development; Query OK, 1 row affected (0.00 sec) mysql> CREATE DATABASE travelsiteph_test; Query OK, 1 row affected (0.00 sec) mysql> CREATE DATABASE travelsiteph_deployment; Query OK, 1 row affected (0.00 sec)
2. Launch Textmate
cd /Users/rupert/projects/rails/travelsiteph mate .
3. Edit database.yml
development: adapter: mysql database: travelsiteph_development username: root password: xxxxxxx host: localhost test: adapter: mysql database: travelsiteph_test username: root password: xxxxxxx host: localhost production: adapter: mysql database: travelsiteph_deployment username: root password: xxxxxxx host: localhost
4. Generate a Poi model. The model should be capitalized and singular.
$ ruby script/generate model Poi exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/poi.rb create test/unit/poi_test.rb create test/fixtures/pois.yml create db/migrate create db/migrate/20090902111538_create_pois.rb
5. Now let’s create the database table for Poi using migrations.
class Poi < ActiveRecord::Migration def self.up create_table :pois, :id => :poi_id do |t| t.column :name, :string t.column :full_address, :string t.column :location, :string t.column :get_there, :string t.column :short_description, :string t.column :full_description, :text t.column :other_info, :text t.column :tel_no, :string t.column :fax_no, :string t.column :mobile_no, :string t.column :email, :string t.column :website, :string t.column :other_contact_details, :text t.column :longitude, :decimal, :precision => 10, :scale => 7 t.column :latitude, :decimal, :precision => 10, :scale => 7 t.column :created_at, :timestamp t.column :updated_at, :timestamp t.timestamps end end def self.down drop_table :pois end end
$ rake db:migrate (in /Users/rupert/projects/rails/travelsiteph) == CreatePois: migrating ========================================= -- create_table(:point_of_interests, {:id=>:poi_id}) -> 0.0353s == CreatePois: migrated (0.0362s) ================================
6. Generate a Poi controller.
$ script/generate controller Poi exists app/controllers/ exists app/helpers/ create app/views/poi create test/functional/ create test/unit/helpers/ create app/controllers/poi_controller.rb create test/functional/poi_controller_test.rb create app/helpers/poi_helper.rb create test/unit/helpers/poi_helper_test.rb
7. Add a list function to Poi Controller
class PoiController < ApplicationController def list @pois = Poi.find(:all) end end
8. Lets test. Open a browser and point to http://127.0.0.1:3000/travelsiteph/poi/list
$ruby script/server
9. Now create the view list.rhtml in views/poi/
<% if @pois.blank? %> <p>There are currently no pois in the system. </p> <% else %> <p>These are the pois in the system: </p> <ul> <% @pois.each do |poi| %> <li><%= link_to poi.name, {:action => 'show', :id => poi.id} -%></li> <% end %> </ul> <% end %>
Part 3: Deploying
1. set RAILS_ENV to production
export RAILS_ENV=production
2. Make sure to populate the database in production mode, run rake db:migrate
3. Capistrano
set :port, 2210 set :application, "halalan2010" #set :repository, "svn+ssh://2rmobile.com/data/repos/web/rails/halalan2010/" set :repository, "http://2rmobile.com/repos/web/rails/halalan2010/" set :scm, :subversion set :scm_username, 'rupert' set :scm_password, proc{Capistrano::CLI.password_prompt('SVN pass:')} # Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none` role :web, "2rmobile.com" # IP Your HTTP server, Apache/etc role :app, "2rmobile.com" # This may be the same as your `Web` server role :db, "2rmobile.com", :primary => true # This is where Rails migrations will run #role :db, "your slave db-server here" set :user, "rupert" set :runner, "rupert" set :deploy_to, "/opt/rails/#{application}" # If you are using Passenger mod_rails uncomment this: # if you're still using the script/reapear helper you will need # these http://github.com/rails/irs_process_scripts namespace :deploy do task :start do run "/etc/init.d/apache2 start" end task :stop do run "/etc/init.d/apache2 stop" end task :restart, :roles => :app, :except => { :no_release => true } do run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}" end task :production do run "export RAILS_ENV=production" end end namespace :db do task :seed do run "cd #{deploy_to}/current && RAILS_ENV=production rake db:seed" end task :populate do run "cd #{deploy_to}/current && RAILS_ENV=production rake db:populate" end end
Capistrano commands I normally use:
#on local #cap deploy:setup #on remote and change owner and permissions of project sudo chown -Rf rupert:root halalan2010 #on local #cap deploy #cap db:seed #cap db:populate
Part 4: Miscellaneous
1. Get a description or rake commands
rake -D db
2. How to populate the database in production mode?
rupert:halalan2010 rupert$ export RAILS_ENV=production rupert:halalan2010 rupert$ rake db:migrate (in /Users/rupert/projects/rails/halalan2010) == CreateDatabase: migrating ================================================= -- create_table(:candidates) -> 0.0036s -- create_table(:voters) -> 0.0031s -- create_table(:votes) -> 0.0027s == CreateDatabase: migrated (0.0100s) ========================================
http://blog.airbladesoftware.com/2009/4/10/avoid-typing-rails_env-all-the-time
3. Uninstall specific gem version
gem uninstall activesupport -v 2.2.2
4 Add a source to gem
rupert:rails rupert$ sudo gem sources -a http://gems.github.com http://gems.github.com added to sources
5. Adding a rails project in svn
#create a remote dir svn mkdir http://www.2rmobile.com/repos/web/rails/virginmobilechecker #checkout and copy all files cd ~/projects/rails mv virginmobilechecker virginmobilechecker_old svn co "svn+ssh://2rmobile.com/data/repos/web/rails/virginmobilechecker" virginmobilechecker mv virginmobilechecker_old/* virginmobilechecker/ cd virginmobilechecker svn add * #ignoring log files svn revert log/* svn propset svn:ignore "*.log" log svn propset svn:ignore "*" tmp svn propset svn:ignore "*" doc #commit the files svn commit -m "first commit" *
Rails Note #13: RubyonRails + Oracle on Linux (i386 / x64)
Dec 11th
In summary, install Oracle Instant Client and try to run sqlplus. If sqlplus connects to the oracle sid then go ahead and install the rails adapters for oracle. What is important to note here, is to install the oracle-instantclient for the architecture of your machine.. I have tested this on Debian Lenny (i386) and CentOS5 (x64)
1. Download from http://www.oracle.com/technology/software/tech/oci/instantclient/
a. oracle-instantclient-basic-10.2.0.4-1.i386
b. oracle-instantclient-devel-10.2.0.4-1.i386
c. oracle-instantclient-sqlplus-10.2.0.4-1.i386
2. Unzip everything to /opt/oracle/instantclient . You should have something like the ff:
[root@csapp1 instantclient]# ls -la total 102704 drwxr-xr-x 3 root root 4096 Dec 10 21:54 . drwxr-xr-x 3 root root 4096 Dec 10 22:03 .. -rw-r--r-- 1 root root 228 Dec 10 21:52 BASIC_README -r--r--r-- 1 root root 1609607 Dec 10 21:52 classes12.jar -rwxr-xr-x 1 root root 67542 Dec 10 21:52 genezi -r--r--r-- 1 root root 1525 Dec 10 21:52 glogin.sql lrwxrwxrwx 1 root root 17 Dec 10 21:54 libclntsh.so -> libclntsh.so.10.1 -rwxr-xr-x 1 root root 21038613 Dec 10 21:52 libclntsh.so.10.1 -r-xr-xr-x 1 root root 3796601 Dec 10 21:52 libnnz10.so -rwxr-xr-x 1 root root 1664116 Dec 10 21:52 libocci.so.10.1 -rwxr-xr-x 1 root root 72674185 Dec 10 21:52 libociei.so -r-xr-xr-x 1 root root 138033 Dec 10 21:52 libocijdbc10.so -r-xr-xr-x 1 root root 1435561 Dec 10 21:52 libsqlplusic.so -r-xr-xr-x 1 root root 997409 Dec 10 21:52 libsqlplus.so -r--r--r-- 1 root root 1555682 Dec 10 21:52 ojdbc14.jar drwxr-xr-x 4 root root 4096 Dec 10 21:52 sdk -r-xr-xr-x 1 root root 7773 Dec 10 21:52 sqlplus -rw-r--r-- 1 root root 232 Dec 10 21:52 SQLPLUS_README -rw-r--r-- 1 root root 516 Dec 10 21:53 tnsnames.ora [root@csapp1 instantclient]#
3. Make a symbolic link for libclntsh.so.10.1 as shown above.
4. Create the Oracle Environment variables
export ORACLE_HOME=/opt/oracle/instantclient export TNS_ADMIN=$ORACLE_HOME export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH export DYLD_LIBRARY_PATH=$ORACLE_HOME export PATH=$PATH:$ORACLE_HOME
5. At this point, you should have oracle-instantclient properly installed. You can test by running sqlplus.
[root@csapp1 instantclient]# sqlplus SQL*Plus: Release 10.2.0.4.0 - Production on Thu Dec 11 11:47:40 2008 Copyright (c) 1982, 2007, Oracle. All Rights Reserved.
NOTE: Sometimes you will get a SEGMENTATION FAULT. If so, try to open a new shell with the environment variables loaded and do an sqlplus in a directory which is not /opt/oracle/instantclient.
6. Install the oracle adapter for rails
7. gem install ruby-oci8
8. gem install oracle_enhanced-adapter –source=”http://gems.rubyonrails.org/”
activerecord-oracle-adapter (1.0.0.9250)
activerecord-oracle_enhanced-adapter (1.1.8)
NOTE: Try to look for the latest gems, the source above is at the time of this writing so it might change.
9. Test using irb
[root@csapp1 instantclient]# irb irb(main):001:0> require 'rubygems' => true irb(main):002:0> require 'oci8' => true irb(main):003:0>
Rails Note #12: Oracle on Intel Mac
Dec 5th
2. Install Oracle Instant Client on Mac.
a. Instant Client Package – Basic: All files required to run OCI, OCCI, and JDBC-OCI applications
- instantclient-basic-macosx-10.2.0.4.0.zip (34,020,719 bytes)
b. *Instant Client Package – SDK: Additional header files and an example makefile for developing Oracle applications with Instant Client
instantclient-sdk-macosx-10.2.0.4.0.zip (603,493 bytes)
OR download the whole bundle (10.2.0.4.zip) with sqlplus installed from my installers.
3. Put this on your sudo vim ~/.bash_profile.
export ORACLE_HOME=/Library/Oracle/instantclient/10.2.0.4 export TNS_ADMIN=$ORACLE_HOME export LD_LIBRARY_PATH=$ORACLE_HOME export DYLD_LIBRARY_PATH=$ORACLE_HOME export PATH=$PATH:$ORACLE_HOME
4. Make a symbolic link
cd /Library/Oracle/instantclient/10.2.0.4 ln -s libclntsh.dylib.10.1 libclntsh.dylib
5. Go to /Library/Oracle/instantclient/10.2.0.4 and edit tnsnames.ora. Point the Oracle SID to the IP where you installed Oracle.
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.155)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
ORCL_2_11 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.2.11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)6. Install the oracle-adapter for rails
sudo gem install activerecord-oracle-adapter --source http://gems.rubyonrails.org
7. In your database.yml file
development: adapter: oracle database: orcl username: youzhu_mobile_dev password: your_password
or browse the contents of a sample rails project youzhumobile.tar.gz
8. If you ever encounter an encoding problem, then we need to set the NLS_LANG environment variable before running script/server.
# export NLS_LANG=American_America.UTF8 # script/server
or I prefer setting it in the environment.rb
Rails::Initializer.run do |config| ENV['NLS_LANG']='American_America.UTF8' # Settings in config/environments/* take precedence over those specified here.
Note: If you don’t know your database encoding, then read this post.
Rails Note #11: TDD and Loading Development Fixtures for Testing
Nov 25th
Here is a brief outline on how I am doing test driven development personally.
1. Code up tests/functional/foo_controller_test.rb until you know what you expect from the method. Make the test method as self explanatory as much as possible.
def test_goto_restaurant_next end
2. Imagine how the URL parameters will be passed to the controller.
get :goto, 'WHOISD-ABONENT'=> MOBILE_NUMBER, :categ_id => '123', :node_id => '10', :page => '2'
3. At this point. It gets too exciting to code up the controller itself. Hold on, try to make an assertion on a variable that we will use in the view.
assert_equal assigns("sub_menus").length, 2
4. Code the controller
5. Code the view
6. Test from the browser.
7. Refactor the testcase and make more assertions.
8. Run the testcase
Now, it could be very hard to execute the tests if you don’t have the same development data inside your testing database. I found a good tip from the Rail’s Way book, and used ar_fixtures.
For whatever reason, dumping data to fixtures is not a part of core Rails. Considering that Rails gives you a to_yaml method on ActiveRecord models and Hash objects, it wouldn’t be too hard to write your own Rake task. However, it’s not necessary to do so because of a well-proven plugin written by Geoff Grosenbach. It’s called ar_fixtures and you can install it with the following command:
$ script/plugin install http://topfunky.net/svn/plugins/ar_fixtures
Once the plugin is installed, dumping a fixture is a simple matter of invoking a new rake task called rake db:fixtures:dump. Unlike the built-in loading rake task, this one takes a MODEL parameter with the name of the ActiveRecord class that you want to dump data for:
$ rake db:fixtures:dump MODEL=BillingCode
Rails Note #10: Generating XML
Nov 25th
This post should have made it a looong time ago..
I am currently building an application where all the output formats is in XML. One of the first problems I had was to output the xml.
1. At first try, I could append ‘xml’ in the routes as a format parameter. But this takes into consideration that all our views would be in XML. However, you could have your views to be index.xml.erb or index.rxml, if you are using the builder templates plugin.
ActionController::Routing::Routes.draw do |map| #map.connect '/menu/show.xml', :controller => 'menu', :action => 'show', :format => 'xml' map.connect ':controller/:action/:id', :format => 'xml' map.connect ':controller/:action/:id.:format', :format => 'xml' end
2. If my application requires me to output both html and xml, then the above would not be sufficient. In my controller, I have to explicitly say :layout => false which means it would not use the application.html.erb found in app/views/layouts if we have one.
So far, I made progress using builder templates only but it is enough to suit my needs. Below is a sample controller and view.
app/controller/mobile_controller.rb
def index headers['Content-Type'] = 'text/xml; charset=utf-8' render :layout => false end
app/views/index.rxml
xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8" xml.content :type => "hypertext" do xml.head do xml.pageID "1" xml.title "USSD Page from Ruby" xml.protocol "html,java,wap,ussd,xhtml" end xml.body { greeting = 'Welcome back!' xml.p greeting } end
Comments