Ruby on Rails 101

Post on 20-Aug-2015

2.074 views 1 download

Transcript of Ruby on Rails 101

1.9.2

3.0.5

RubyonRails 101

@claytonlz - Desert Code Camp 2011.1 - http://spkr8.com/t/7007

Saturday, April 2, 2011

EcosystemModelsControllersViewsDeploying & OptimizingResources for Learning

Saturday, April 2, 2011

Community

Saturday, April 2, 2011

“This sure is a nice fork, I bet I could… HOLY

SHIT A KNIFE!”

Saturday, April 2, 2011

Opinionated

Saturday, April 2, 2011

“I flippin’ told you MVCis the only way to buildweb apps! Teach you to

doubt DHH!”

Saturday, April 2, 2011

Rapid Development

Saturday, April 2, 2011

“These goats are okay, but I really need a yak

for some quality shaving”

Saturday, April 2, 2011

EcosystemModelsControllersViewsDeployingResources for Learning

Saturday, April 2, 2011

Models

AssociationsValidationsCallbacksQuerying

Saturday, April 2, 2011

Models

ActiveRecord::Baseclass Product < ActiveRecord::Base ...end

productsproductsname string

sku string

price decimal

Saturday, April 2, 2011

Models ➤ Associations# manufacturerhas_many :products

# producthas_one :upcbelongs_to :manufacturerhas_many :batcheshas_many :ingredients, :through => :batches

# batchbelongs_to :productbelongs_to :ingredient

# ingredienthas_many :batcheshas_many :products, :through => :batches

products

manufacturersupcs

batches

ingredients

Saturday, April 2, 2011

Models ➤ Associations

# create a product and find its manufacturerproduct = manufacturer.products.create({:name => "Kitlifter"})product.manufacturer

# create a upc and find its product's manufacturerupc = product.create_upc({:code => "001122"})upc.product.manufacturer

# create a batch (linking a product and ingredient)wheat = Ingredient.create({:name => "Wheat"})bread = Product.create({:name => "Bread"})

batch.create({:product => bread, :ingredient => wheat})

Saturday, April 2, 2011

Models ➤ Associations

“Using has_many or belongs_to is more than just on which table the foreign key is placed,

itʼs a matter of who can be thought of as ʻowningʼ the other. A product ʻownsʼ a UPC.”

When should I use has_oneand belongs_to?

Saturday, April 2, 2011

Models ➤ Validations

class Product < ActiveRecord::Base validates_presence_of :name validates_uniqueness_of :name validates_format_of :sku, :with => /^SKU\d{8}$/ validates_inclusion_of :usda_rating, :in => %w( prime choice ) validate :cannot_be_active_if_recalled def cannot_be_active_if_recalled if recalled? && recalled_on < Date.today errors.add(:active, "Can't be active if it's been recalled") endend

Saturday, April 2, 2011

Models ➤ Validations

“It is possible to save a record, without validating, by using save(:validate => false)”

I know my record istechnically invalid, butI want to save it anyhow.

Saturday, April 2, 2011

Models ➤ Callbacks

class Ingredient before_destroy :determine_destroyability before_create :format_legacy_name after_update :log_changes after_create :import_harvest_data # validation # create # save # update # destroy end

Callback Chain

STOP!!

determine_destroyability

Saturday, April 2, 2011

Models ➤ Querying

Product.find(98)Product.find_by_name("Diet Coke")Product.find_by_name_and_sku("Diet Coke", "SKU44387")Product.find([98,11,39])Product.firstProduct.lastProduct.allProduct.count

# old and bustedProduct.find(:all, :conditions => {:name => "Cheese-it!"})

# new hotnessProduct.where(:name => "Cheese-it!").all

Saturday, April 2, 2011

Models ➤ QueryingProduct.where("name = ?", 'Skittles')Product.where(:created_at => Date.yesterday..Date.today)Product.where(:sku => ["SKU912", "SKU187", "SKU577"])

Product.order('name DESC')

Product.select('id, name')

Product.limit(5)

# chainableProduct.where(:created_at => Date.yesterday..Date.today) .limit(10) Product.order('created_at ASC').limit(20).offset(40)

Product.select('created_at').where(:name => 'Twix')

Saturday, April 2, 2011

Models ➤ Queryingmanufacturer.includes(:products) .where('products.usda_rating = ?', 'prime')

manufacturer.includes(:products) .where(:state => 'AZ') .order('created_at') manufacturer.includes(:products => :ingredients) .where('ingredients.name = ?', 'glucose') .order('updated_at') manufacturer.joins(:products) .where('products.sku = ?', 'SKU456') ingredient.includes(:products => {:manufacturer => :conglomerate}) .where('conglomerates.name = ?', 'nestle') animalia.includes(:phylum => {:class => {:order => {:family => :genus}}})

child.includes(:parent => [:brother, {:sister => :children}])

Saturday, April 2, 2011

Models ➤ Validations

“Using includes will load the records into memory when the query

is executing, joins will not.”

Why would I use joinsinstead of includes?

Saturday, April 2, 2011

Controllers

RoutingFiltersConventions

Saturday, April 2, 2011

Controllers ➤ Routingresources :products# GET /products => index action# GET /products/new => new action# GET /products/:id => show action# GET /products/:id/edit => edit action## POST /products => create action# # PUT /products/:id => update action## DELETE /products/:id => destroy action

products_path # /productsproducts_url # http://www.example.com/products

product_path(@product) # /products/29product_path(@product, :xml) # /products/29.xml

Saturday, April 2, 2011

Controllers ➤ Routing

namespace :admin do resources :users resources :ordersend

admin_users_path # /admin/usersedit_admin_order_path # /admin/orders/4/edit

class Admin::UsersController < ApplicationController # /app/controllers/admin/users_controller.rb # /app/views/admin/users/end

Saturday, April 2, 2011

Controllers ➤ Routingresources :accounts, :except => :destroy do resources :users do post :activate, :on => :member collection do get 'newest' end end resources :clients, :only => [:index, :show]end

account_users_path(@account) # /accounts/182/usersnewest_account_users_path(@account) # /accounts/182/users/newestactivate_account_user_path(@account, @user) # /accounts/182/user/941

accounts_clients_path(@account) # /accounts/182/clientsnew_accounts_client_path(@account) # FAIL!

Saturday, April 2, 2011

Controllers ➤ Filters

class UsersController < ApplicationController before_filter :load_manufacturer before_filter :find_geo_data, :only => [:show] skip_before_filter :require_login after_filter :log_accessend

# in ApplicationControllerdef log_access Rails.logger.info("[Access Log] Users Controller access at #{Time.now}")end

Saturday, April 2, 2011

Controllers ➤ Conventionsclass ProductsController < ApplicationController def index # GET /products end def show # GET /products/:id end def new # GET /products/new end def create # POST /products end def edit # GET /products/:id/edit end def update # PUT /products/:id end def destroy # DELETE /products/:id endend

def update # ... update occurred @parent.children.each ...end

def edit @product = Product.find(params[:id])end

def show @product = Product.find(params[:id])end

def destroy @product = Product.find(params[:id])end

before_filter :load_product

Saturday, April 2, 2011

Controllers ➤ Conventionsclass ProductsController < ApplicationController def index # GET /products end def show # GET /products/:id # renders /app/views/products/show.format end def new # GET /products/new end def create # POST /products redirect_to products_url end def edit # GET /products/:id/edit end def update # PUT /products/:id end def destroy # DELETE /products/:id endend

def update # ... update occurred @parent.children.each ...end

def edit @product = Product.find(params[:id])end

def show @product = Product.find(params[:id])end

def destroy @product = Product.find(params[:id])end

before_filter :load_product

Saturday, April 2, 2011

Views

Layouts & HelpersFormsPartialsActionView Helpers

Saturday, April 2, 2011

Views ➤ Layouts & Helpers

<!-- app/views/products/show.html.erb --><h2><%= @product.name %></h2><p>Price: <%= @product.price %></p>

<!-- app/layouts/application.html.erb --><div id="container"> <%= yield %></div>

<div id="container"> <h2>Pop-Tarts</h2> <p>Price: $3.99</p></div>

def show @product = Product.find(params[:id])end M C

V

Saturday, April 2, 2011

Views ➤ Layouts & Helpers<h2><%= @product.name %></h2><p>Price: <%= number_to_currency(@product.price) %></p><p>Ingredients: <%= @product.ingredients.present? ? @product.ingredients.map(&:name).join(',') : 'N/A' %></p>

# app/helpers/products_helper.rbdef display_ingredients(ingredients) return "N/A" if ingredients.blank? ingredients.map(&:name).join(',')end

<h2><%= @product.name %></h2><p>Price: <%= number_to_currency(@product.price) %></p><p>Ingredients: <%= display_ingredients(@product.ingredients) %></p>

Saturday, April 2, 2011

Views ➤ Forms

<%= form_tag search_path do %> <p> <%= text_field_tag 'q' %><br /> <%= submit_tag('Search') %> </p><% end %>

<form action="/search" method="post"> <p> <input type="text" name="q" value="" id="q" /> <input type="submit" name="commit_search" value="Search" id="commit_search" /> </p></form>

Saturday, April 2, 2011

Views ➤ Forms<h2>New Product</h2><%= form_for(@product) do |f| %> <!-- action => /products/:id --> <!-- method => POST --> <p> <%= f.text_field :name %> </p> <p> <%= f.check_box :active %> </p><% end %>

<h2>Edit Product</h2><%= form_for(@product) do |f| %> <!-- action => /products/:id --> <!-- method => PUT --> <p> <%= f.text_field :name %> </p> <p> <%= f.check_box :active %> </p><% end %>

← New Record

Existing Record →

Saturday, April 2, 2011

Views ➤ Forms

<%= f.hidden_field :secret %><%= f.password_field :password %><%= f.label :name, "Product Name" %><%= f.radio_button :style, 'Clear' %><%= f.text_area, :description %><%= f.select :condition, ["Good", "Fair", "Bad"] %>

<%= f.email_field :user_email %><%= f.telephone_field :cell_number %>

Saturday, April 2, 2011

Views ➤ Partials

<% @products.each do |product| %> <tr><td><%= link_to(product.title, product_path(product)) %></td></tr><% end %>

<% @products.each do |product| %> <%= render :partial => 'product_row', :locals => {:product => product} %><% end %>

<!-- app/views/products/_product_row.html.erb --><tr><td><%= link_to(product.title, product_path(product)) %></td></tr>

<%= render :partial => 'product_row', :collection => @products, :as => :product %>

Saturday, April 2, 2011

Views ➤ Partials

<!-- app/views/shared/_recent_changes.html.erb --><ul> <li>...</li> <li>...</li></ul>

<!-- app/views/reports/index.html.erb --><%= render :partial => 'shared/recent_changes' %>

<!-- app/views/pages/news.html.erb --><%= render :partial => 'shared/recent_changes' %>

<%= render :partial => @product %><%= render(@product) %>

<%= render 'bio', :person => @john %>

Saturday, April 2, 2011

Views ➤ Partials

NumberHelperTextHelperFormHelperJavaScriptHelperDateHelperUrlHelperCaptureHelperSanitizeHelper

Saturday, April 2, 2011

Deploying & Optimizing

Heroku

NewRelicPassenger

Saturday, April 2, 2011

Resources for Learning

Video

PeepCode

RailsCasts

CodeSchool

Books

The Rails Way

Beginning Ruby

Ruby for _________Other

PHX Rails User Group

Gangplank

Saturday, April 2, 2011

@claytonlzhttp://spkr8.com/t/7007

Saturday, April 2, 2011