Turbocharge your web development with Rails Vagmi Mudumbai Dharana Software Innovations Pvt Ltd @vagmi / vagmi@dharanasoft.com
About me http://vagmim.com RailsPundit ChennaiGeeks facebook.com/groups/chennaigeeks
http://www.catb.org/~esr/hacker-emblem/
Agenda • About Ruby • Controllers • About Rails • Layouts • MVC • Views • Models • Forms • Relationships • Q &A • Routes
•Created by Yakuhiro “Matz” Matsumoto in 1995 in Japan •Generally available to the english speaking world at 2000
•Multi paradigm language •Supports imperative/Object Oriented/ Functional styles of programming
# The Greeter class class Greeter def initialize(name) @name = name.capitalize end def salute puts "Hello #{@name}!" end end # Create a new object g = Greeter.new("world") # Output "Hello World!" g.salute
•Many Flavors •MRI/YARV •JRuby •Rubinius •IronRuby •Maglev •And more
• Created in 2005 by David Heinemeier Hannson (a.k.a. DHH) • A web framework to helps you actually enjoy programming
• Intended to be simple and consistent to use • Convention over configuration • Freedom from needless XML situps
Installing Ruby • For windows you can get Ruby from • http://rubyinstaller.org/
Installing Ruby • For Linux and Mac OSX • Install via RVM • http://rvm.beginrescueend.com/ • http://amerine.net/2010/02/24/rvm-rails3- ruby-1-9-2-setup.html
Installing Rails $ gem install rails
Rails MVC Router Controller View Model DB HTML/CSS/JS
Create a Rails App $ rails new todolist
Rails Project Structure myapp/ |-- Gemfile # all the dependencies go here |-- Rakefile # the build file?? |-- app # The entire application sits here |-- config # Configure the app to your heart's content |-- db # Database migrations, seed file |-- lib # Custom rake tasks and your libraries |-- log # The directory we all love |-- public # Static assets like CSS, JS and images |-- script # Contains one file "rails" |-- test # Tests - unit, functional, integration |-- tmp # misc stuff like sessions, pids and working files `-- vendor # 3rd party stuff - not used as much these days
Rails Project Structure myapp/ `-- app |-- controllers # controllers | `-- application_controller.rb |-- helpers | `-- application_helper.rb # view helpers |-- mailers |-- models `-- views `-- layouts `-- application.html.erb # could be haml or any other # templating language
Rails Project Structure myapp/ `-- config |-- application.rb # the main application config file |-- boot.rb # setup bundler and the environment |-- database.yml # setup database connections |-- environments | |-- development.rb # development specific setup | |-- production.rb # production specific setup | `-- test.rb # test specific setup |-- initializers | |-- inflections.rb # any file put inside | |-- mime_types.rb # this directory will | |-- secret_token.rb # be executed when the | `-- session_store.rb # rails application boots |-- locales | `-- en.yml # setup internationalization `-- routes.rb # map URLs to Controllers/Actions
Models
Create a model $ rails g model todo title:string done:boolean completed_at:datetime invoke active_record create db/migrate/20110625034305_create_todos.rb create app/models/todo.rb invoke test_unit create test/unit/todo_test.rb create test/fixtures/todos.yml
class CreateTodos < ActiveRecord::Migration def self.up create_table :todos do |t| t.string :title t.boolean :done t.datetime :completed_at t.timestamps end end def self.down drop_table :todos end end Migration
The model class class Todo < ActiveRecord::Base # seriously thats it # rails does rest of the magic end
Create the table $ rake db:migrate (in /path/to/myapp) == CreateTodos: migrating ================ -- create_table(:todos) -> 0.0015s == CreateTodos: migrated (0.0016s) ===========================================
$ rails console Loading development environment (Rails 3.0.7) ruby-1.9.2-p180 :001 > The Rails console The REPL for Rails
> todo=Todo.new # => #<Todo id: nil, title: nil, done: nil, completed_at: nil, created_at: nil, updated_at: nil> > todo.title="Some title" # => "Some title" > todo.save # AREL (0.5ms) INSERT INTO "todos" ("title", "done", "completed_at", "created_at", "updated_at") VALUES ('Some title', NULL, NULL, '2011-06-25 04:21:47.272312', '2011-06-25 04:21:47.272312') => true Create a new object
> todo = Todo.new(:title=>"Teach Rails",:done=>true,:completed_at=>Time.now) => #<Todo id: nil, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: nil, updated_at: nil> > todo.save AREL (0.8ms) INSERT INTO "todos" ("title", "done", "completed_at", "created_at", "updated_at") VALUES ('Teach Rails', 't', '2011-06-25 04:26:29.853087', '2011-06-25 04:26:38.869335', '2011-06-25 04:26:38.869335') => true Create a new object
Querying > Todo.where(:done=>true).all Todo Load (0.4ms) SELECT "todos".* FROM "todos" WHERE "todos"."done" = 't' => [#<Todo id: 2, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 04:26:38">]
> t = Todo.where(:done=>true).first Todo Load (0.4ms) SELECT "todos".* FROM "todos" WHERE "todos"."done" = 't' LIMIT 1 => #<Todo id: 2, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 04:26:38"> > t.done=false => false > t.save AREL (0.5ms) UPDATE "todos" SET "done" = 'f', "updated_at" = '2011-06-25 05:31:07.025845' WHERE "todos"."id" = 2 => true Update object
Deleting objects > t.destroy AREL (0.5ms) DELETE FROM "todos" WHERE "todos"."id" = 2 => #<Todo id: 2, title: "Teach Rails", done: false, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 05:31:07">
Relationships $ rails g bucket name:string $ rails g task title:string done:boolean bucket:references create_table :buckets do |t| class Bucket < ActiveRecord::Base t.string :name has_many :tasks t.timestamps end end create_table :tasks do |t| t.string :title class Task < ActiveRecord::Base t.boolean :done belongs_to :bucket t.references :bucket end t.timestamps end
Creating and querying relationships > bucket = Bucket.create(:name=>"work") # create work bucket > bucket.tasks.create(:title=>"Fill in timesheets") # create task under bucket > bucket.tasks.create(:title=>"Fix bug #234") #create another task > bucket.tasks.count # => 2 > bucket.tasks > t=Task.first # get the task object > t.bucket # access the bucket object from the task object
Still awake?
Controllers & Routes
config/routes.rb Myapp::Application.routes.draw do # direct root (/) to WelcomeController's # index action root :to => "welcome#index" end $ rails g controller welcome
Welcome Controller # app/controllers/welcome_controller.rb class WelcomeController < ApplicationController def index render :text=>"hello world" end end
Views # app/controller/welcome_controller.rb class WelcomeController < ApplicationController def index @time = Time.now end end <!-- in app/views/welcome/index.html.erb --> <h1>The time is <%=@time.strftime('%d-%b-%Y %H:%M: %S')%></h1>
ReST and Resources Myapp::Application.routes.draw do resources :tasks end $ rake routes (in /path/to/myapp) tasks GET /tasks(.:format) {:action=>"index", :controller=>"tasks"} POST /tasks(.:format) {:action=>"create", :controller=>"tasks"} new_task GET /tasks/new(.:format) {:action=>"new", :controller=>"tasks"} edit_task GET /tasks/:id/edit(.:format) {:action=>"edit", :controller=>"tasks"} task GET /tasks/:id(.:format) {:action=>"show", :controller=>"tasks"} PUT /tasks/:id(.:format) {:action=>"update", :controller=>"tasks"} DELETE /tasks/:id(.:format) {:action=>"destroy", :controller=>"tasks"}
ReST and Resources class TasksController < ApplicationController # index displays a list of tasks # new presents a form to create a task # create processes the form submitted by the new action # show displays an individual task # edit presents a form to update a task # update processes the form submitted by the edit action # destroy deletes a task end
Nested resources Myapp::Application.routes.draw do resources :buckets, :shallow=>true do resources :tasks end end $ rake routes (in /path/to/myapp) bucket_tasks GET /buckets/:bucket_id/tasks(.:format) {:action=>"index", :controller=>"tasks"} POST /buckets/:bucket_id/tasks(.:format) {:action=>"create", :controller=>"tasks"} new_bucket_task GET /buckets/:bucket_id/tasks/new(.:format) {:action=>"new", :controller=>"tasks"} edit_task GET /tasks/:id/edit(.:format) {:action=>"edit", :controller=>"tasks"} task GET /tasks/:id(.:format) {:action=>"show", :controller=>"tasks"} PUT /tasks/:id(.:format) {:action=>"update", :controller=>"tasks"} DELETE /tasks/:id(.:format) {:action=>"destroy", :controller=>"tasks"} buckets GET /buckets(.:format) {:action=>"index", :controller=>"buckets"} POST /buckets(.:format) {:action=>"create", :controller=>"buckets"} new_bucket GET /buckets/new(.:format) {:action=>"new", :controller=>"buckets"} edit_bucket GET /buckets/:id/edit(.:format) {:action=>"edit", :controller=>"buckets"} bucket GET /buckets/:id(.:format) {:action=>"show", :controller=>"buckets"} PUT /buckets/:id(.:format) {:action=>"update", :controller=>"buckets"} DELETE /buckets/:id(.:format) {:action=>"destroy", :controller=>"buckets"} * If you squint hard enough, you will be able to read it.
BucketsController def index @buckets = Bucket.all end def show @bucket=Bucket.find(params[:id]) end def destroy @bucket=Bucket.find(params[:id]) @bucket.destroy redirect_to buckets_path end
BucketsController def new @bucket = Bucket.new end def create @bucket = Bucket.new(params[:bucket]) if(@bucket.save) flash[:notice] = "Bucket created" redirect_to @bucket else render :action=>:new end end
BucketsController def edit @bucket = Bucket.find(params[:id]) end def update @bucket=Bucket.find(params[:id]) if(@bucket.update_attributes(params[:bucket])) flash[:notice]="Bucket updated" redirect_to @bucket else render :action=>:edit end end
Tasks Controller def new @bucket = Bucket.find(params[:bucket_id]) @task = @bucket.tasks.build end def create @bucket = Bucket.find(params[:bucket_id]) # the form should have passed bucket_id # as one of the parameters via # a hidden field @task = Task.new(params[:task]) if(@task.save) flash[:notice]="task created" redirect_to @task else render :action=>:new end end The other actions remain the same
Fantastic Forms
Formtastic # add these to your # Gemfile gem 'formtastic' gem 'jquery-rails' $ rails g formtastic:install $ rails g jquery:install <!-- in app/views/buckets/new.html.erb --> <%= semantic_form_for @bucket do |f| %> <%= f.inputs %> <%= f.buttons %> <% end %>
Hands On
Vagmi Mudumbai vagmi@dharanasoft.com twitter.com/vagmi facebook.com/vagmi linkedin.com/in/vagmi github.com/vagmi plus.google.com/ 106483555843485143380/ Thank you

Ruby on Rails - Introduction

  • 1.
    Turbocharge your web developmentwith Rails Vagmi Mudumbai Dharana Software Innovations Pvt Ltd @vagmi / vagmi@dharanasoft.com
  • 2.
    About me http://vagmim.com RailsPundit ChennaiGeeks facebook.com/groups/chennaigeeks
  • 3.
  • 5.
    Agenda • About Ruby • Controllers • About Rails • Layouts • MVC • Views • Models • Forms • Relationships • Q &A • Routes
  • 6.
    •Created by Yakuhiro “Matz” Matsumoto in 1995 in Japan •Generally available to the english speaking world at 2000
  • 7.
    •Multi paradigm language •Supportsimperative/Object Oriented/ Functional styles of programming
  • 8.
    # The Greeterclass class Greeter def initialize(name) @name = name.capitalize end def salute puts "Hello #{@name}!" end end # Create a new object g = Greeter.new("world") # Output "Hello World!" g.salute
  • 9.
    •Many Flavors •MRI/YARV •JRuby •Rubinius •IronRuby •Maglev •And more
  • 10.
    • Created in2005 by David Heinemeier Hannson (a.k.a. DHH) • A web framework to helps you actually enjoy programming
  • 11.
    • Intended tobe simple and consistent to use • Convention over configuration • Freedom from needless XML situps
  • 12.
    Installing Ruby • Forwindows you can get Ruby from • http://rubyinstaller.org/
  • 13.
    Installing Ruby • ForLinux and Mac OSX • Install via RVM • http://rvm.beginrescueend.com/ • http://amerine.net/2010/02/24/rvm-rails3- ruby-1-9-2-setup.html
  • 14.
  • 15.
    Rails MVC Router Controller View Model DB HTML/CSS/JS
  • 16.
    Create a RailsApp $ rails new todolist
  • 17.
    Rails Project Structure myapp/ |--Gemfile # all the dependencies go here |-- Rakefile # the build file?? |-- app # The entire application sits here |-- config # Configure the app to your heart's content |-- db # Database migrations, seed file |-- lib # Custom rake tasks and your libraries |-- log # The directory we all love |-- public # Static assets like CSS, JS and images |-- script # Contains one file "rails" |-- test # Tests - unit, functional, integration |-- tmp # misc stuff like sessions, pids and working files `-- vendor # 3rd party stuff - not used as much these days
  • 18.
    Rails Project Structure myapp/ `--app |-- controllers # controllers | `-- application_controller.rb |-- helpers | `-- application_helper.rb # view helpers |-- mailers |-- models `-- views `-- layouts `-- application.html.erb # could be haml or any other # templating language
  • 19.
    Rails Project Structure myapp/ `--config |-- application.rb # the main application config file |-- boot.rb # setup bundler and the environment |-- database.yml # setup database connections |-- environments | |-- development.rb # development specific setup | |-- production.rb # production specific setup | `-- test.rb # test specific setup |-- initializers | |-- inflections.rb # any file put inside | |-- mime_types.rb # this directory will | |-- secret_token.rb # be executed when the | `-- session_store.rb # rails application boots |-- locales | `-- en.yml # setup internationalization `-- routes.rb # map URLs to Controllers/Actions
  • 20.
  • 21.
    Create a model $rails g model todo title:string done:boolean completed_at:datetime invoke active_record create db/migrate/20110625034305_create_todos.rb create app/models/todo.rb invoke test_unit create test/unit/todo_test.rb create test/fixtures/todos.yml
  • 22.
    class CreateTodos <ActiveRecord::Migration def self.up create_table :todos do |t| t.string :title t.boolean :done t.datetime :completed_at t.timestamps end end def self.down drop_table :todos end end Migration
  • 23.
    The model class classTodo < ActiveRecord::Base # seriously thats it # rails does rest of the magic end
  • 24.
    Create the table $rake db:migrate (in /path/to/myapp) == CreateTodos: migrating ================ -- create_table(:todos) -> 0.0015s == CreateTodos: migrated (0.0016s) ===========================================
  • 25.
    $ rails console Loadingdevelopment environment (Rails 3.0.7) ruby-1.9.2-p180 :001 > The Rails console The REPL for Rails
  • 26.
    > todo=Todo.new # =>#<Todo id: nil, title: nil, done: nil, completed_at: nil, created_at: nil, updated_at: nil> > todo.title="Some title" # => "Some title" > todo.save # AREL (0.5ms) INSERT INTO "todos" ("title", "done", "completed_at", "created_at", "updated_at") VALUES ('Some title', NULL, NULL, '2011-06-25 04:21:47.272312', '2011-06-25 04:21:47.272312') => true Create a new object
  • 27.
    > todo =Todo.new(:title=>"Teach Rails",:done=>true,:completed_at=>Time.now) => #<Todo id: nil, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: nil, updated_at: nil> > todo.save AREL (0.8ms) INSERT INTO "todos" ("title", "done", "completed_at", "created_at", "updated_at") VALUES ('Teach Rails', 't', '2011-06-25 04:26:29.853087', '2011-06-25 04:26:38.869335', '2011-06-25 04:26:38.869335') => true Create a new object
  • 28.
    Querying > Todo.where(:done=>true).all Todo Load (0.4ms) SELECT "todos".* FROM "todos" WHERE "todos"."done" = 't' => [#<Todo id: 2, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 04:26:38">]
  • 29.
    > t =Todo.where(:done=>true).first Todo Load (0.4ms) SELECT "todos".* FROM "todos" WHERE "todos"."done" = 't' LIMIT 1 => #<Todo id: 2, title: "Teach Rails", done: true, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 04:26:38"> > t.done=false => false > t.save AREL (0.5ms) UPDATE "todos" SET "done" = 'f', "updated_at" = '2011-06-25 05:31:07.025845' WHERE "todos"."id" = 2 => true Update object
  • 30.
    Deleting objects > t.destroy AREL (0.5ms) DELETE FROM "todos" WHERE "todos"."id" = 2 => #<Todo id: 2, title: "Teach Rails", done: false, completed_at: "2011-06-25 04:26:29", created_at: "2011-06-25 04:26:38", updated_at: "2011-06-25 05:31:07">
  • 31.
    Relationships $ rails gbucket name:string $ rails g task title:string done:boolean bucket:references create_table :buckets do |t| class Bucket < ActiveRecord::Base t.string :name has_many :tasks t.timestamps end end create_table :tasks do |t| t.string :title class Task < ActiveRecord::Base t.boolean :done belongs_to :bucket t.references :bucket end t.timestamps end
  • 32.
    Creating and queryingrelationships > bucket = Bucket.create(:name=>"work") # create work bucket > bucket.tasks.create(:title=>"Fill in timesheets") # create task under bucket > bucket.tasks.create(:title=>"Fix bug #234") #create another task > bucket.tasks.count # => 2 > bucket.tasks > t=Task.first # get the task object > t.bucket # access the bucket object from the task object
  • 33.
  • 34.
  • 35.
    config/routes.rb Myapp::Application.routes.draw do # direct root (/) to WelcomeController's # index action root :to => "welcome#index" end $ rails g controller welcome
  • 36.
    Welcome Controller # app/controllers/welcome_controller.rb classWelcomeController < ApplicationController def index render :text=>"hello world" end end
  • 37.
    Views #app/controller/welcome_controller.rb class WelcomeController < ApplicationController def index @time = Time.now end end <!-- in app/views/welcome/index.html.erb --> <h1>The time is <%=@time.strftime('%d-%b-%Y %H:%M: %S')%></h1>
  • 38.
    ReST and Resources Myapp::Application.routes.draw do resources :tasks end $ rake routes (in /path/to/myapp) tasks GET /tasks(.:format) {:action=>"index", :controller=>"tasks"} POST /tasks(.:format) {:action=>"create", :controller=>"tasks"} new_task GET /tasks/new(.:format) {:action=>"new", :controller=>"tasks"} edit_task GET /tasks/:id/edit(.:format) {:action=>"edit", :controller=>"tasks"} task GET /tasks/:id(.:format) {:action=>"show", :controller=>"tasks"} PUT /tasks/:id(.:format) {:action=>"update", :controller=>"tasks"} DELETE /tasks/:id(.:format) {:action=>"destroy", :controller=>"tasks"}
  • 39.
    ReST and Resources classTasksController < ApplicationController # index displays a list of tasks # new presents a form to create a task # create processes the form submitted by the new action # show displays an individual task # edit presents a form to update a task # update processes the form submitted by the edit action # destroy deletes a task end
  • 40.
    Nested resources Myapp::Application.routes.draw do resources :buckets, :shallow=>true do resources :tasks end end $ rake routes (in /path/to/myapp) bucket_tasks GET /buckets/:bucket_id/tasks(.:format) {:action=>"index", :controller=>"tasks"} POST /buckets/:bucket_id/tasks(.:format) {:action=>"create", :controller=>"tasks"} new_bucket_task GET /buckets/:bucket_id/tasks/new(.:format) {:action=>"new", :controller=>"tasks"} edit_task GET /tasks/:id/edit(.:format) {:action=>"edit", :controller=>"tasks"} task GET /tasks/:id(.:format) {:action=>"show", :controller=>"tasks"} PUT /tasks/:id(.:format) {:action=>"update", :controller=>"tasks"} DELETE /tasks/:id(.:format) {:action=>"destroy", :controller=>"tasks"} buckets GET /buckets(.:format) {:action=>"index", :controller=>"buckets"} POST /buckets(.:format) {:action=>"create", :controller=>"buckets"} new_bucket GET /buckets/new(.:format) {:action=>"new", :controller=>"buckets"} edit_bucket GET /buckets/:id/edit(.:format) {:action=>"edit", :controller=>"buckets"} bucket GET /buckets/:id(.:format) {:action=>"show", :controller=>"buckets"} PUT /buckets/:id(.:format) {:action=>"update", :controller=>"buckets"} DELETE /buckets/:id(.:format) {:action=>"destroy", :controller=>"buckets"} * If you squint hard enough, you will be able to read it.
  • 41.
    BucketsController def index @buckets = Bucket.all end def show @bucket=Bucket.find(params[:id]) end def destroy @bucket=Bucket.find(params[:id]) @bucket.destroy redirect_to buckets_path end
  • 42.
    BucketsController def new @bucket = Bucket.new end def create @bucket = Bucket.new(params[:bucket]) if(@bucket.save) flash[:notice] = "Bucket created" redirect_to @bucket else render :action=>:new end end
  • 43.
    BucketsController def edit @bucket = Bucket.find(params[:id]) end def update @bucket=Bucket.find(params[:id]) if(@bucket.update_attributes(params[:bucket])) flash[:notice]="Bucket updated" redirect_to @bucket else render :action=>:edit end end
  • 44.
    Tasks Controller def new @bucket = Bucket.find(params[:bucket_id]) @task = @bucket.tasks.build end def create @bucket = Bucket.find(params[:bucket_id]) # the form should have passed bucket_id # as one of the parameters via # a hidden field @task = Task.new(params[:task]) if(@task.save) flash[:notice]="task created" redirect_to @task else render :action=>:new end end The other actions remain the same
  • 45.
  • 46.
    Formtastic # add these to your # Gemfile gem 'formtastic' gem 'jquery-rails' $ rails g formtastic:install $ rails g jquery:install <!-- in app/views/buckets/new.html.erb --> <%= semantic_form_for @bucket do |f| %> <%= f.inputs %> <%= f.buttons %> <% end %>
  • 47.
  • 48.
    Vagmi Mudumbai vagmi@dharanasoft.com twitter.com/vagmi facebook.com/vagmi linkedin.com/in/vagmi github.com/vagmi plus.google.com/ 106483555843485143380/ Thank you