Hello
May 12, 2015
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