What's new in Rails 2?
-
date post
12-Sep-2014 -
Category
Business
-
view
30.144 -
download
3
description
Transcript of What's new in Rails 2?
“Look at all the things I’m NOT
doing.”–DHH during the “Creating a blog
in 15 minutes” screencast
Evolutionary, not revolutionary.
ActiveRecord
Numerical validation
•Gains the ability to specify comparisons.
•Examples:validates_numericality_of :salary, :greater_than => 49_000
validates_numericality_of :age, :less_than_or_equal => 99
validates_numericality_of :employees, :greater_than => 0
:allow_blank => true
Skips validation for empty strings and nil.
XML in, JSON out>> Post.new.from_xml({:title => "Hello!", :body => "text"}.to_xml)
=> #<Post id: nil, title: "Hello!", body: "text", created_at: nil, updated_at: nil>
>> Post.new(:title => "Hello!", :body => "text").to_json
=> "{"updated_at": null, "title": "Hello!", "body": "text", "created_at": null}"
Sexy migrations
create_table :posts do |t|
t.belongs_to :blog, :null => false
t.string :title, :subtitle
t.text :body
t.timestamps
end
Query cache•Very dumb. Checks SQL string
equality.
•Cleared by any INSERT/UPDATE/DELETE.
•Enabled per-action by default.
•Can be skipped if necessary:def self.uncached_newest uncached do find(:all, :order => :created_at) endend
Foxy Fixtures
Three main features
•Don’t specify the IDs for each record.
•Reference associated fixtures by name.
•Sets created_at and updated_at to Time.now automatically.
Foxy Fixtures example
# blogs.ymlmy_blog: name: "My awesome blog"
# posts.ymlfirst_post: blog: my_blog title: "First post!"
fixtures :allLoad all fixtures for all test cases.
(Recommended!)
ActionPack
Cookie sessions•Now the default session store.
•Stored in clear text, secured with a hash.
•Configure a secret in environment.rb:
Rails::Initializer.run do |config| config.action_controller.session = { :session_key => '_rails_app_session', :secret => 'e96a9......aef9111a' }end
HTTP-only cookiesPrevents access to cookies from JavaScript.
CSRF protection
•Enabled by default in application.rb
•Uses a token to verify requests are from the application, not a malicious site.
•Built-in to form_tag and friends.
Partial layoutsUse with partials:<% render :partial => "post", :layout => "window" %>
or with a block:<% render :layout => "window", :locals => { :name => "Recent" } do %>
<% for post in @recent_posts %>
<h2><%=h post.title %></h2>
<!-- ... -->
<% end %>
<% end %>
Route namespaces
map.namespace :admin do |admin| # Maps to Admin::PostsController admin.resources :postsend# Maps to PostsControllermap.resources :posts
Semicolon is dead.Long live forward
slash!
Association routing shortcuts
map.resources :blogs, :has_many => [:posts, :themes], :has_one => :owner
HTTP authentication
class PostsController < ApplicationController
USER_NAME, PASSWORD = "bryan", "secret"
before_filter :authenticate, :except => [ :index ]
...
private
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
end
end
Exception handlersclass ApplicationController < ActionController::Base
rescue_from User::NotAuthorized, :with => :deny_access
rescue_from 'MyAppError::Base' do |exception|
render :xml => exception.to_xml, :status => 500
end
protected
def deny_access
# ...
end
end
Asset caching
•Concatenates file contents.
•Only active in production mode.
•Examples:<%= stylesheet_link_tag "reset", "main", :cache => true %>
<%# Cache in public/javascripts/special.js %>
<%= javascript_include_tag "whiz", "bang", :cache => "special" %>
Asset servers
•Distributes request to four asset hosts.
•Speeds up page load time considerably.
•In production.rb:ActionController::Base.asset_host = "asset
%d.example.com"
AtomFeedHelper# index.atom.builder:
atom_feed do |feed|
feed.title("Bryan's Bytes")
feed.updated((@posts.first.created_at))
for post in @posts
feed.entry(post) do |entry|
entry.title(post.title)
entry.content(post.body, :type => 'html')
entry.author do |author|
author.name("NYC.rb")
end
end
end
end
Multiview
•Template filename changes:
filename.format.renderer
•Examples:
show.csv.erb
edit.html.haml
index.atom.builder
simply_helpfulNow in core... but you should’ve been using it
already.
dom_class and dom_id
•dom_class(@person) => "person"
•dom_class(Person) => "person"
•dom_class(@person, :edit) => "edit_person"
•dom_id(@person) => "person_1234"
•dom_id(Person.new) => "new_person"
div_for/content_tag_for<% div_for @person do %> <!-- ... --><% end %>
<!-- Becomes --><div class="person" id="person_42"> <!-- ... --></div>
url_for for models
•url_for(@post) works like post_path(@post).
•url_for(Post.new) works like new_post_path.
•Works with link_to, redirect_to, etc.
render :partial for AR
• render :partial => @post works like render :partial => "post", :object => @post
• render :partial => @posts works like render :partial => "post", :collection => @posts
form_for•Determines form action based on
the record. (e.g. post_path or new_post_path)
•New records use :method => :post
•Existing records use :method => :put
•Automatically adds a HTML class and ID
form_for example
<% form_for @person do |f| %>
<%= f.text_field :name %>
<% end %>
<!-- Becomes -->
<form action="/people" method="post" class="person" id="new_person">
<input type="text" name="person[name]" id="person_name" />
</form>
Extra Goodies
Debugging
Getting started
•sudo gem install -y ruby-debug
•Call the method “debugger” in your code
•script/server --debugger
Debugger commands
• irb – Drop into an irb session
• list – List the code surround the breakpoint
•p/pp – Print results of an expression
•up – Move one frame higher
• cont – Resume execution
•next/step – Execute one line at a time.
•where – Display the current stack
Live demo
assert_emails
# Assert one email is sent during actionassert_emails 1 do post :signup, :name => "Bryan"end
# Assert no emails are sentpost :signup, :name => ""assert_no_emails
Hash filtering
•Hash#except is the inverse of Hash#slice.
•Example:
>> {:foo => 1, :bar => 2}.except(:bar, :baz)
=> {:foo=>1}
Database Rake tasks
•rake db:create and db:create:all
•rake db:drop and db:drop:all
•rake db:reset
•rake db:rollback (defaults to STEP=1)
•rake db:version
List routes with Rake
$ rake routes
posts GET /posts {:controller=>"posts", :action=>"index"}
formatted_posts GET /posts.:format {:controller=>"posts", :action=>"index"}
POST /posts {:controller=>"posts", :action=>"create"}
POST /posts.:format {:controller=>"posts", :action=>"create"}
new_post GET /posts/new {:controller=>"posts", :action=>"new"}
formatted_new_post GET /posts/new.:format {:controller=>"posts", :action=>"new"}
edit_post GET /posts/:id/edit {:controller=>"posts", :action=>"edit"}
formatted_edit_post GET /posts/:id/edit.:format {:controller=>"posts", :action=>"edit"}
post GET /posts/:id {:controller=>"posts", :action=>"show"}
formatted_post GET /posts/:id.:format {:controller=>"posts", :action=>"show"}
PUT /posts/:id {:controller=>"posts", :action=>"update"}
PUT /posts/:id.:format {:controller=>"posts", :action=>"update"}
DELETE /posts/:id {:controller=>"posts", :action=>"destroy"}
DELETE /posts/:id.:format {:controller=>"posts", :action=>"destroy"}
/:controller/:action/:id
/:controller/:action/:id.:format
Initializer hooks
Rails load order:
1.config/preinitializer.rb
2.config/environment.rb
3.config/environments/RAILS_ENV.rb
4.config/initializers/*.rb
Code annotations
Finds FIXME, TODO and OPTIMIZE comments.
$ rake notesapp/models/post.rb: * [ 2] [TODO] : Add support for themes
app/views/layouts/application.rhtml: * [ 1] [FIXME] Will break with less than three posts
Request profiler
•sudo gem install -y ruby-prof
•Example:$ cat login_session.rb
get_with_redirect '/'
post_with_redirect '/sessions', :password => 'NYC.rb!'
$ ./script/performance/request -n 10 login_session.rb
Losing weight
ActionWebService is out.Use ActiveResource for
REST.
acts_as_* behaviors
script/plugin install http://svn.rubyonrails.org/rails/plugins/acts_as_list/
script/plugin install
http://svn.rubyonrails.org/rails/plugins/acts_as_nested_set/
script/plugin install
http://svn.rubyonrails.org/rails/plugins/acts_as_tree/
Controller variables
•Don’t use @params, @session, @flash, @request or @env.
•Just drop the “@” and use the methods.
ActiveRecord finders
•Post.find_all becomes Post.find(:all).
•Post.find_first becomes Post.find(:first).
Components
•Interesting feature, but too slow.
•Try refactoring to partials and filters...
•...or grab Sebastian Delmont’s plugin:
http://dev.notso.net/svn/rails/plugins/embedded_actions/trunk/
Renamed routes
•Nested resources now use the parent name as a prefix.
•Example:map.resources :blogs do |blog| blog.resources :postsend•post_path becomes blog_post_path, etc.
Pagination
Switch to will_paginate (recommended).
http://errtheblog.com/posts/56-im-paginating-again
Or install the classic_pagination plugin:
script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
Database adapters
Adapters except SQLite, MySQL and PostgreSQL were removed from Rails core.
sudo gem install activerecord-oracle-adapter
Form helpers
•start_form_tag and end_form_tag are gone.
•Switch to the form_tag block syntax.
•Use form_for when possible.
form_tag example
<%= start_form_tag posts_path %> <%= text_field :post, :title %><%= end_form_tag %>
becomes <% form_tag posts_path do %> <%= text_field :post, :title %> <% end %>
AJAX view helpers
Autocomplete and in-place editing moved to plugins.script/plugin install http://svn.rubyonrails.org/rails/plugins/auto_complete/
script/plugin install http://svn.rubyonrails.org/rails/plugins/in_place_editing/
“Use the Source, Luke.”
How to upgrade1.Upgrade to Rails 1.2.6.
2.Eliminate deprecation warnings.
3.Make sure all your tests pass.
4.Upgrade to Rails 2.0.1.
5.Run Mislav’s Rails 2 compatibility checker script. (http://pastie.caboo.se/private/krcevozww61drdeza13e3a)
6.Make sure all your tests pass.
Questions?What’s new in
Rails 2?Bryan Helmkamp
http://brynary.com/
Photos used• http://www.flickr.com/photos/kaufman/81616562/
• http://icanhascheezburger.com/2007/01/12/wait-ill-fix-it/