You are on page 1of 160

Hello

Robert Dempsey
adsdevshop.com
adsdevshop.com/apps
rdempsey
A-Z Intro To
Ruby on Rails
Always
Be
Learning
Teach Others
Be Bold
Whatʼs Going On
• Introduction to Ruby
• Introduction to Rails
• Hands-on Lab
• Breaks interspersed
Ruby
1995
2006
Perl
SmallTalk
Eiffel
Ada
+ Lisp
Ruby
#10 baby!
5.times { print “We love Ruby” }
class Numeric
def plus(x)
self.+(x)
end
end

y = 5.plus 6
# y is now equal to 11
Rails
2005
Image copyright 2008 Yoshiko314 (Flickr)
MVC
Model
View
Controller
Model
View
Controller
Model
View
Controller
Model
View
Controller
map.root :controller => ʻemployersʼ
Action HTTP Method URL XML
index GET /jobs /jobs.xml

show GET /jobs/1 /jobs/1.xml

new GET /jobs/new

edit GET /jobs/1;edit

create POST /jobs /jobs.xml

update PUT /jobs/1 /jobs/1.xml

destroy DELETE /jobs/1 /jobs/1.xml


Letʼs Build
Something
The Project
• Employers
• Jobs
rails jobby -d postgresql
rails jobby -d mysql
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
app/
controllers/
helpers/
models/
views/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
README
Rakefile
app/
config/
db/
doc/
lib/
log/
public/
script/
test/
tmp/
vendor/
development:
adapter: postgresql
encoding: unicode
database: jobby_development
pool: 5
username: root
password:

config/database.yml
development:
adapter: mysql
encoding: utf8
database: jobby_development
pool: 5
username: root
password:
socket: /tmp/mysql.sock

config/database.yml
rake db:create
script/server
rm public/index.html
map.connect ʻ:controller/:action/:idʼ

map.connect ʻ:controller/:action/:id.:formatʼ

config/routes.rb
script/generate model Employer
script/generate scaffold Employer
name:string
address:string
city:string
state:string
zipcode:string
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/employers
exists app/views/layouts/
exists test/functional/
exists test/unit/
create test/unit/helpers/
exists public/stylesheets/
create app/views/employers/index.html.erb
create app/views/employers/show.html.erb
create app/views/employers/new.html.erb
create app/views/employers/edit.html.erb
create app/views/layouts/employers.html.erb
create public/stylesheets/scaffold.css
create app/controllers/employers_controller.rb
create test/functional/employers_controller_test.rb
create app/helpers/employers_helper.rb
create test/unit/helpers/employers_helper_test.rb
route map.resources :employers
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/employer.rb
create test/unit/employer_test.rb
create test/fixtures/employers.yml
create db/migrate
create db/migrate/20090501175821_create_employers.rb
app/models/employer.rb
db/migrate/20090...1_create_employers.rb
app/views/employers/index.html.erb
app/views/employers/show.html.erb
app/views/employers/new.html.erb
app/views/employers/edit.html.erb
app/views/layouts/employers.html.erb
public/stylesheets/scaffold.css
app/controllers/employers_controller.rb
app/helpers/employers_helper.rb
test/functional/employers_controller_test.rb
test/unit/helpers/employers_helper_test.rb
test/unit/employer_test.rb
test/fixtures/employers.yml
route map.resources :employers
class CreateEmployers < ActiveRecord::Migration
def self.up
create_table :employers do |t|
t.string :name
t.string :address
t.string :city
t.string :state
t.string :zipcode
t.timestamps
end
end

def self.down
drop_table :employers
end
end

db/migrations/2009...create_employers.rb
rake db:migrate
map.root :controller => ʻemployersʼ

config/routes.rb
http://localhost:3000/
class Employer < ActiveRecord::Base
end

app/models/employer.rb
class Employer < ActiveRecord::Base
validates_presence_of :name
validates_length_of :city, :minimum => 3
end

app/models/employer.rb
http://localhost:3000/employers/new
Controller => CRUD
Model => Logic
script/console
# GET /employers
# GET /employers.xml
def index
@employers = Employer.all

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @employers }
end
end

app/controllers/employers_controller.rb
# GET /employers
# GET /employers.xml
def index
@employers = Employer.all

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @employers }
end
end

app/controllers/employers_controller.rb
# GET /employers
# GET /employers.xml
def index
@employers = Employer.all

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml =>
@employers }
end
end

app/controllers/employers_controller.rb
app/views/employers/index.html.erb
<%=h employer.name %>

app/views/employers/index.html.erb
<%= link_to 'New employer', ... %>

app/views/employers/index.html.erb
edit_employer_path(employer)

app/views/employers/index.html.erb
app/views/layouts/employers.html.erb
# GET /employers/new
# GET /employers/new.xml
def new
@employer = Employer.new

respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @employer }
end
end

app/controllers/employers_controller.rb
app/views/employers/new.html.erb
# POST /employers
# POST /employers.xml
def create
@employer = Employer.new(params[:employer])

respond_to do |format|
if @employer.save
flash[:notice] = 'Employer was successfully created.'
format.html { redirect_to(@employer) }
format.xml { render :xml => @employer,
:status => :created, :location => @employer }
else
format.html { render :action => "new" }
format.xml { render :xml => @employer.errors, :status
=> :unprocessable_entity }
end
end
end

app/controllers/employers_controller.rb
# GET /employers/1
# GET /employers/1.xml
def show
@employer = Employer.find(params[:id])

respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @employer }
end
end

app/controllers/employers_controller.rb
app/views/employers/show.html.erb
# GET /employers/1/edit
def edit
@employer = Employer.find(params[:id])
end

app/controllers/employers_controller.rb
app/views/employers/edit.html.erb
# PUT /employers/1
# PUT /employers/1.xml
def update
@employer = Employer.find(params[:id])

respond_to do |format|
if @employer.update_attributes(params[:employer])
flash[:notice] = 'Employer was successfully updated.'
format.html { redirect_to(@employer) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @employer.errors,
:status => :unprocessable_entity }
end
end
end
app/controllers/employers_controller.rb
# DELETE /employers/1
# DELETE /employers/1.xml
def destroy
@employer = Employer.find(params[:id])
@employer.destroy

respond_to do |format|
format.html { redirect_to(employers_url) }
format.xml { head :ok }
end
end

app/controllers/employers_controller.rb
Donʼt
Repeat
Yourself
Partials
_form.html.erb

app/views/employers/_form.html.erb
app/views/employers/_form.html.erb
<%= render :partial => 'form' %>
app/views/employers/new.html.erb
app/views/employers/edit.html.erb
<%= render :partial => 'shared/form' %>
@employer = Employer.find(params[:id])

app/controllers/employers_controller.erb
before_filter :find_employer,
:only => [:show, :edit, :update, :destroy]

app/controllers/employers_controller.rb
app/controllers/employers_controller.rb
private
def find_employer
@employer = Employer.find(params[:id])
end

app/controllers/employers_controller.rb
app/controllers/employers_controller.rb
script/generate scaffold Job
name:string
description:text
class CreateJobs < ActiveRecord::Migration
def self.up
create_table :jobs do |t|
t.integer :employer_id
t.string :name
t.text :description
t.timestamps
end
end

def self.down
drop_table :jobs
end
end
db/migrations/2009...create_jobs.rb
rake db:migrate
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
jobs employers
Model: Job Model: Employer
belongs_to :employer has_many :jobs
id integer id integer
employer_id integer name string
name string address string
employers jobs
Model: Employer Model: Job
has_one :job belongs_to :employer
id integer id integer
name string employer_id integer
address string name string
employers jobs
Model: Employer Model: Job
has_many :jobs belongs_to :employer
id integer id integer
name string employer_id integer
address string name string
physicians
Model: Physician
has_many :appointments
has_many :patients,
:through => :appointments
appointments
id integer
Model: Appointment
name string belongs_to :physician
belongs_to :patient

id integer
patients
physician_id integer
Model: Patient
has_many :appointments
patient_id integer
has_many :physicians,
:through => :appointments

id integer
name string
physicians
Model: Physician
has_and_belongs_to_many :patients

id integer physicians_patients
name string
physician_id integer
patients
patient_id integer
Model: Patient
has_and_belongs_to_many
:physicians

id integer
name string
class Job < ActiveRecord::Base
end

app/models/job.rb
class Job < ActiveRecord::Base
belongs_to :employer

validates_presence_of :name
validates_presence_of :description
end

app/models/job.rb
class Job < ActiveRecord::Base
belongs_to :employer

validates_presence_of :name
validates_presence_of :description
end

app/models/job.rb
class Employer < ActiveRecord::Base
has_many :jobs

validates_presence_of :name
validates_length_of :city, :minimum => 3
end

app/models/employer.rb
map.resources :employers

map.resources :employers,
:has_many => :jobs

map.resources :jobs

app/controllers/employers_controller.rb
before_filter :find_employer

app/controllers/jobs_controller.rb
app/controllers/jobs_controller.rb
private
def find_employer
@employer = Employer.find(params[:employer_id])
end

app/controllers/jobs_controller.rb
app/controllers/jobs_controller.rb
# GET /jobs
# GET /jobs.xml
def index
@jobs = @employer.jobs

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @jobs }
end
end

app/controllers/jobs_controller.rb
# GET /jobs/new
# GET /jobs/new.xml
def new
@job = Job.new
@job = @employer.jobs.build

respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @job }
end
end

app/controllers/jobs_controller.rb
@job = @employer.jobs.build
app/views/jobs/index.html.erb
# POST /jobs
# POST /jobs.xml
def create
@employer = Employer.find(params[:employer_id])
@job = @employer.jobs.build(params[:job])

respond_to do |format|
if @job.save
flash[:notice] = 'Job was successfully created.'
format.html { redirect_to employer_job_url(@employer, @job) }
format.xml { render :xml => @job, :status => :created, :location => @job }
else
format.html { render :action => "new" }
format.xml { render :xml => @job.errors, :status => :unprocessable_entity }
end
end
end

app/controllers/jobs_controller.rb
# GET /jobs/1
# GET /jobs/1.xml
def show
@job = @employer.jobs.find(params[:id])

respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @job }
end
end

app/controllers/jobs_controller.rb
app/views/jobs/show.html.erb
# GET /jobs/1/edit
def edit
@job = @employer.jobs.find(params[:id])
end

app/controllers/jobs_controller.rb
app/views/jobs/edit.html.erb
# PUT /jobs/1
# PUT /jobs/1.xml
def update
@job = Job.find(params[:id])

respond_to do |format|
if @job.update_attributes(params[:job])
flash[:notice] = 'Job was successfully updated.'
format.html { redirect_to employer_job_url(@employer, @job) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @job.errors, :status
=> :unprocessable_entity }
end
end
end

app/controllers/jobs_controller.rb
# DELETE /jobs/1
# DELETE /jobs/1.xml
def destroy
@job = Job.find(params[:id])
@job.destroy

respond_to do |format|
format.html { redirect_to employer_jobs_url(@employer) }
format.xml { head :ok }
end
end

app/controllers/jobs_controller.rb
app/views/employers/show.html.erb
app/views/jobs/index.html.erb
app/views/jobs/index.html.erb
app/views/employers/index.html.erb
app/views/employers/index.html.erb
app/controllers/employers_controller.rb
app/controllers/employers_controller.rb
app/views/employers/index.html.erb
app/views/employers/index.html.erb
app/controllers/jobs_controller.rb
app/controllers/employers_controller.rb
app/views/employers/index.html.erb
Next Steps
DRY up our Job views

Add search to our jobs

Add a logins for employers

Add tags to our jobs


Resources
Rails Guides

Agile Web Development (PP)

Intro to Ruby 1.9

Cucumber + RSpec
Contest!
Letʼs Chat

You might also like