A-Z Intro To Rails

4,744 views

Published on

The slides from my A-Z Intro to Ruby on Rails at RailsConf 09.

Published in: Technology
6 Comments
10 Likes
Statistics
Notes
No Downloads
Views
Total views
4,744
On SlideShare
0
From Embeds
0
Number of Embeds
718
Actions
Shares
0
Downloads
191
Comments
6
Likes
10
Embeds 0
No embeds

No notes for slide

  • My name is Robert Dempsey
  • I’ll be graduating with an MBA from Crummer in August.
  • Certified ScrumMaster
  • I’m the CEO of ADS, a web development shop in Orlando
  • We develop an online suite of apps
    Scrum’d: simple project management for agile teams
    Expens’d: simple expense tracking
    Prioritiz’d: all about getting things done
  • Find me on Twitter
  • My wife and daughter are here in Las Vegas

  • Two quick movies I want to share




  • A few people commented on our blog
    I can provide specific help after the tutorial
  • Ruby
  • Created by Yukihiro “matz” Matsumoto
  • 1995 - public release
  • 2006 - gained mass acceptance
  • Blending of languages: Perl, Smalltalk, Eiffel, Ada, and Lisp
  • Ranked #10 in the world on the Tiobe index, April 2009
  • Open source
  • Everything is an object
    Everything can be given it’s own properties (instance variables) and actions (methods)
    All types have methods and instance variables
    The same rules apply everywhere
  • Ruby is Flexible
    Freely alter Ruby’s parts
    Remove, redefine, and extend at will
  • Ruby is Easy on the Eyes and Brain
    Very limited punctuation
    Preference for English keywords
    Enhanced readability and reduced learning curve

  • Created by David Heinemeier Hansson
    Extracted from Basecamp - 37signals
  • Released to the public
  • Full-stack framework for developing database-backed web applications
    Uses the Model-View-Controller pattern
    Builds on the power of Ruby
    Stresses convention over configuration
  • Productivity gains: smaller teams, faster time to market, more concurrent projects
    Code management: less code = easier management
    Faster development
    Simpler solution for a common problem: web-front end to a database
  • Data warehousing and data mining
    Statistics reporting
    Management systems
    Collaborative applications
    Community sites
    E-commerce applications
    Content management systems
  • Open source


  • A model represents the information (data) of the application and the rules to manipulate that data. In the case of Rails, models are primarily used for managing the rules of interaction with a corresponding database table. In most cases, one table in your database will correspond to one model in your application. The bulk of your application’s business logic will be concentrated in the models.
  • Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that performs tasks related solely to the presentation of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.
  • Controllers provide the “glue” between models and views. In Rails, controllers are responsible for processing the incoming requests from the web browser, interrogating the models for data, and passing that data on to the views for presentation.
  • One route in our app
  • REST
    Maps actions to HTTP methods

  • In the course of building this app I will explain the basics:
    Directory structure
    Migrations
    Models, views, controllers
    Routes
    More
  • Generate a Rails app with the Postgres database
  • Generate a Rails app with the MySQL database
  • Rails directory structure
  • This is a brief instruction manual for your application.
    Use it to tell others what your application does, how to set it up, and so on.
    On GitHub, many devs use this as the home page
  • This file contains batch jobs that can be run from the terminal.
  • Contains the controllers, models, and views for your application.
    You’ll focus on this folder for the remainder of this tutorial.
  • Looking into the app directory, where lot’s of our code goes
  • Configure your application’s runtime rules, routes, database, and more.
  • Shows your current database schema, as well as the database migrations.
  • In-depth documentation for your application.
  • Extended modules for your application (more advanced than we’ll go today)
  • Application log files.
  • The only folder seen to the world as-is. This is where your images, javascript, stylesheets (CSS), and other static files go.
  • Scripts provided by Rails to do recurring tasks, such as benchmarking, plugin installation, and starting the console or the web server.
  • Unit tests, fixtures, and other test apparatus.
  • Temporary files
  • Third-party code.
    Gems, plugins, Rails, etc.
  • Configure the database - Postgres
  • Configure the database - MySQL
  • Create the database
  • Fire up the server
    Starts our application in development mode (by default)
    Can start the local server in development, testing, or production
    * Highly suggest running in production mode for testing OR set up a staging server
  • Browse to http://localhost:3000
    Should see something like this
    The default Rails page, located at public/index.html
  • Remove the public index file

  • The basic way to create the employer model
  • Use scaffolding to create an Employer
    - Typically you’d get rid of this later
    - You’ll need to customize what has been generated
    - The better you get, the less scaffold you’ll use
  • Directories and files created with the generator
  • The biggies
  • The table and fields are created when we run this
  • Run the migration
    Since we’re in development, it will be applied to the dev database
  • Create the default root
    We’ll use this later
    Uncomment the line in routes.rb and change it
  • The list page
    Create two employers
    Update one
    Delete one
  • Our employer model
  • Our employer model
    Add validations: these are two of many
  • Employer errors
  • Skinny controller fat model
    Jamis Buck - Rails core team member
  • The controller has the CRUD, and that’s it
  • Put all logic into the model, not into the controller
    Result: better code reuse, keep details in templates, easier testing
  • The console is a tool that gives us the runtime environment at a command-line
    Use it for testing, rather than trying everything in a browser
    Can fully interact with a database
    Can run in any Rails environment: development, testing, production
    Fire it up
  • Create new objects
    Save objects
    View errors
    Use “reload!” to see updates to your models
  • We first pull up a list of employers using the index action
    Above the action is the REST call
    We can have numerous return formats: html, xml, json
  • Above the action is the REST call
  • Data return formats
    We can have numerous return formats: html, xml, json
  • Index view
  • h is a Rails helper method to sanitize displayed data, preventing cross-site scripting attacks
  • link_to builds a hyperlink to a particular destination
  • edit_employer_path is a helper that Rails provides as part of RESTful routing.
    You’ll see a variety of these helpers for the different actions that the controller includes.
  • Employer layout
    <%= yield %> is where views get rendered into
    The scaffold generator creates a default layout for each model
    We can create a master layout that is applied to all, and either have a per-model layout, or remove them
  • First, create a new employer first by showing the new form
    Instantiate a new employer
  • New view
    Form helpers
    error messages, label, text field, submit
  • The employer is then created by the create action
  • Next we show the employer
    This shows only a single employer
  • Show view
  • If we want to edit the employer we retrieve the employer using the edit action
  • Edit view
  • The update action actually updates the record
  • The destroy action will remove the employer from the database

  • The new and edit forms have the same form fields
  • Name the partial
    In the same view folder as all the other employer stuff
    The &#x201C;_&#x201D; indicates it&#x2019;s a partial
  • The new partial
  • Render the partial
    Can render partials that are in any folder


  • Can render partials that are in any folder by specifying the folder and the partial name
  • Duplicates in the show, edit, update, and delete methods
  • Put it all into a before filter
    Before filters run before actions
    After filters run after actions
    Put this code underneath the controller declaration

  • The code for the before_filter
    Put it at the bottom of the controller above the last end

  • Use scaffolding to create a Job
    Created our model, our views, and our controller
  • Job migration
  • Run the migration
  • Model relationships
  • Belongs_to association
    One-to-one connection
    Each job can be assigned to only one employer
  • Has_one association
    One-to-one connection
    * Used if an employer had one and only one job
  • Has_many association
    The other side of the belongs_to association
    One-to-many connection
    Each instance of employer has 0 or more jobs
  • Has_many through association
    Many-to-many connection
    The third model sets up the association
  • Has_and_belongs_to_many association
    Many-to-many connection
  • Our job model
  • Our job model
  • Our job model
  • Our updated employer model with the connection to the jobs
  • Create jobs as a nested resource within employers

  • Just like with the Employer controller, create a before filter on the Jobs controller


  • The code for the before_filter
    Put it at the bottom of the controller above the last end

  • Index action to create a job
  • Index view
  • Create a new job as a resource of an Employer
  • This creates a new Job object and sets up the employer_id field to have the id from the specified Employer object in a single operation
  • New view
  • Create action
  • Show the job
  • Show view
  • If we want to edit the job we retrieve the job using the edit action
  • Edit view
  • The update action actually updates the record
  • The destroy action will remove the job from the database
  • Hook the employer and it&#x2019;s jobs together
    Update the show view for employers
    Each employer has it&#x2019;s own jobs collection
  • Now we can see the employer and get to their jobs
  • And we can see the list of jobs for the employer, and CRUD them.
  • Add a simple search form to our index page
  • Simple employer search
    Search form added to employers/index.html.erb
  • Update the index method

  • Keep the search in the box
    Updated search form
    Shows our query in the search box

  • Updated index action
    @query allows us to capture information and use it in a form








  • A-Z Intro To Rails

    1. Hello
    2. Robert Dempsey
    3. adsdevshop.com
    4. adsdevshop.com/apps
    5. rdempsey
    6. A-Z Intro To Ruby on Rails
    7. Always Be Learning
    8. Teach Others
    9. Be Bold
    10. Whatʼs Going On • Introduction to Ruby • Introduction to Rails • Hands-on Lab • Breaks interspersed
    11. Ruby
    12. 1995
    13. 2006
    14. Perl SmallTalk Eiffel Ada + Lisp Ruby
    15. #10 baby!
    16. 5.times { print “We love Ruby” }
    17. class Numeric def plus(x) self.+(x) end end y = 5.plus 6 # y is now equal to 11
    18. Rails
    19. 2005
    20. Image copyright 2008 Yoshiko314 (Flickr)
    21. MVC
    22. Model View Controller
    23. Model View Controller
    24. Model View Controller
    25. Model View Controller
    26. map.root :controller => ʻemployersʼ
    27. 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
    28. Letʼs Build Something
    29. The Project • Employers • Jobs
    30. rails jobby -d postgresql
    31. rails jobby -d mysql
    32. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    33. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    34. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    35. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    36. app/ controllers/ helpers/ models/ views/
    37. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    38. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    39. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    40. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    41. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    42. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    43. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    44. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    45. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    46. README Rakefile app/ config/ db/ doc/ lib/ log/ public/ script/ test/ tmp/ vendor/
    47. development: adapter: postgresql encoding: unicode database: jobby_development pool: 5 username: root password: config/database.yml
    48. development: adapter: mysql encoding: utf8 database: jobby_development pool: 5 username: root password: socket: /tmp/mysql.sock config/database.yml
    49. rake db:create
    50. script/server
    51. rm public/index.html
    52. map.connect ʻ:controller/:action/:idʼ map.connect ʻ:controller/:action/:id.:formatʼ config/routes.rb
    53. script/generate model Employer
    54. script/generate scaffold Employer name:string address:string city:string state:string zipcode:string
    55. 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
    56. 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
    57. 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
    58. rake db:migrate
    59. map.root :controller => ʻemployersʼ config/routes.rb
    60. http://localhost:3000/
    61. class Employer < ActiveRecord::Base end app/models/employer.rb
    62. class Employer < ActiveRecord::Base validates_presence_of :name validates_length_of :city, :minimum => 3 end app/models/employer.rb
    63. http://localhost:3000/employers/new
    64. Controller => CRUD
    65. Model => Logic
    66. script/console
    67. # 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
    68. # 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
    69. # 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
    70. app/views/employers/index.html.erb
    71. <%=h employer.name %> app/views/employers/index.html.erb
    72. <%= link_to 'New employer', ... %> app/views/employers/index.html.erb
    73. edit_employer_path(employer) app/views/employers/index.html.erb
    74. app/views/layouts/employers.html.erb
    75. # 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
    76. app/views/employers/new.html.erb
    77. # 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 => quot;newquot; } format.xml { render :xml => @employer.errors, :status => :unprocessable_entity } end end end app/controllers/employers_controller.rb
    78. # 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
    79. app/views/employers/show.html.erb
    80. # GET /employers/1/edit def edit @employer = Employer.find(params[:id]) end app/controllers/employers_controller.rb
    81. app/views/employers/edit.html.erb
    82. # 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 => quot;editquot; } format.xml { render :xml => @employer.errors, :status => :unprocessable_entity } end end end app/controllers/employers_controller.rb
    83. # 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
    84. Donʼt Repeat Yourself
    85. Partials
    86. _form.html.erb app/views/employers/_form.html.erb
    87. app/views/employers/_form.html.erb
    88. <%= render :partial => 'form' %>
    89. app/views/employers/new.html.erb
    90. app/views/employers/edit.html.erb
    91. <%= render :partial => 'shared/form' %>
    92. @employer = Employer.find(params[:id]) app/controllers/employers_controller.erb
    93. before_filter :find_employer, :only => [:show, :edit, :update, :destroy] app/controllers/employers_controller.rb
    94. app/controllers/employers_controller.rb
    95. private def find_employer @employer = Employer.find(params[:id]) end app/controllers/employers_controller.rb
    96. app/controllers/employers_controller.rb
    97. script/generate scaffold Job name:string description:text
    98. 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
    99. rake db:migrate
    100. belongs_to has_one has_many has_many :through has_one :through has_and_belongs_to_many
    101. 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
    102. 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
    103. 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
    104. 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 patient_id integer has_many :appointments has_many :physicians, :through => :appointments id integer name string
    105. 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
    106. class Job < ActiveRecord::Base end app/models/job.rb
    107. class Job < ActiveRecord::Base belongs_to :employer validates_presence_of :name validates_presence_of :description end app/models/job.rb
    108. class Job < ActiveRecord::Base belongs_to :employer validates_presence_of :name validates_presence_of :description end app/models/job.rb
    109. class Employer < ActiveRecord::Base has_many :jobs validates_presence_of :name validates_length_of :city, :minimum => 3 end app/models/employer.rb
    110. map.resources :employers map.resources :employers, :has_many => :jobs map.resources :jobs app/controllers/employers_controller.rb
    111. before_filter :find_employer app/controllers/jobs_controller.rb
    112. app/controllers/jobs_controller.rb
    113. private def find_employer @employer = Employer.find(params[:employer_id]) end app/controllers/jobs_controller.rb
    114. app/controllers/jobs_controller.rb
    115. # 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
    116. # 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
    117. @job = @employer.jobs.build
    118. app/views/jobs/index.html.erb
    119. # 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 => quot;newquot; } format.xml { render :xml => @job.errors, :status => :unprocessable_entity } end end end app/controllers/jobs_controller.rb
    120. # 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
    121. app/views/jobs/show.html.erb
    122. # GET /jobs/1/edit def edit @job = @employer.jobs.find(params[:id]) end app/controllers/jobs_controller.rb
    123. app/views/jobs/edit.html.erb
    124. # 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 => quot;editquot; } format.xml { render :xml => @job.errors, :status => :unprocessable_entity } end end end app/controllers/jobs_controller.rb
    125. # 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
    126. app/views/employers/show.html.erb
    127. app/views/jobs/index.html.erb
    128. app/views/jobs/index.html.erb
    129. app/views/employers/index.html.erb
    130. app/views/employers/index.html.erb
    131. app/controllers/employers_controller.rb
    132. app/controllers/employers_controller.rb
    133. app/views/employers/index.html.erb
    134. app/views/employers/index.html.erb
    135. app/controllers/jobs_controller.rb
    136. app/controllers/employers_controller.rb
    137. app/views/employers/index.html.erb
    138. Next Steps
    139. DRY up our Job views Add search to our jobs Add a logins for employers Add tags to our jobs
    140. Resources
    141. Rails Guides Agile Web Development (PP) Intro to Ruby 1.9 Cucumber + RSpec
    142. Contest!
    143. Letʼs Chat

    ×