96
Rails Tutorial

OSDC 2009 Rails Turtorial

Embed Size (px)

Citation preview

Page 1: OSDC 2009 Rails Turtorial

Rails Tutorial

Page 2: OSDC 2009 Rails Turtorial

自我介紹

http://blog.xdite.net

低調部落客

http://handlino.com

Rails Developer

Page 3: OSDC 2009 Rails Turtorial

bingo.handlino.com

sudomake.com

VeryXD.net

Project Using Rails

Page 4: OSDC 2009 Rails Turtorial

VeryXD.net

Project Using Sinatra

MrIE6.com

Page 5: OSDC 2009 Rails Turtorial

DRYDon’t Repeat Yourself

Page 6: OSDC 2009 Rails Turtorial

Agenda

• ActiveRecord

• Template / Helper

• Library

• Plugin

Page 7: OSDC 2009 Rails Turtorial

Agenda

• ActiveRecord

• Template / Helper

• Library

• Plugin

少寫更多的 Code

Page 8: OSDC 2009 Rails Turtorial

MVCModel - View - Controller

Page 9: OSDC 2009 Rails Turtorial

MVCModel-View-Controller

route.rbHTTP requestGET /users/1

Browser

UsersController

end

def show@user = User.find(params[:id])

respond_to do |format|format.htmlformat.xml

endend

def index......

end

Model

Database

#show.html.erb

<html> <h1>User Profile</h1> <p><%= @user.nickname %></p></html>

View

決定哪一個 Controller 和 Action

Page 10: OSDC 2009 Rails Turtorial

C > M現實

Page 11: OSDC 2009 Rails Turtorial

C > M現實

大家都愛把 Code 塞進 Controller

Page 12: OSDC 2009 Rails Turtorial

Refactor to ModelActiveRecord 內建 feature

Page 13: OSDC 2009 Rails Turtorial

ActiveRecord• validation

• callback

• counter_cache

• named_scope

• STI

• polymorphic association

Page 14: OSDC 2009 Rails Turtorial

validation

Page 15: OSDC 2009 Rails Turtorial

validation

class Post < ActiveRecord::Base validates_presence_of :subject end

Page 16: OSDC 2009 Rails Turtorial

validation

class Post < ActiveRecord::Base validates_presence_of :subject end

Page 17: OSDC 2009 Rails Turtorial

validation

Page 18: OSDC 2009 Rails Turtorial

validation

validates_exclusion_of :age, :in => 30..60

validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create

validates_inclusion_of :format, :in => %w( jpg gif png )

validates_length_of :phone, :in => 7..32, :allow_blank => true

validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id]

Page 19: OSDC 2009 Rails Turtorial

Callbacks

def create @post = Post.new(params[:post]) @post.content += " < #{Time.now.to_s} >" if @post.save flash[:notice] = 'Post was successfully created.' redirect_to blog_path(@post) else render :action => "new" end end

直覺想法

Page 20: OSDC 2009 Rails Turtorial

Callbacks

class Post < ActiveRecord::Base

before_create :insert_timestamp def insert_timestamp self.content += " < #{Time.now.to_s} >" end

end

應該使用 before_create

Page 21: OSDC 2009 Rails Turtorial

Callbacks

before_validationbefore_validation_on_createafter_validatinafter_validation_on_createbefore_savebefore_create

after_createafter_save

insert update

before_validationbefore_validation_on_updateafter_validatinafter_validation_on_upatebefore_savebefore_update

after_updateafter_save

before_destroy

after_destroy

delete

DestroyCreate Update

Page 22: OSDC 2009 Rails Turtorial

Counter Cache

計算文章留言數

Page 23: OSDC 2009 Rails Turtorial

Counter Cache

class Comment < ActiveRecord::Base belongs_to :post def after_save self.update_counter_cache end def after_destroy self.update_counter_cache end def update_conter_cache self.post.comments_count = self.post.comments.size slf.post.save(false) endend

直覺想法

Page 24: OSDC 2009 Rails Turtorial

class PostCommentsCount < ActiveRecord::Migration def self.up add_column :posts, :comments_count, :integer , :default => 0 end

def self.down remove_column :posts,:comments_count endend

Counter Cacheclass Comment < ActiveRecord::Base belongs_to :post, :counter_cache => trueend

自動解決

Page 25: OSDC 2009 Rails Turtorial

Named Scope

Post.publish=> SELECT * FROM `posts` WHERE (`posts`.`is_blocked` = 0)

Post.recent=> SELECT * FROM `posts` ORDER BY created_at DESC LIMIT 1

Post.publish.recent=> SELECT * FROM `posts` WHERE (`posts`.`is_blocked` = 0) ORDER BY created_at DESC LIMIT 1

class Post < ActiveRecord::Base named_scope :publish, :conditions => { :is_blocked => false } named_scope :recent, :order => "created_at DESC", :limit => 1end

v.2.1 起

Page 26: OSDC 2009 Rails Turtorial

STI (Single Table Inheritance )

class Post < ActiveRecord::Base has_many :comments before_create :insert_timestamp def insert_timestamp self.content += " < #{Time.now.to_s} >" end named_scope :publish, :conditions => { :is_blocked => false } named_scope :recent, :order => "created_at DESC", :limit => 1 end

class Article < Postend

Page 27: OSDC 2009 Rails Turtorial

Polymorphic Association

• Post has_many comments

• Photo has_many comments

• News has_many comments

post_comment

photo_comment

news_comment

直覺想法

需要這麼多張 Table 嗎?

Page 28: OSDC 2009 Rails Turtorial

Polymorphic Associationclass Post < ActiveRecord::Base has_many :comments, :as => :resourceend

class Comment < ActiveRecord::Base belongs_to :resource, :polymorphic => trueend

class PolymorphicComment < ActiveRecord::Migration def self.up remove_column :comments, :post_id add_column :comments, :resource_id, :integer add_column :comments, :resource_type, :string end

def self.down add_column :comments, :post_id, :integer remove_column :comments, :resource_id remove_column :comments, :resource_type endend

Page 29: OSDC 2009 Rails Turtorial

Polymorphic Association

Page 30: OSDC 2009 Rails Turtorial

MVCModel - View - Controller

Page 31: OSDC 2009 Rails Turtorial

V > C現實

Page 32: OSDC 2009 Rails Turtorial

V > C現實

大家都愛把 Code 寫在 View 裡 ....

Page 33: OSDC 2009 Rails Turtorial

Less code in viewRender Template & Use Helper

Page 34: OSDC 2009 Rails Turtorial

View 裡面的髒 code

Page 35: OSDC 2009 Rails Turtorial

Render Template

用 partial 包起來

Page 36: OSDC 2009 Rails Turtorial

Render Template

用 partial 包起來

Page 37: OSDC 2009 Rails Turtorial
Page 38: OSDC 2009 Rails Turtorial
Page 39: OSDC 2009 Rails Turtorial

Write Your Own Helper

自動生 <td> <tr>

Page 40: OSDC 2009 Rails Turtorial

Write Your Own Helper

Page 41: OSDC 2009 Rails Turtorial
Page 42: OSDC 2009 Rails Turtorial
Page 43: OSDC 2009 Rails Turtorial

Don’t re-invent the wheeluse the library ( lib/ ), gems

Page 44: OSDC 2009 Rails Turtorial

Yahoo Open Hack Day 佳作

1日開發 HTML +CSS (not flash)和多出品

Page 45: OSDC 2009 Rails Turtorial

lib/

rubygems

Page 46: OSDC 2009 Rails Turtorial

lib/

Page 47: OSDC 2009 Rails Turtorial

7326 gems

Page 48: OSDC 2009 Rails Turtorial

數不清的 gems

Page 49: OSDC 2009 Rails Turtorial

Rapid Web Developmentvendor/plugin

Page 50: OSDC 2009 Rails Turtorial

1. 認證篇authentication

Page 51: OSDC 2009 Rails Turtorial

restful-authentication

• 使用者註冊/登入/登出

• User model

• RESTful Session controller

• Activation mailer

./script/generate authenticated user sessions --include-activation

不需要自己撰寫認證系統

Page 52: OSDC 2009 Rails Turtorial

open_id_authentication

• 支援 OpenID 登入

• openid session controller

• openid migration

Page 53: OSDC 2009 Rails Turtorial

openid_pack

• restful_authentication + open_id_authentication同時支援用戶註冊或使用 OpenID ( multiple )

• 和多出品

Page 54: OSDC 2009 Rails Turtorial

2. Model 篇ActiveRecord

Page 55: OSDC 2009 Rails Turtorial

attachment_fu

• 將 model 當做一個檔案附件

• File system / amazon S3 / Database store

has_attachment :storage => :file_system, :path_prefix => 'public/files', :content_type => :image, :resize_to => [50,50]

Page 56: OSDC 2009 Rails Turtorial

restful_authenication

attachment_fu

Page 57: OSDC 2009 Rails Turtorial

acts_as_taggable_on_steroids

class Post < ActiveRecord::Base acts_as_taggable end

p = Post.find(:first) p.tag_list # [] p.tag_list = "Funny, Silly" p.save p.tag_list # ["Funny", "Silly"]

p.tag_list.add("Great", "Awful") p.tag_list.remove("Funny")

• 裝作有標籤 tagging 功能

Page 58: OSDC 2009 Rails Turtorial

標籤雲

Page 59: OSDC 2009 Rails Turtorial

validates_url_of

• 加上 http:// 如果資料缺少 http:// 或 https://

• 使用正規表示法檢查格式• 和多出品

class Foo < ActiveRecord::Base validates_url_of :url, :message => 'is not valid or not responding'.tend

Page 60: OSDC 2009 Rails Turtorial

3. Controller&View 篇ActionPack

Page 61: OSDC 2009 Rails Turtorial

will_paginate

@posts = Post.paginate :page => params[:page], :per_page => 50

<ol> <% for post in @posts -%> <li>Render `post` in some nice way.</li> <% end -%> </ol>

<%= will_paginate @posts %>

• 分頁必備,包含 HTML helper 及 CSS style

分頁功能

Page 62: OSDC 2009 Rails Turtorial

will_paginate (cont.)• 附贈 named_scope,如果你還沒升級到 Rails 2.1

class Product < ActiveRecord::Base

named_scope :cheap, :conditions => { :price => 0..5 } named_scope :recent, lambda { |*args| {:conditions => ["released_at > ?", (args.first || 2.weeks.ago)]} } named_scope :visible, :include => :category, :conditions => { 'categories.hidden' => false } end

@products = Product.recent.cheap.paginate :page => params[:page], :per_page => 50

• 人人都愛的串接寫法

Page 63: OSDC 2009 Rails Turtorial

jRails• 我們都愛 jQuery

gugod hlbbyebye! Prototype.js

Page 64: OSDC 2009 Rails Turtorial

facebox_render• Facebox is a JQuery-based lightbox

http://famspam.com/facebox/

Page 65: OSDC 2009 Rails Turtorial

facebox_render (cont.)

Text

class ApplicationController < ActionController::Base include FaceboxRenderend

• 無縫銜接 facebox,和多出品

Page 66: OSDC 2009 Rails Turtorial

facebox_render (cont.)

Text

class ApplicationController < ActionController::Base include FaceboxRenderend

<%= facebox_link_to "Login", :url => new_session_url %>

• 無縫銜接 facebox,和多出品

Page 67: OSDC 2009 Rails Turtorial

facebox_render (cont.)

Text

class ApplicationController < ActionController::Base include FaceboxRenderend

<%= facebox_link_to "Login", :url => new_session_url %>

• 無縫銜接 facebox,和多出品

Page 68: OSDC 2009 Rails Turtorial

facebox_render (cont.)

Text

class ApplicationController < ActionController::Base include FaceboxRenderend

<%= facebox_link_to "Login", :url => new_session_url %>

def new # do some thing you want respond_to do |format| format.html format.js { render_facebox } endend

• 無縫銜接 facebox,和多出品

Page 69: OSDC 2009 Rails Turtorial

facebox_render (cont.)

Text

class ApplicationController < ActionController::Base include FaceboxRenderend

<%= facebox_link_to "Login", :url => new_session_url %>

def new # do some thing you want respond_to do |format| format.html format.js { render_facebox } endend

• 無縫銜接 facebox,和多出品

Page 70: OSDC 2009 Rails Turtorial

Ajax form submit

Page 71: OSDC 2009 Rails Turtorial

Ajax form submit

Page 72: OSDC 2009 Rails Turtorial

<% form_remote_tag :url => batch_event_attendees_path(@event) do %>

Ajax form submit

Page 73: OSDC 2009 Rails Turtorial

def batch ... respond_to do |format| format.html format.js { render_to_facebox } endend

Text

Page 74: OSDC 2009 Rails Turtorial

def batch ... respond_to do |format| format.html format.js { render_to_facebox } endend

Text

Page 75: OSDC 2009 Rails Turtorial

def batch ... respond_to do |format| format.html format.js { render_to_facebox } endend

batch.html.erb

Text

Page 76: OSDC 2009 Rails Turtorial

def batch ... respond_to do |format| format.html format.js { render_to_facebox } endend

batch.html.erb

Text

Page 77: OSDC 2009 Rails Turtorial

stickies• 強化版的 flash[:notice] 提示訊息

• 四種不同種類的訊息提示,包含 CSS style 及 Javascript close按鈕。

error_stickie("Your account has been disabled") warning_stickie("Your account will expire in 3 days") notice_stickie("Account activated") debug_stickie("This only works when RAILS_ENV is development")

<%= render_stickies %>

Page 78: OSDC 2009 Rails Turtorial

4. 上線篇deployment

Page 79: OSDC 2009 Rails Turtorial

ar_mailer• 當有很多 E-mail 要發送的時候,需要非同步的 E-mail 發送

Class EventNotifier < ActionMailer::ARMailer

def signup_notification(user) ... end

end

UserNotifier.deliver_signup_notification(@user)

Database ar_sendmail daemon

Page 80: OSDC 2009 Rails Turtorial

hoptoad

• 記錄 exception 例外時(500 error)

• 包含當時的 log 記錄

Page 81: OSDC 2009 Rails Turtorial

New Relic• profiling your rails app

• trace code stack

• provide optimize direction

Page 82: OSDC 2009 Rails Turtorial

Capistrano自動化 deploy 步驟1. ssh to production server

2. svn checkout 3. run some your script (link file/copy config file/ clear cache…etc)4. restart mongrel cluster

Page 83: OSDC 2009 Rails Turtorial

plugin 哪裡找?

Page 84: OSDC 2009 Rails Turtorial

thank you.

Page 85: OSDC 2009 Rails Turtorial

Bonus

Page 86: OSDC 2009 Rails Turtorial

I18nless pain( Rails 2.2 )

Page 87: OSDC 2009 Rails Turtorial
Page 88: OSDC 2009 Rails Turtorial

使用 session 切換

yml 管理

Page 89: OSDC 2009 Rails Turtorial

Template & EngineUltima lazy solution ( Rails 2.3)

Page 90: OSDC 2009 Rails Turtorial

Template

• 開發者會不斷的進行新專案• 每次依需求安裝不等數量的 gem / plugin

• 每次依需求撰寫不同的 route / rake

• ...開始維護自己的架站包?

• ......還是要 by case 修改架站包

• ..........苦悶 =_=

Page 91: OSDC 2009 Rails Turtorial

Templates

• (restful / openid / twitter) _authenication

• Facebook

• Google App Engine

Page 92: OSDC 2009 Rails Turtorial

Engine

• 開發者會不斷的進行新專案• MVC 架構可以抄襲以前的 code

• ...每次還是從自己的架站包 copy

• ......還是要 by case 修改架站包

• ..........苦悶 =_=

Page 93: OSDC 2009 Rails Turtorial

推書籤到 Twitter

也是我寫的 XD

Page 94: OSDC 2009 Rails Turtorial

推書籤到 Twitter

也是我寫的 XD

Page 95: OSDC 2009 Rails Turtorial

• 把 Application 當做一個 Plugin

• 不需另外撰寫code整合原有程式

• Load 了就上

• 有效利用舊 code

Engine plugin

Page 96: OSDC 2009 Rails Turtorial

thanks again.

http://blog.xdite.net

http://twitter.com/xdite