Rails Basics

From Wiki
Jump to navigation Jump to search

Installation

  • Install ruby and rubygems as you would any other package.
  • Use gems to install rails:
sudo gem update
sudo gem install rails
  • To match a specific version:
gem install rails -v 2.3.5
  • show installed gems:
gem list
  • make links to /var/lib/gems/1.8/bin binaries in /usr/local/bin

More Installation Wisdom

I wanted to be able to develop this on my macbook too. I installed ruby and rubygems from source. I ended up getting version 1.3.1 of rubygems and 2.2.2 of rails, which was higher than on my Ubuntu Intrepid machine. So I had to update rubygems beyond the official intrepid version using this:

sudo gem install rubygems-update
cd /var/lib/gems/1.8/bin
sudo ./update_rubygems

Now I have to reinstall the latest gems all over again:

sudo gem install rails composite_primary_keys

There were also problems because rails has dropped default support for mysql:

sudo apt-get install ruby1.8-dev libmysqlclient15-dev
sudo gem install mysql

Edits to config/environment.rb:

  • comment out this line: config.time_zone = 'UTC'
  • add this line: require 'composite_primary_keys'

Copied old config/database.yml to new project

Reference

Application Setup

  • Create rails app:
rails -d mysql cookbook

This creates a big directory containing all code for the project.

  • Login to mysql as root and create mysql databases:
mysql> create database cookbook_dev;
mysql> create database cookbook_test;
mysql> create database cookbook_prod;
  • Create a mysql user account and give it rights to the databases:
mysql> grant all privileges on cookbook_dev.* to 'rails_user'@'localhost' identified by 'r8!lz';
mysql> grant all privileges on cookbook_test.* to 'rails_user'@'localhost' identified by 'r8!lz';
mysql> grant all privileges on cookbook_prod.* to 'rails_user'@'localhost' identified by 'r8!lz';
  • Define tables. Edit a file called create-mysql-db.sql:
drop table if exists 'chapters';
create table chapters (
    id                             int not null auto_increment,
    title                          varchar(255) not null,
    sort_order                     int not null default 0,
        primary key (id)
) type=innodb;

drop table if exists 'recipes';
create table recipes (
    id                             int not null auto_increment,
    chapter_id                     int not null,
    title                          varchar(255) not null,
    problem                        text not null,
    solution                       text not null,
    discussion                     text not null,
    see_also                       text null,
    sort_order                     int not null default 0,
        primary key (id, chapter_id, title),
        foreign key (chapter_id) references chapters(id)
) type=innodb;

drop table if exists 'tags';
create table tags (
    id                             int not null auto_increment,
    name                           varchar(80) not null,
        primary key (id)
) type=innodb;

drop table if exists 'recipes_tags';
create table recipes_tags (
    recipe_id                      int not null,
    tag_id                         int not null,
        primary key (recipe_id, tag_id),
        foreign key (recipe_id) references recipes(id),
        foreign key (tag_id)  references tags(id)
) type=innodb;
  • Create tables:
$ mysql cookbook_dev -u rails_user -p < create-mysql-db.sql
$ mysql cookbook_test -u rails_user -p < create-mysql-db.sql
$ mysql cookbook_prod -u rails_user -p < create-mysql-db.sql
  • Edit config/database.yml to have the right username/password for each database (double-check database names too).

Model

To create an object that will be linked to a database table (e.g. users):

ruby script/generate model <object/table name (singular form)>

For example:

ruby script/generate model user

This creates a file called app/models/user.rb, which defines a User ActiveRecord class. Edit this file to add table relationships. For example, we might have cookbook/app/models/chapter.rb:

class Chapter < ActiveRecord::Base
  has_many :recipes
end

Other relationship functions include belongs_to and has_and_belongs_to_many.

Find example:

found_user = User.find(userid)
found_user = User.find(:first, :conditions => ["email = ?", email])

Controller

To control an object's behavior:

ruby script/generate controller <object (single form)> <list of actions>

For example:

ruby script/generate controller user add delete login logout

This command creates a file app/controllers/user_controller.rb, which defines a class UserController. The class defines four stub methods: add, delete, login, and logout.

Logging from a controller

class HomeController < ActionController::Base
  def index
    logger.info 'informational message'
  end
end

This will show up in the server log. Log levels are debug, info, warn, error, and fatal. In production, debug entries are omitted.

View

The view files are created automatically for each action specified at controller creation. The same command that created the UserController class above also created four files in app/views/user/: add.rhtml, delete.rhtml, login.rhtml, and logout.rhtml. A user accesses the view by opening http://www.example.com/my_app/add.

Info on select vs select_tag vs collection_select: http://shiningthrough.co.uk/blog/show/6

Editing .rhtml files

  • Use <% ... %> to hold ruby code that should be processed.
  • Use <%= ... %> to also print the output of the code.
  • Comments:
<%
=begin
This style will work with scriplets too  <%= now.broken.function(foo) %>
=end
%>

<% if false %>
so will this style <%= now.broken.function(foo) %>
<% end %>

Access to data

  • The view can access the controller's instance variables like @name.
  • The view can't access any of the controller's methods, class variables (@@my_class_name), or constants.
  • The view can access global constants defined in config/environment.rb.

Layouts/Templates

  • To apply a layout to every page in your web application, create a file called app/views/layouts/application.rhtml. It should look something like this:
<html><head><title>My Website</title></head>
<body>
    <%= @content_for_layout %>
</body></html>
  • Make a view-specific template by creating app/views/layouts/my_view.rhtml.
  • Layouts can access all of the same data that views can.