A Z Introduction To Ruby On Rails

Preview:

Citation preview

Hello

Robert Dempsey

adsdevshop.com

adsdevshop.com/apps

rdempsey

A-Z Intro ToRuby on Rails

AlwaysBeLearning

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) endend

y = 5.plus 6# y is now equal to 11

Rails

2005

Image copyright 2008 Yoshiko314 (Flickr)

MVC

ModelViewController

ModelViewController

ModelViewController

ModelViewController

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 BuildSomething

The Project• Employers

• Jobs

rails jobby -d postgresql

rails jobby -d mysql

READMERakefileapp/config/db/doc/lib/log/public/script/test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/log/public/script/test/tmp/vendor/

README

Rakefileapp/config/db/doc/lib/log/public/script/test/tmp/vendor/

READMERakefile

app/config/db/doc/lib/log/public/script/test/tmp/vendor/

app/ controllers/ helpers/ models/ views/

READMERakefileapp/

config/db/doc/lib/log/public/script/test/tmp/vendor/

READMERakefileapp/config/

db/doc/lib/log/public/script/test/tmp/vendor/

READMERakefileapp/config/db/

doc/lib/log/public/script/test/tmp/vendor/

READMERakefileapp/config/db/doc/

lib/log/public/script/test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/

log/public/script/test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/log/

public/script/test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/log/public/

script/test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/log/public/script/

test/tmp/vendor/

READMERakefileapp/config/db/doc/lib/log/public/script/test/

tmp/vendor/

READMERakefileapp/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.rbdb/migrate/20090...1_create_employers.rbapp/views/employers/index.html.erbapp/views/employers/show.html.erbapp/views/employers/new.html.erbapp/views/employers/edit.html.erbapp/views/layouts/employers.html.erbpublic/stylesheets/scaffold.cssapp/controllers/employers_controller.rbapp/helpers/employers_helper.rbtest/functional/employers_controller_test.rbtest/unit/helpers/employers_helper_test.rbtest/unit/employer_test.rbtest/fixtures/employers.ymlroute 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 endend

db/migrations/2009...create_employers.rb

rake db:migrate

map.root :controller => ʻemployersʼ

config/routes.rb

http://localhost:3000/

class Employer < ActiveRecord::Baseend

app/models/employer.rb

class Employer < ActiveRecord::Base validates_presence_of :name validates_length_of :city, :minimum => 3end

app/models/employer.rb

http://localhost:3000/employers/new

Controller => CRUD

Model => Logic

script/console

# GET /employers# GET /employers.xmldef index @employers = Employer.all

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

app/controllers/employers_controller.rb

# GET /employers# GET /employers.xmldef index @employers = Employer.all

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

app/controllers/employers_controller.rb

# GET /employers# GET /employers.xmldef index @employers = Employer.all

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

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.xmldef new @employer = Employer.new

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

app/controllers/employers_controller.rb

app/views/employers/new.html.erb

# POST /employers# POST /employers.xmldef 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 endend

app/controllers/employers_controller.rb

# GET /employers/1# GET /employers/1.xmldef show @employer = Employer.find(params[:id])

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

app/controllers/employers_controller.rb

app/views/employers/show.html.erb

# GET /employers/1/editdef edit @employer = Employer.find(params[:id])end

app/controllers/employers_controller.rb

app/views/employers/edit.html.erb

# PUT /employers/1# PUT /employers/1.xmldef 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 endend

app/controllers/employers_controller.rb

# DELETE /employers/1# DELETE /employers/1.xmldef destroy @employer = Employer.find(params[:id]) @employer.destroy

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

app/controllers/employers_controller.rb

DonʼtRepeatYourself

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 endend

db/migrations/2009...create_jobs.rb

rake db:migrate

belongs_tohas_onehas_manyhas_many :throughhas_one :throughhas_and_belongs_to_many

employersemployersModel: EmployerModel: Employerhas_many :jobshas_many :jobs

id integer

name string

address string

jobsjobsModel: JobModel: Jobbelongs_to :employerbelongs_to :employer

id integer

employer_id integer

name string

employersemployersModel: EmployerModel: Employerhas_one :jobhas_one :job

id integer

name string

address string

jobsjobsModel: JobModel: Jobbelongs_to :employerbelongs_to :employer

id integer

employer_id integer

name string

employersemployersModel: EmployerModel: Employerhas_many :jobshas_many :jobs

id integer

name string

address string

jobsjobsModel: JobModel: Jobbelongs_to :employerbelongs_to :employer

id integer

employer_id integer

name string

physiciansphysiciansModel: PhysicianModel: Physicianhas_many :appointmentshas_many :patients, :through => :appointments

has_many :appointmentshas_many :patients, :through => :appointments

id integer

name string

appointmentsappointmentsModel: AppointmentModel: Appointmentbelongs_to :physicianbelongs_to :patientbelongs_to :physicianbelongs_to :patient

id integerphysician_id integer

patient_id integer

patientspatientsModel: PatientModel: Patienthas_many :appointmentshas_many :physicians, :through => :appointments

has_many :appointmentshas_many :physicians, :through => :appointments

id integer

name string

physiciansphysiciansModel: PhysicianModel: Physicianhas_and_belongs_to_many :patientshas_and_belongs_to_many :patients

id integer

name stringphysicians_patientsphysicians_patients

physician_id integer

patient_id integerpatientspatients

Model: PatientModel: Patienthas_and_belongs_to_many :physicianshas_and_belongs_to_many :physicians

id integer

name string

class Job < ActiveRecord::Baseend

app/models/job.rb

class Job < ActiveRecord::Base belongs_to :employer

validates_presence_of :name validates_presence_of :descriptionend

app/models/job.rb

class Job < ActiveRecord::Base belongs_to :employer

validates_presence_of :name validates_presence_of :descriptionend

app/models/job.rb

class Employer < ActiveRecord::Base has_many :jobs

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

app/models/employer.rb

map.resources :employers

app/controllers/employers_controller.rb

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

map.resources :jobs

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.xmldef index @jobs = @employer.jobs

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

app/controllers/jobs_controller.rb

# GET /jobs/new# GET /jobs/new.xmldef new @job = Job.new @job = @employer.jobs.build

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

app/controllers/jobs_controller.rb

@job = @employer.jobs.build

app/views/jobs/index.html.erb

# POST /jobs# POST /jobs.xmldef 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 endend

app/controllers/jobs_controller.rb

# GET /jobs/1# GET /jobs/1.xmldef show @job = @employer.jobs.find(params[:id])

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

app/controllers/jobs_controller.rb

app/views/jobs/show.html.erb

# GET /jobs/1/editdef 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.xmldef 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 endend

app/controllers/jobs_controller.rb

# DELETE /jobs/1# DELETE /jobs/1.xmldef destroy @job = Job.find(params[:id]) @job.destroy

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

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