Friday, October 23, 2009

Ruby-on-Rails Installation & Implementation

Objectives:
  • Install RoR and Gems
  • Setting up SVN
  • Develop Rails applications with painless deployment in mind;
  • Build and configure web servers and other services;
  • Stress application before deploying
Installing on local machine (windows xp)
First download and install ruby16-27_irc2.exe by double clicking on the exe file. (Installation steps are skipped). The next step is to update the installation using gem.

Updating Gem
Gem is the name of the utility supplied with Ruby in order to manage, install, and update the Ruby installation in an easy way. The second step in the manual installation of RoR is updating the Ruby installation so that if a new package or an update for any of the package is available, then the complete installation can be made up-to-date.

Before we begin, if you are behind a proxy, open the command prompt and give the following command:
>Set HTTP_PROXY=http://proxy_address:proxy_port

>gem update
That completes the update gem step. Next, let us install RoR.

Installing RoR
This is the last and the easiest part of the installation process. Just one command and RoR shall be installed.
At the prompt, issue the following command:
>gem install rails --include-dependencies

It would give the following message.
Congrats! RoR is now installed on your system.

Next we will update ruby and install necessary gems…
>gem update -system -rdoc
>gem install mysql

Testing the Installation
The installation is successful as much as the process is concerned. However, it is always a good idea to test the installation. From this point onwards, I will be using the rails_apps directory as the base directory for the RoR application that will be developed.

Creating a Starter Application
When you are testing a deployment configuration. You’ll want this simple application to do enough with Rails so you can see whether your production setup works. You don’t want to have to debug your deployment environment and your application at the same time. Once you have that working, you can move on to your real application.

You’ll want to do all the following steps on your development machine, not on your host. Your goal is to build a Rails application that exercises Rails models, views, and controllers. Since the default Rails project already tests the controller and views by default, you need to worry only about a primitive model.

Four steps to new application:
  1. Setting up the Application Structure
  2. Adding the First Controller class
  3. Implementing the Action Method
  4. Adding the View Template

Fire up command prompt and switch to rails_apps directory. The installation has to be tested for two components Ruby and Rails
>rails –d mysql dotevo

Step above will give you a project with mysql database backing. There will be lots of files generated. It means RoR installation is OK. What has happened is that RoR has generated the whole file structure for the application. Even certain files that work as placeholders have been generated by just one command.

Directories and Files Located in the directory
dotevo/
|-- README
|-- Rakefile
|-- app
|-- components
|-- config
|-- db
|-- doc
|-- lib
|-- log
|-- public
|-- script
|-- test
`-- vendor

A brief description of the directory structure and files is provided as follows:

Name .......... Description
README......... Gives a brief introduction to Rails and how to get started
Rakefile ...... the applications build script, which is written in Ruby
app ........... Contains your application’s code, including models, controllers, views and helpers
components .... Empty by default; reusable code in the form of components should be placed here.
Note that using components is generally considered a bad practice.
config ....... Holds your application’s configuration files, including database config.
db ............ Holds your ActiveRecord migrations and database schema files
doc ........... Empty by default; put the documentation for your application in this
directory (use rake appdoc to generate the documentation for your controllers and models)
lib ........... Holds application-specific code that is reusable
log ........... Log files are written to this directory
public ........ Contains static files like HTML, CSS, and JavaScript files
script ....... Contains various scripts for starting and maintaining your Rails application
test .......... Holds your unit, integration, and functional tests and their fixtures
vendor ........ Where plugins are installed

Now start the server with mongrel and start the browser to see our newly created project on http://localhost:3000

Check the server provided by RoR. Give the following command after changing into the dotevo folder.

> cd dotevo
> ruby script/server

As a response to the command, you should see the messages saying that it is booting up the Mongrel server since I had Mongrel installed on the system, the default is WEBrick…

Next, open the browser of your choice and provide the following URL:
http://localhost:3000.

The code you see on the Welcome page is in the index.html file, which is located in the public directory under the application root. It was created by the rails command and should be deleted, so that it doesn’t prevent the controller for the root context from being called:

C:\> del public\index.html

You will get an error, Recognition failed for "/", if you access http://localhost:3000 again after deleting index.html. The error is thrown because there are no controller and action set up to handle the request.

We are now ready to start writing some code.

First, we’ll see how requests are handled by the Rails framework. Later, we will modify the skeleton application that Ruby on Rails created for us to fit our requirements.

Configuring Ruby on Rails to Use the Database
The information Ruby on Rails needs for connecting to the database is located in a configuration file that is written in a lightweight markup language called YAML. The configuration file, database.yml, is located in the db folder and was created for you when you ran the rails command earlier. The generated configuration template contains examples for MySQL,

Database Configuration
# MySQL version
# gem install mysql

development:
adapter: mysql
encoding: utf8
reconnect: false
database: dotevo_development
pool: 5
username: myuser
password: mypwd
host: localhost

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: mysql
encoding: utf8
reconnect: false
database: dotevo_test
pool: 5
username: myuser
password: mypwd
host: localhost


Save the configuration after you are finished editing it.
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

Run the commands as follows:
> cd dotevo
> ruby script/generate model type_businesses
The last command will give you a model and also generated a migration that you can use to create your database-backed model.

The next step is to edit the migration so that it will create the type_businesses table structure. At this point, we can return to text editor to do our editing by opening the file db/migrate/20091002214424_create_type_businesses.rb

After making the changes it should be as follows:

class CreateTypeBusinesses < ActiveRecord::Migration
def self.up
create_table :type_businesses do |t|
t.column :type_description, :string, :limit => 45, :null => false
t.column :type_activity, :date, :null => false, :default => Time.now
end
end

def self.down
drop_table :type_businesses
end
end

Now use rake to migrate for generating table in our dotevo_developments database and verify if the table is generated properly as follows:
> rake db:migrate


Scaffolding:
To get some instant front-end rough view, we'll use another Rails feature called scaffolding. In order to generate a scaffold, you simply need to specify the name of the model you want to scaffold for with the column names and their data types. In our case, the model is called type_businesses. Therefore, from inside RAILS_ROOT, we will run on the database as follows:

> ruby script/generate scaffold type_businesses type_description:string type_activity:date

What happen in the above statement is that; we have generated a CRUD interface for our database table we created earlier in model with the name "type_businesses" the PK is automatically generated with column name "id", for other columns we have instructed to be "type_description" of data type string, and "type_activity" with data type date. All these columns are explicitly defined in our model which; we edited earlier.

***
And here it is a quick and dirty RoR test application, you can repeat the above steps for all the tables of your application and generate a raw front-end page using scaffolding for each table CRUD unit.
***

Wednesday, October 7, 2009

SVN and Trac - Ubuntu 9.04 Server

Machine Info:
root@mydomain:/projects/trac# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=9.04
DISTRIB_CODENAME=jaunty
DISTRIB_DESCRIPTION="Ubuntu 9.04"

My server has following directories created on it.
root@mydomain:~# mkdir /projects
root@mydomain:~# mkdir /projects/svn
root@mydomain:~# mkdir /projects/trac
root@mydomain:~# mkdir /projects/files

Enable dav_fs as follows:
root@mydomain:~# a2enmod dav_fs

First we will tell Apache that any and all requests for the (virtual) folder projects should be handled by Trac.

root@mydomain:~# aptitude install subversion libapache2-svn
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done

Installed TRAC as follows:
root@mydomain:/home/wiz# aptitude install libapache2-svn python-setuptools python-subversion
root@mydomain:/home/wiz# aptitude install python-mysqldb
root@mydomain:/projects/trac# wget http://ftp.edgewall.com/pub/trac/Trac-0.11.5.tar.gz
root@mydomain:/projects/trac# tar -xzf Trac-0.11.5.tar.gz
root@mydomain:/projects/trac# cd Trac-0.11.5
root@mydomain:/projects/trac/Trac-0.11.5# python setup.py install

Made changes in /etc/apache2/sites-available/default as follows:
#
# >>> Added for Mgmt of software with Trac/svn
# >>> 09/25/2009 ... @mj@d <<<
#
ScriptAlias /projects /usr/share/trac/cgi-bin/trac.cgi
SetEnv TRAC_ENV_PARENT_DIR "/projects/trac"
#
AuthType Basic
AuthName "Trac Environment"
AuthUserFile /projects/projects.passwd
Require valid-user
#
DAV svn
SVNParentPath /projects/svn
AuthType Basic
AuthName "Subversion Repositories"
AuthUserFile /projects/projects.passwd
Require valid-user
#
Alias /files "/projects/files"
DAV On
AuthType Basic
AuthName "Files"
AuthUserFile /projects/projects.passwd
Require valid-user
#
Require valid-user


Installed Berkeley DB as follows:
root@mydomain:/projects/bdb/db-4.8.24# cd build_unix/
root@mydomain:/projects/bdb/db-4.8.24/build_unix# ../dist/configure --bindir=/usr/local/bin
root@mydomain:/projects/bdb/db-4.8.24/build_unix# make prefix=/usr/contrib/bdb install

./libtool --mode=execute true db_verify


Created Project as follows:
root@mydomain:/projects# svnadmin create svn/sandbox --fs-type=fsfs
root@mydomain:/projects# mkdir -p files/sandbox/public files/sandbox/private files/sandbox/images

Creating Trac Environment:
root@mydomain:/projects# trac-admin trac/sandbox initenv

/var/lib/python-support/python2.6/MySQLdb/__init__.py:34:
DeprecationWarning: the sets module is deprecated from sets import ImmutableSet

Creating a new Trac environment at /projects/trac/sandbox Trac will first ask a few questions about your environment in order to initialize and prepare the project database.

Please enter the name of your project. This name will be used in page titles and descriptions.

Project Name [My Project]> sandbox

Please specify the connection string for the database to use.

By default, a local SQLite database is created in the environment directory. It is also possible to use an already existing

PostgreSQL database (check the Trac documentation for the exact connection string syntax).

Database connection string [sqlite:db/trac.db]>

Please specify the type of version control system, By default, it will be svn.

If you don't want to use Trac with version control integration, choose the default here and don't specify a repository directory in the next question.

Repository type [svn]>

Please specify the absolute path to the version control repository, or leave it blank to use Trac without a repository. You can also set the repository location later.

Path to repository [/path/to/repos]> /projects/svn/sandbox


http://localhost:8000/sandbox

Giving error while I started project/sandbox as follows:


# tracd --port 8000 /projects/trac/sandbox
Server starting in PID 24970.
Serving on 0.0.0.0:8000 view at http://127.0.0.1:8000/


Following commands is used to start server…
root@mydomain:/projects# tracd -p 8000 -b 192.168.1.105 /projects/trac/sandbox

Server starting in PID 27409.
Serving on http://192.168.1.105:8000/


Pointed browser to http://192.168.1.105:8000/sandbox
It shows the page successfully:


Security
At the moment our server is configured to allow access to certain actions—like writing to our subversion repository—only to authenticated users. Now we need to actually allow our users to perform these actions by storing their authentication details. These are stored in a text file that Apache understands— the projects.passwd file referred to in the earlier excerpts.

Managing Users
Creating this file is quite simple using the htpasswd tool provided by Apache, which should be accessible simply by its name on Linux. We need to explicitly tell it to create a new file the first time, and which file to use for subsequent user additions.

Initially dav_svn was setup as follows:

root@mydomain:~# htpasswd -cm /etc/apache2/dav_svn.passwd adminsvn
New password:
Re-type new password:

Adding password for user adminsvn
Note: we replaced dav_svn.passwd with new projects.passwd. For a first run, we use the following:

$ htpasswd -c /projects/projects.passwd wiz
We will be prompted to specify and then confirm the password for our user wiz.

root@mydomain:/projects# htpasswd -c /projects/projects.passwd wiz
New password:
Re-type new password:

Adding password for user wiz
Alternatively we can specify the password as part of the command if we use the -b parameter, although we should be aware that this is not safe since the password will be stored in the command history of our Operating System.

For subsequent users we simply drop the -c:

root@mydomain:/projects# htpasswd /projects/projects.passwd mike
New password:
Re-type new password:

Adding password for user mike

Again we will have to specify and confirm mike's password. Now we have two users who can access our server.

Create an administrator user right now. Make sure you add a user who’s already in your /etc/apache2/dav_svn.passwd file.

root@mydomain:/projects# trac-admin trac/sandbox permission add mike TRAC_ADMIN

The changes we have made in file /etc/apache2/sites-available/default should look as follows:
#
# >>> Added for Mgmt of software with Trac/svn
# >>> 09/25/2009 <<<
#
ScriptAlias /projects /usr/share/trac/cgi-bin/trac.cgi
SetEnv TRAC_ENV_PARENT_DIR "/projects/trac"
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /projects/trac
PythonOption TracUriRoot /projects
#
AuthType Basic
AuthName "Trac Authentication"
AuthUserFile /projects/projects.passwd
# AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
#
DAV svn
SVNParentPath /projects/svn
AuthType Basic
AuthName "Subversion Repositories"
AuthUserFile /projects/projects.passwd
Require valid-user
#
Alias /files "/projects/files"
DAV On
AuthType Basic
AuthName "Files"
AuthUserFile /projects/projects.passwd
Require valid-user
#
Require valid-user

Notice here, again that we use TracEnvParentDir to show we host multiple instances of Trac. You may change the TracUriRoot to something different.

File Permissions
Since everything is running through Apache, we need to ensure it can write to the files it needs. Since we have put everything under the projects folder, we can set our permissions there and let them cascade down through the rest.

Linux
Linux file permissions are split into user, group, and other. We will change the group to the same one used by Apache, allow the group to write to our projects folder and then make sure the permissions are inherited by anything inside the folder.

Again, make sure to chown your Trac installation to www-data:

The general format for using authentication is:
root@mydomain:/projects# chgrp -R www-data /projects
root@mydomain:/projects# chmod -R g+w /projects
root@mydomain:/projects# chmod -R g+s /projects
root@mydomain:/projects# chown -R www-data.www-data /projects/trac

Trac Permissions:
Trac maintains it own set of permissions for each environment we create. The permissions we are going to create here cover the behavior described in the following chapters.

The default permissions in Trac allow unauthenticated (or rather anonymous) users to do anything. We are going to prevent them from editing the wiki—they can still view it though—and accessing the source code browser. Then we are going to let authenticated users do both of these as well as access milestones.

1. Type cd /projects and press Enter.
2. Type trac-admin followed by trac/sandbox and press Enter.
3. Type permission remove anonymous WIKI_CREATE WIKI_MODIFY BROWSER_VIEW and press Enter.
4. Type permission add authenticated WIKI_ADMIN BROWSER_VIEW MILESTONE_ADMIN and press Enter.
5. Type quit and press Enter to leave trac-admin.

Remember, we will need to do this for each Trac environment that we create.

root@mydomain:/projects# trac-admin trac/sandbox
Welcome to trac-admin 0.11.5

Interactive Trac administration console.
Copyright (c) 2003-2009 Edgewall Software

Type: '?' or 'help' for help on commands.

Trac [/projects/trac/sandbox]> permission remove anonymous WIKI_CREATE WIKI_MODIFY BROWSER_VIEW
/var/lib/python-support/python2.6/MySQLdb/__init__.py:34: *DeprecationWarning: the sets module is deprecated from sets import ImmutableSet
Trac [/projects/trac/sandbox]> permission add authenticated WIKI_ADMIN BROWSER_VIEW MILESTONE_ADMIN
Trac [/projects/trac/sandbox]> quit


*See troubleshooting section.

$ tracd -p port --auth=base_project_dir,password_file_path,realm project_path
where:
* base_project_dir is the base directory of the project; note: this doesn't refer to the project name, and it is case-sensitive even for windows environments
* password_file_path path of the password file
* realm realm
* project_path path of the project

Example:
$ tracd -p 8080 \
--auth=project1,/path/to/users.htdigest,mycompany.com /path/to/project1

Now start standalone server using tracd as follows:
root@mydomain:~# tracd -p 8000 -b 192.168.1.105 --basic-auth=/projects/trac,/projects/projects.passwd,mydomain.com /projects/trac/sandbox
Server starting in PID 20268.
Serving on http://192.168.1.105:8000/

Now, access your trac over the web: http://mydomain.com/projects for a complete listing of hosted projects or http://mydomain.com/projects/sandbox for the sandbox project.
You may also login now! As you can see, we use the projects.passwd file here so everyone with subversion access also has access to trac.

With a minor configuration change, Trac is capable of sending emails when tickets are raised/updated. To make the most of this it is recommended that we use email addresses for our htpasswd usernames, then we need to do nothing besides enabling email.

See the Notification section of http://trac.edgewall.org/wiki/TracIni to see how to enable this.
Editing or deleting users is simply a matter of modifying the password file. If we want to change their password we need to re-run the htpasswd command.

Troubleshooting the warnings for user:
When server is started using following commands it spit out warnings as follows:
root@mydomain:~# tracd -p 8000 -a *,/projects/projects.passwd,mydomain.com /projects/trac/sandbox
Warning: invalid digest line in /projects/projects.passwd: wiz:N8pehMMzM0reI
Warning: invalid digest line in /projects/projects.passwd: mike:Qt4TvmrlBvF0I
Warning: found no users in realm: mydomain.com
Server starting in PID 30586.
Serving on 0.0.0.0:8000 view at http://127.0.0.1:8000/

made changes in /etc/group file as follows:
root@mydomain:~# nano /etc/group
...
trac:x:1003:mydomain.com+wiz,mydomain.com+mike

Also changed the stand alone startup command "tracd" to start the server as follows:

root@mydomain:~# tracd -p 8000 --basic-auth=*,/projects/projects.passwd,mydomain.com /projects/trac/sandbox

Server starting in PID 604.
Serving on 0.0.0.0:8000 view at http://127.0.0.1:8000/

Open up browser and typed the http://mydomain.com:8000/ in address bar...
Trac now allows authentication and works with above defined users...