rails workshop for java people (september 2015)
TRANSCRIPT
![Page 1: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/1.jpg)
RUBY ON RAILS
![Page 2: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/2.jpg)
Ruby vs Java
![Page 3: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/3.jpg)
Ruby = Slower
![Page 4: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/4.jpg)
Java = Verbose
![Page 5: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/5.jpg)
Ruby == JavaWhat's the same?
![Page 6: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/6.jpg)
Garbage collected
![Page 7: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/7.jpg)
Strongly typed objects
![Page 8: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/8.jpg)
public, private, and protected
![Page 9: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/9.jpg)
Ruby != JavaWhat's different?
![Page 10: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/10.jpg)
No compilation
![Page 11: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/11.jpg)
begin...end vs {}
![Page 12: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/12.jpg)
require instead of import
![Page 13: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/13.jpg)
Parentheses optional
in method calls
![Page 14: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/14.jpg)
Everything is an object
![Page 15: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/15.jpg)
No types, no casting, no static type checking
![Page 16: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/16.jpg)
Foo.new vs new Foo()
![Page 17: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/17.jpg)
nil == null
![Page 18: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/18.jpg)
under_score vs CamelCase
![Page 19: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/19.jpg)
No method overloading
![Page 20: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/20.jpg)
Mixins vs interfaces
![Page 21: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/21.jpg)
Example time
![Page 22: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/22.jpg)
Classes
![Page 23: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/23.jpg)
class Person attr_accessor :name
def initialize(name) @name = name end
def say(message="default message") puts "#{name}: #{message}" unless message.blank? endend
![Page 24: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/24.jpg)
> andre = Person.new("André")> andre.say("Hello!")=> André: Hello!
![Page 25: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/25.jpg)
Inheritance
![Page 26: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/26.jpg)
class RudePerson < Person def shout(message="default message") say(message.upcase) endend
![Page 27: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/27.jpg)
Mixins
![Page 28: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/28.jpg)
module RudeBehaviour def shout(message="default message") say(message.upcase) endend
class Person include RudeBehaviour # ...end
![Page 29: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/29.jpg)
Readability nazi'sUsually 5+ ways to do the same thing, so it looks nice.
![Page 30: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/30.jpg)
def repeat(message="default message", count=1) # say message count times.end
![Page 31: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/31.jpg)
def repeat(message="default message", count=1) loop do say(message) count -= 1 break if count == 0 endend
![Page 32: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/32.jpg)
def repeat(message="default message", count=1) while(count > 0) say(message) count -= 1 endend
![Page 33: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/33.jpg)
def repeat(message="default message", count=1) until(count == 0) say(message) count -= 1 endend
![Page 34: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/34.jpg)
def repeat(message="default message", count=1) (0...count).each do say(message) endend
![Page 35: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/35.jpg)
def repeat(message="default message", count=1) for index in (0...count) say(message) endend
![Page 36: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/36.jpg)
def repeat(message="default message", count=1) count.times do say(message) endend
![Page 37: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/37.jpg)
Meta-programmingChanging the code on the fly
![Page 38: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/38.jpg)
> Person.new.respond_to?(:shout)=> false> Person.include(RudeBehaviour)=> Person> Person.new.respond_to?(:shout)=> true
![Page 39: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/39.jpg)
# Add the 'shout' method to each object that has a 'say' method.> Object.subclasses.each{ |o| o.include(RudeBehaviour) if o.respond_to?(:say) }
![Page 40: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/40.jpg)
We can manipulate code
![Page 41: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/41.jpg)
class Person ["hello", "goodbye", "howdie"].each do |word| define_method("say_#{word}") do say("#{name}: #{word}") end endend
![Page 42: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/42.jpg)
> Person.new("André").say_hello=> André: hello
![Page 43: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/43.jpg)
Who even needs methods?The power of method_missing
![Page 44: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/44.jpg)
class Person def method_missing(method_name, *arguments) if method_name.starts_with?("say_") # Say everything after 'say_' say(method_name[4..-1]) else super end endend
![Page 45: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/45.jpg)
Your turn
![Page 46: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/46.jpg)
Animal kingdomBuild a Fish, Chicken, and Platypus
![Page 47: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/47.jpg)
4 Each animal makes a noise (blub, tock, gnarl)
4 All animals have health
4 Certain animals have a beak (chicken, platypus, NOT fish)
4 Animals with a beak can peck other animals (health--)
4 Certain animals can lay eggs (fish, chicken, NOT platypus)
![Page 48: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/48.jpg)
module RudeBehaviour def shout(message="default message") say(message.upcase) endend
class Person include RudeBehaviour
attr_accessor :name
def initialize(name) self.name = name end
def say(message="default message") puts "#{name}: #{message}" unless message.blank? endend
![Page 49: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/49.jpg)
class Animal attr_accessor :health
def initialize self.health = 100 end
def make_noise noise puts noise endend
module Beaked def peck(animal) animal.health -= 1 endend
class Egg ; end
module EggLayer def lay_egg Egg.new endend
class Chicken < Animal include Beaked, EggLayer def make_noise super("tock") endend
![Page 50: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/50.jpg)
RailsA web framework
![Page 51: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/51.jpg)
DRY & MVCConvention over configuration
![Page 52: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/52.jpg)
[EXPLAIN MVC GRAPH]
![Page 53: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/53.jpg)
GET http://localhost:3000/people
![Page 54: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/54.jpg)
Routing# config/routes.rbMyApp::Application.routes.draw do get "/people", to: "people#index"end
![Page 55: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/55.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController def index endend
![Page 56: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/56.jpg)
The view# app/views/people/index.html<p>Hello world!</p>
![Page 57: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/57.jpg)
This is a bit plain...Let's add some dynamic data
![Page 58: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/58.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController def index @people = ["André", "Pieter", "Matthijs"] endend
![Page 59: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/59.jpg)
The view (ERB)# app/views/people/index.html.erb<ul><% @people.each do |person| %> <li><%= person %></li><% end %></ul>
![Page 60: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/60.jpg)
The view (SLIM)# app/views/people/index.html.slimul - @people.each do |person| li= person
![Page 61: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/61.jpg)
What about a database?The default is SQLLite
![Page 62: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/62.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Baseend
![Page 63: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/63.jpg)
Migrations# db/migrations/00000000_create_people.rbclass CreatePeople < ActiveRecord::Migration def change create_table :people do |t| t.string :name end endend
rails g migration create_people name:string
![Page 64: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/64.jpg)
Wait!!!?How does it know people belongs to the person model?
![Page 65: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/65.jpg)
Convention over configuration
Tables are plural, models are singular
![Page 66: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/66.jpg)
> rake db:create db:migrate
![Page 67: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/67.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController def index @people = Person.all endend
![Page 68: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/68.jpg)
The view (SLIM)# app/views/people/index.html.slimul - @people.each do |person| li= person.name
![Page 69: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/69.jpg)
Convention over configuration
All columns are mapped to methods
![Page 70: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/70.jpg)
Okay, lets add some people.
![Page 71: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/71.jpg)
> Person.new(name: "André").save> Person.new(name: "Pieter").save> Person.new(name: "Matthijs").save
> Person.count=> 3
![Page 72: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/72.jpg)
Validations> Person.new.save=> true
![Page 73: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/73.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Base validates :name, presence: trueend
![Page 74: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/74.jpg)
Validations> p = Person.new
> p.save=> false
> p.errors.messages=> {:name=>["can't be blank"]}
![Page 75: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/75.jpg)
Let's add a formThis will introduce two new 'actions'
![Page 76: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/76.jpg)
NEW & CREATEthe form, and the creation
![Page 77: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/77.jpg)
Routing# config/routes.rbMyApp::Application.routes.draw do get "/people", to: "people#index" get "/people/new", to: "people#new" post "/people", to: "people#create"end
![Page 78: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/78.jpg)
Routing# config/routes.rbMyApp::Application.routes.draw do resources :people, only: [:index, :new, :create]end
![Page 79: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/79.jpg)
Convention over configuration
index, show, new, edit, create, update, destroy
![Page 80: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/80.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController def index @people = Person.all end
def new @person = Person.new endend
![Page 81: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/81.jpg)
The view (ERB)# app/views/people/new.html.erb<%= form_for @person do |f| %> <div> <%= f.text_field :name %> </div> <div> <%= f.submit "Save" %> </div><% end %>
![Page 82: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/82.jpg)
The view (SLIM)# app/views/people/new.html.slim= form_for @person do |f| div= f.text_field :name div= f.submit "Save"
From now on, we will continue in SLIM, but ERB is just as good.
![Page 83: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/83.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController # def index ... # def new ...
def create @person = Person.new(person_attributes) if @person.save redirect_to action: :index else render :new end end
private
def person_attributes params.require(:person).permit(:name) endend
![Page 84: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/84.jpg)
The view (SLIM)# app/views/people/new.html.slim- @person.errors.full_messages.each do |error| div.red= error
= form_for @person do |f| div= f.text_field :name div= f.submit "Save"
![Page 85: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/85.jpg)
Finally, destroying stuff.
![Page 86: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/86.jpg)
Routing# config/routes.rbMyApp::Application.routes.draw do resources :people, only: [:index, :new, :create, :destroy]end
![Page 87: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/87.jpg)
The view (SLIM)# app/views/people/index.html.slimul - @people.each do |person| li= link_to(person.name, person_path(person), method: :delete)
NOTE: the method is the HTTP method, not the controller method.
![Page 88: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/88.jpg)
Path helpers> rake routesPrefix Verb URI Pattern Controller#Action-------------------------------------------------------------people GET /people people#indexperson GET /people/:id people#shownew_person GET /people/new people#newedit_person GET /people/:id/edit people#edit POST /people people#create PATCH /people/:id people#update DELETE /people/:id people#destroy
![Page 89: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/89.jpg)
The Controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController # def index ... # def new ... # def create ...
def destroy Person.find(params[:id]).destroy redirect_to action: :index endend
![Page 90: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/90.jpg)
Example time
![Page 91: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/91.jpg)
Installing ruby (OSX)> brew install rbenv ruby-build
Then add eval "$(rbenv init -)" to your .profile
> rbenv install 2.2.3
Linux: https://github.com/sstephenson/rbenv
![Page 92: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/92.jpg)
Installing Rails> gem install rails
![Page 93: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/93.jpg)
Making your app> rails new [my_app]
![Page 94: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/94.jpg)
Structure- app - models - views - controllers- config- db- Gemfile / Gemfile.lock
![Page 95: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/95.jpg)
Dependencies# Gemfilegem 'slim-rails'
Add this line to your Gemfile to use slim, then install them:
> bundle install
![Page 96: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/96.jpg)
Running your app> rails s
![Page 97: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/97.jpg)
Build a small app (45 mins)Use the pdf for reference
![Page 98: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/98.jpg)
Your app should:
4 be able to add items
4 be able to edit items
4 be able to destroy items
4 be able to show a single item
4 be able to show a list of items
![Page 99: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/99.jpg)
Next up: relationshas_many, belongs_to, has_one, has_many_through
![Page 100: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/100.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Base validates :name, presence: true has_many :skillsend
# app/models/skill.rbclass Skill < ActiveRecord::Base belongs_to :personend
![Page 101: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/101.jpg)
Migrations# db/migrations/00000000_create_skills.rbclass CreateSkills < ActiveRecord::Migration def change create_table :skills do |t| t.string :name t.references :person end endend
![Page 102: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/102.jpg)
But this binds the skill to a single person...
![Page 103: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/103.jpg)
We need a link tableRails forces you to name it properly!
![Page 104: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/104.jpg)
# app/models/proficiency.rbclass Proficiency < ActiveRecord::Base belongs_to :person belongs_to :skillend
![Page 105: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/105.jpg)
Migrations# db/migrations/00000000_create_proficiencies.rbclass CreateProficiencies < ActiveRecord::Migration def change create_table :proficiencies do |t| t.references :person t.references :skill end endend
![Page 106: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/106.jpg)
Migrations# db/migrations/00000000_remove_person_reference_from_skills.rbclass RemovePersonReferenceFromSkills < ActiveRecord::Migration def change remove_reference :skills, :person endend
![Page 107: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/107.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Base validates :name, presence: true
has_many :proficiencies has_many :skills, through: :proficienciesend
# app/models/skill.rbclass Skill < ActiveRecord::Base has_many :proficiencies has_many :people, through: :proficienciesend
# app/models/proficiency.rbclass Proficiency < ActiveRecord::Base belongs_to :person belongs_to :skillend
![Page 108: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/108.jpg)
> andre = Person.new(name: "André")> andre.skills << Skill.create(name: "Knitting")> andre.save
![Page 109: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/109.jpg)
Update your app (30 mins)Use the pdf for reference
![Page 110: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/110.jpg)
Your app should:
4 have a relationship through a link table
4 have the forms to create/update/destroy the related items (in our example: Skills)
4 should NOT be able to build the relationship using a form (yet).
![Page 111: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/111.jpg)
Building nested formsThough usually it can be prevented by making the link table a first-class citizen.
![Page 112: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/112.jpg)
The view# app/views/people/new.html.slim= form_for @person do |f| div= f.text_field :name = f.fields_for :proficiencies, @person.proficiencies.build do |g| div= g.collection_select :skill_id, Skill.all, :id, :name div= f.submit "Save"
![Page 113: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/113.jpg)
The controller# app/controllers/people_controller.rbclass PeopleController < ApplicationController # def index ... # def new ... # def create ...
private
def person_attributes params.require(:person).permit(:name, proficiencies_attributes: [:skill_id]) endend
![Page 114: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/114.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Base validates :name, presence: true
has_many :proficiencies has_many :skills, through: :proficiencies
accepts_nested_attributes_for :proficienciesend
![Page 115: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/115.jpg)
Update your app (30 mins)Use the pdf for reference
![Page 116: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/116.jpg)
Your app should:
4 should be able to build the relationship using a form.
4 you can pick: nested or first-class
![Page 117: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/117.jpg)
TestingPick your poison: rspec, test-unit,
![Page 118: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/118.jpg)
# test/models/person_test.rbrequire 'test_helper'
class PersonTest < ActiveSupport::TestCase test "Person has a name, that is required" do assert !Person.new.valid? assert Person.new(name: "André").valid? endend
Run your tests
> rake test
![Page 119: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/119.jpg)
# test/integration/people_get_test.rbrequire 'test_helper'
class PeopleGetTest < ActionDispatch::IntegrationTest test "that the index shows a list of people" do # Build three people names = ["André", "Matthijs", "Pieter"] names.each{ |name| Person.create(name: name) }
get people_path assert_response :success
assert_select "li", "André" assert_select "li", "Matthijs" assert_select "li", "Pieter" endend
![Page 120: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/120.jpg)
Update your app (15 mins)Use the pdf for reference
![Page 121: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/121.jpg)
Your app should:
4 Test your validations, and relationships.
4 Test a few basic forms
![Page 122: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/122.jpg)
Building API'sMaking a JSON API for your models
![Page 123: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/123.jpg)
Routing# config/routes.rbMyApp::Application.routes.draw do resources :people namespace :api do resources :people endend
![Page 124: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/124.jpg)
The controller# app/controllers/api/people_controller.rbclass Api::PeopleController < ApplicationController def index render json: Person.all endend
![Page 125: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/125.jpg)
The response[ { id: 1, name: "André" }, { id: 2, name: "Pieter" }, { id: 3, name: "Matthijs" } ]
![Page 126: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/126.jpg)
Adapting the JSONMultiple ways to achieve the same thing.
![Page 127: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/127.jpg)
The model# app/models/person.rbclass Person < ActiveRecord::Base def as_json options={} { name: name } endend
![Page 128: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/128.jpg)
But this changes it everywhere
JSON is also a view
![Page 129: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/129.jpg)
The controller# app/controllers/api/people_controller.rbclass Api::PeopleController < ApplicationController def index @people = Person.all endend
![Page 130: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/130.jpg)
The view# app/views/api/people/index.json.jbuilderjson.array! @people, :name
![Page 131: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/131.jpg)
This means we can even merge both controllers
just drop the jbuilder view in the original views
the view will be selected using the request format
![Page 132: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/132.jpg)
Update your app (45 mins)Use the pdf for reference
![Page 133: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/133.jpg)
Your app should:
4 Have a view JSON api
4 Test the API
![Page 134: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/134.jpg)
Q & ASpecific questions go here
![Page 135: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/135.jpg)
EXTRA: Update your app (60 mins)
Use the pdf for reference
![Page 136: Rails workshop for Java people (September 2015)](https://reader031.vdocuments.us/reader031/viewer/2022030312/58ee4e7c1a28ab08738b456d/html5/thumbnails/136.jpg)
Your app should:
4 Do something you want it too
4 We will help.