Professional Documents
Culture Documents
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
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
Cucumber + RSpec
Contest!
Letʼs Chat