10 reasons why i love ruby on rails
TRANSCRIPT
10 reasons why I love Ruby on Rails
Surasit Liangpornrattanaa.k.a. PunNeng
Ruby on Rails
rubyonrails.org an open-source web framework that's
optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration
David Heinemeier Hansson - DHH
1. Ruby
ruby-lang.org Yukihiro “matz” Matsumoto Matz wrote “Treating code as an essay” in
“Beautiful code” Easy to read/understand Increase productivity
RubyGems
Treating code as an essay
Rubyputs "Hello World"
Javaclass MyJavaProg{ public static void main(String args[]){ System.out.println("Hello World"); }}
2. Philosophy and Design
Convention over Configuration(CoC) Don't repeat yourself(DRY)
Convention over Configuration
Table name users
Model user.rb class User < ActiveRecord::Base; end
Restful controller users_controller.rb class UsersController < ApplicationController; end
View app/views/users/*.html.erb
DRY – Don't repeat yourself
Controllerclass UsersController < ApplicationController def create logger.info "Before create" # ... end def update logger.info "Before update" # ... endend
DRY – Don't repeat yourself
before_filter :show_log, :only => [ :create, :update]
def create # ... end def update # ... end protected def show_log logger.info "Before #{params[:action]}" end
DRY – Don't repeat yourself
Model - Callbacks before_create after_create before_save before_save etc. API
3. MVC
M – Model ActiveRecord
V – View ActionView
C – Controller ActionController
Controller
# app/controllers/users_controller.rbclass UsersController < ApplicationController def index @users = User.find :all end
def new @user = User.new end
def create @user = User.new params[:user] if @user.save redirect_to :action => "index" else render :action =>"new" end endend
View
# app/views/users/index.html.erb<h2>User list</h2><%= @users.each do |user| %> <p>Name: <%= user.name %></p> <p>Age: <%= user.age %></p> <hr /><% end %>
# partial rendering<h2>User list</h2><%= render :partial "user_list", :collection => @users
# app/views/users/_user_list.html.erb<%= collection.each do |user| %> <p>Name: <%= user.name %></p> <p>Age: <%= user.age %></p> <hr /><% end %>
4. ActiveRecord
user = User.new :name => "Neng", :age => 25user.save #=> true
User.find 1neng = User.find_by_name "Neng"# SELECT * FROM `users` WHERE (`name` = 'Neng') LIMIT 1neng.age #=> 25
ActiveRecord::Migration
# db/migrate/001_create_users.rbclass CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :name, :null => false t.integer :age, :status end
User.create :name => "Neng", :age => 25 end
def self.down drop_table :users endend
ActiveRecord::Validations
# app/models/user.rbclass User < ActiveRecord::Base validates_presence_of :name validates_uniqueness_of :name validates_length_of :name, :in => 5..30end
user = User.newuser.save #=> falseuser.errors.full_messages #=> ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
ActiveRecord::Callbacks
# app/models/user.rbclass User < ActiveRecord::Base validates_presence_of :name validates_length_of :name, :in => 5..30
before_save :set_status
def set_status status = 1 endend
user = User.new :name => "Neng"user.save #=> falseuser.status #=> 1user.set_status #=> 1
5. Ajax helpers
# It is PrototypeJS!!# Generates: <a href="#" onclick="new# Ajax.Updater({success:'posts',failure:'error'}, '/blog/destroy/5',# {asynchronous:true, evalScripts:true}); return false;">Delete this post</a> link_to_remote "Delete this post", :url => { :action => "destroy", :id => post.id }, :update => { :success => "posts", :failure => "error" }
# Generates:# <form action="/" method="post" onsubmit="new Ajax.Request('/',# {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});# return false;"><div><input name="commit" type="submit"value="Save" /></div># </form> <% form_remote_tag :url => '/posts' do -%> <div><%= submit_tag 'Save' %></div> <% end -%>
Ajax helpers
# Generates: new # Form.Element.Observer('suggest', 0.25, function(element, value) {new# Ajax.Updater('suggest',# '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q='# + value})}) <%= observe_field :suggest, :url => { :action => :find_suggestion }, :frequency => 0.25, :update => :suggest, :with => 'q' %>
# Generates:# new PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update',# {asynchronous:true, evalScripts:true})}, 20) periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
Ajax helpers
# app/controllers/users_controller.rbclass UsersController < ApplicationController def index @users = User.find :all # request.xhr? respond_to do |format| format.html format.js do # render :text => "replaced message" # or RJS render :update do |page| page.insert_html :bottom, 'list', "<li>#{@users.last.name}</li>" page.visual_effect :highlight, 'list' page.hide 'status-indicator', 'cancel-link' end end end endend
6. Restful
REST - Representational state transfer Style of software architecture for distributed
hypermedia systems such as the World Wide Web
Roy Fielding - One of the principal authors of HTTP specification
Outline how resources are defined and addressed
Web services Main feature in Rails 2.0
7. Cool plugins
HAML ActiveScaffold MakeResourceful File column/Upload column Restful authentication Acts as tree, versioned, etc.
8. Capistrano
capify.org Automated Deployment System Version control system – svn / git $ svn commit / $ git push $ cap deploy
$ svn commit / git push
PCReposvn/git
Host
Upload every changes to git/svn repo
$ cap deploy
PCReposvn/git
Host
Upload every changes to git/svn repo
Remote to host and run $ svn update / git pull
$ cap deploy
PCReposvn/git
Host
Upload every changes to git/svn repo
Remote to host and run $ svn update / git pull
$ svn update / git pull
9. RSpec
rspec.info Behavior Driven Development – BDD Story framework Spec framework
BDD
Encourages collaboration between developers, QA and non-technical or business participants in a software project
Test First
10. FREE !!
Open Source
Q & A
Bye