what's new in rails 4
TRANSCRIPT
What's new in Rails 4
Lucas Caton
4
June 25, 2013Rails 4.0: Final version released!
Ruby 1.8.7Ruby 1.9.2Ruby 1.9.3Ruby 2.0.0
RubyGems 2.x
ThreadSafety
memcache-client
dalli=> 20% faster=> ThreadSafe=> Easier to integrate with NewRelic RPM
ActiveRecordActiveModel4
#where
Post.find_all_by_title('Rails 4')
Post.where(title: 'Rails 4')
#!nd_or_*
Post.find_or_initialize_by_title('Rails 4')
Post.find_or_initialize_by(title:'Rails4')
#update
@post.update_attributes(post_params)
@post.update(post_params)
#update_columns
@post.update_attribute(post_params)
@post.update_columns(post_params)
Skip validations!
#all
@posts = Post.scoped
@posts = Post.all
ActiveRecord::Relation
Scopes
scope :sold, where(state: 'sold')default_scope where(state: 'available')
scope :sold, ->{ where(state: 'sold') }default_scope ->{ where(state: 'available') }
class User < ActiveRecord::Base def visible_posts case role when 'Country Manager' Post.where(country: country) when 'Reviewer' Post.published when 'Bad User' end endend
class User < ActiveRecord::Base def visible_posts case role when 'Country Manager' Post.where(country: country) when 'Reviewer' Post.published when 'Bad User' [] end endend
@posts = current_user.visible_posts
if @posts.any? @posts.recentelse []end
#noneclass User < ActiveRecord::Base def visible_posts case role when 'Country Manager' Post.where(country: country) when 'Reviewer' Post.published when 'Bad User' Post.none end endend
#notif author Post.where('author != ?', author)else Post.where('author IS NOT NULL')end
#notif author Post.where('author != ?', author)else Post.where('author IS NOT NULL')end
Post.where.not(author: author)
#order
User.order('created_at DESC')User.order(:name, 'created_at DESC')
User.order(created_at: :desc)User.order(:name, created_at: :desc)
ActiveModel4
ActiveModelclass SupportTicket include ActiveModel::Conversion include ActiveModel::Validations extend ActiveModel::Naming extend ActiveModel::Translation
attr_accessor :title, :description
validates_presence_of :title validates_presence_of :descriptionend
ActiveModel
class SupportTicket include ActiveModel::Model
attr_accessor :title, :description
validates_presence_of :title validates_presence_of :descriptionend
Strong Parameters4
class User < ActiveRecord::Base attr_accessible :nameend
# Controllerdef update if @user.update_attributes(params[:user]) redirect_to @user, notice: 'Updated' endend
Strong Parametersclass User < ActiveRecord::Baseend
# Controllerdef update user_params = params.require(:user).permit(:name)
end
Strong Parametersclass User < ActiveRecord::Baseend
# Controllerdef update user_params = params.require(:user).permit(:name)
if @user.update(user_params) redirect_to @user, notice: 'Updated' endend
Routes4
match '/items/:id/purchase', to: 'items#purchase'
match '/items/:id/purchase', to: 'items#purchase'XSS Attack (Cross-site Scripting)
post '/items/:id/purchase', to: 'items#purchase'match '/items/:id/purchase', to: 'items#purchase', via: :postmatch '/items/:id/purchase', to: 'items#purchase', via: :all
PATCH Method for HTTPAbstract
Several applications extending the Hypertext Transfer Protocol (HTTP) require a feature to do partial resource
modi!cation. The existing HTTP PUT method only allows a complete replacement of a document. This proposal
adds a new HTTP method, PATCH, to modify an existing HTTP resource.
http://tools.ietf.org/html/rfc5789
$ rake routes
items GET /items(.:format) items#index POST /items(.:format) items#createnew_item GET /items/new(.:format) items#newedit_item GET /items/:id/edit(.:format) items#edititem GET /items/:id(.:format) items#show PUT /items/:id(.:format) items#update PATCH /items/:id(.:format) items#update DELETE /items/:id(.:format) items#destroy
PATCH HTTP verb
Action Controller4
#before_action
before_filter :set_user, only: [:update]
before_action :set_user, only: [:update]
Encrypted cookie storedin the browser
Flash messages
<p id="notice"><%= flash[:notice] %></p>
<p id="notice"><%= notice %></p>
Streaming
class FooController < ActionController::Base include ActionController::Live
def index 100.times { # Client will see this as it's written response.stream.write "hello world\n" sleep 1 } response.stream.close endend
Views4
collections helpers<% @owners.each do |owner| %> <%= radio_button_tag :owner_id, owner.id %> <%= owner.name %><% end %>
collection_radio_buttons(:item, :owner_id, @owners, :id, :name)
collection_check_boxes(:item, :owner_id, @owners, :id, :name)
date !elds
<%= f.date_field :return_date %>
<input id="item_return_date" name="item[return_date]" type="date">
date !elds<%= f.date_field :return_date %>
ETags
First request
1. Render body2. Create ETag3. Body & ETag includedin response
First request
1. Render body2. Create ETag3. Body & ETag includedin response
headers['ETag'] = Digest::MD5.hexdigest(body)
First request
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
304 Not Modified
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Client caches response Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
304 Not Modified
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Client caches response Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
304 Not Modified
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Client caches response Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
1. Render body2. Create ETag3. Compare ETag4. If ETags match then bodynot included in response
304 Not Modified
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Client caches response Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
1. Render body2. Create ETag3. Compare ETag4. If ETags match then bodynot included in response
304 Not Modified
1. Render body2. Create ETag3. Body & ETag includedin response
200 Successheaders['ETag']
328ebd07ec6a48ad7f70e44045f184a8
First request
Client caches response Second requestheaders['If-None-Match']328ebd07ec6a48ad7f70e44045f184a8
Client reads responsefrom cache
1. Render body2. Create ETag3. Compare ETag4. If ETags match then bodynot included in response
304 Not Modified
TurboLinks
aka. full body pjax
https://github.com/defunkt/jquery-pjax
turbolinks
gem 'turbolinks'
//= require turbolinks
Gem!le
app/assets/javascripts/application.js
turbolinks
gem 'turbolinks'gem 'jquery-turbolinks'
//= require turbolinks//= require jquery.turbolinks
Gem!le
app/assets/javascripts/application.js
turbolinks
Other improvements
=> Routing Concerns=> Test Folder Structure=> Caching improvements=> Custom Flash Types=> jbuilder template handler
LinksRails Guides - Upgrading from Rails 3.2 to Rails 4.0:http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0
Rails Casts - Upgrading to Rails 4http://railscasts.com/episodes/415-upgrading-to-rails-4
Code School - Learn Rails 4 best practiceshttp://www.codeschool.com/courses/rails-4-zombie-outlaws
Thank you!
?