08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
Ruby 2.0 / Rails 4.0, A selection of new features.
1. Ruby 2.0 / Rails 4.0
A selection of new features
Evan Dorn
Founder, Logical Reality Design
http://lrdesign.com
evan@lrdesign.com
@idahoev
Friday, August 9, 13
14. REFINEMENTS
•Hopefully improves the monkeypatch madness
•How many Core or StdLib classes does Rails extend?
•String
•Integer
•Hash
• Range
• Array
•Regexp
•Proc
•Date
•File
•Marshal
•Logger
•NameError
•Numeric
•BigDecimal
•LoadError
•Time
Friday, August 9, 13
15. REFINEMENTS
•Hopefully improves the monkeypatch madness
•How many Core or StdLib classes does Rails extend?
•String
•Integer
•Hash
• Range
• Array
•Regexp
•Proc
•Date
•File
•Marshal
•Logger
•NameError
•Numeric
•BigDecimal
•LoadError
•Time
•Module
•Class
•Object
Friday, August 9, 13
16. REFINEMENTS
•What’s wrong with all this?
•“core” becomes a bit meaningless
•All loaded code sees these mutant core classes
•Harder to write gems that both with and without Rails
Friday, August 9, 13
20. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
21. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
22. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
23. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
24. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
25. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
26. REFINEMENTS
module MyExtensions
refine String do
def do_stuff
p “awesome!”
end
end
end
String.new.do_stuff # undefined method “do_stuff”
using MyExtensions
String.new.do_stuff
=> “awesome!”
Friday, August 9, 13
27. KEYWORD ARGUMENTS
•my_method(options = {}) has problems
•assigning defaults with merge({...}) is fugly
•options[:mispeled_arg] silently returns nil!
•options = {} allocates a new hash on every call
Friday, August 9, 13
39. STRONG PARAMS
class UsersController < ApplicationController
def update
user = User.find(params[:id])
if user.update_attributes(user_params) # see below
redirect_to home_path
else
render :edit
end
end
private
# Require that :user be a key in the params Hash,
# and only accept :first, :last, and :email attributes
def user_params
params.require(:user).permit(:first, :last, :email)
end
end
Friday, August 9, 13
40. STRONG PARAMS
class UsersController < ApplicationController
def update
user = User.find(params[:id])
if user.update_attributes(user_params) # see below
redirect_to home_path
else
render :edit
end
end
private
# Require that :user be a key in the params Hash,
# and only accept :first, :last, and :email attributes
def user_params
params.require(:user).permit(:first, :last, :email)
end
end
Friday, August 9, 13
41. STRONG PARAMS
class UsersController < ApplicationController
def update
user = User.find(params[:id])
if user.update_attributes(user_params) # see below
redirect_to home_path
else
render :edit
end
end
private
# Require that :user be a key in the params Hash,
# and only accept :first, :last, and :email attributes
def user_params
params.require(:user).permit(:first, :last, :email)
end
end
Friday, August 9, 13
42. STRONG PARAMS
class UsersController < ApplicationController
def update
user = User.find(params[:id])
if user.update_attributes(user_params) # see below
redirect_to home_path
else
render :edit
end
end
private
# Require that :user be a key in the params Hash,
# and only accept :first, :last, and :email attributes
def user_params
params.require(:user).permit(:first, :last, :email)
end
end
Friday, August 9, 13
43. STRONG PARAMS
•Params hashes get some new methods
•e.g. params.permitted?
•params hash will contain only the permitted keys
•No deep permits: if the Hash contains a Hash, you
must permit nested keys specifically
Friday, August 9, 13
45. FRAGMENT CACHING
•Caching HTML fragments can be a huge speedup
•Expiring fragments correctly is a bitch
•... especially if they’re nested
•... and slow if you have a lot of cache keys
Friday, August 9, 13
46. OLD BUSTED CACHING
%h2 To-do List
- cache “todo_for_#{current_user.id}” do
%table
- @todo_items.each do |item|
- cache “todo_item_#{item.id}” do
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
47. OLD BUSTED CACHING
%h2 To-do List
- cache “todo_for_#{current_user.id}” do
%table
- @todo_items.each do |item|
- cache “todo_item_#{item.id}” do
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
48. RUSSIAN DOLL CACHING
•Important changes:
•cache(key) do ...end takes an Array for the key
•key generation concatenates the array elements
•after calling #cache_key on any members that
respond to that method
Friday, August 9, 13
49. NEW HOTNESS CACHING
%h2 To-do List
- cache [ :todo_list, current_user, @todo_list ] do
%table
- @todo_list.items.each do |item|
- cache [ :todo_item, item ] do
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
50. NEW HOTNESS CACHING
%h2 To-do List
- cache [ :todo_list, current_user, todo_list ] do
%table
- @todo_list.items.each do |item|
- cache [ :todo_item, item ] do
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
51. class TodoItem < ActiveRecord::Base
def cache_key
“#{self.id}-#{self.updated_at.to_s(:number)}”
end
end
class TodoList # A presenter
attr_accessor :items # array of items
attr_accessor :user # User object
def cache_key
“#{user.id}-#{items.newest.updated_at.to_s(:number)“
end
end
Friday, August 9, 13
52. class TodoItem < ActiveRecord::Base
def cache_key
“#{self.id}-#{self.updated_at.to_s(:number)}”
end
end
class TodoList # A presenter
attr_accessor :items # array of items
attr_accessor :user # User object
def cache_key
“#{user.id}-#{items.newest.updated_at.to_s(:number)“
end
end
Friday, August 9, 13
53. class TodoItem < ActiveRecord:: Base
def cache_key
“#{self.id}-#{self.updated_at.to_s(:number)}”
end
end
class TodoList # A Presenter
attr_accessor :items # array of items
attr_accessor :user # User object
def cache_key
“#{user.id}-#{items.newest.updated_at.to_s(:number)“
end
end
Friday, August 9, 13
55. class TodoItem
def cache_key
“#{self.id}-#{self.updated_at.to_s(:number)}”
end
end
class TodoList
attr_accessor :items # array of items
attr_accessor :user # User object
def cache_key
“#{items.newest.updated_at.to_s(:number)“
end
end
class User < ActiveRecord::Base
def cache_key
“#{self.id}-#{self.updated_at.to_s(:number)}”
end
end
Friday, August 9, 13
56. NEW HOTNESS CACHING
%h2 To-do List
- cache [ :todo_list, current_user, todo_list ] do
-# “todo_list/1234-201308081234/201308081146”
%table
- @todo_list.items.each do |item|
- cache [ :todo_item, item ] do
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
57. NEW HOTNESS CACHING
%h2 To-do List
- cache [ :todo_list, current_user, todo_list ] do
-# “todo_list/1234-201308081234/201308081146”
%table
- @todo_list.items.each do |item|
- cache [ :todo_item, item ] do
-# “todo_item/5316-201306071156”
%tr
%td= item.name
%td= item.importance
Friday, August 9, 13
58. RUSSIAN DOLL CACHING
•With clever key construction:
•Every model update causes a cache miss
•... Never have to invalidate fragments!
•Any decent memory store will expire unused keys for
you
Friday, August 9, 13
59. PSST... A SECRET:
You can do this in Rails 3, too.
Just write your own smart cache key
helpers.
Friday, August 9, 13
60. PATCH
•PUT is no longer the default HTTP method for #update
actions.
•(Because PUT is defined to be whole-object, never
partial, and should avoid side-effects.)
•Use PATCH instead
•Affects: config/routes.rb, tests, etc.
Friday, August 9, 13
61. ACTIVEMODEL::MODEL
•Turns any object into a proper model
•For use with form_for(), etc.
•attr_accessors become AM-style attributes
•Adds name introspection, conversion, I18n support,
validations, etc...
Friday, August 9, 13
63. ACTIVEMODEL::MODEL
class UserFormModel
include ActiveModel::Model
def new(user)
@user = user
@settings = user.settings
end
attr_accessor :name, :admin
def persisted?
@user.persisted?
end
def persist!
@user.name = name
@user.save!
@settings.admin = admin
@settings.save!
end
end
Friday, August 9, 13
64. ACTIVEMODEL::MODEL
class UserFormModel
include ActiveModel::Model
def new(user)
@user = user
@settings = user.settings
end
attr_accessor :name, :admin
def persisted?
@user.persisted?
end
def persist!
@user.name = name
@user.save!
@settings.admin = admin
@settings.save!
end
Friday, August 9, 13
65. ACTIVEMODEL::MODEL
class UserFormModel
include ActiveModel::Model
def new(user)
@user = user
@settings = user.settings
end
attr_accessor :name, :admin
def persisted?
@user.persisted?
end
def persist!
@user.name = name
@user.save!
@settings.admin = admin
@settings.save!
end
Friday, August 9, 13
66. ACTIVEMODEL::MODEL
class UserFormModel
include ActiveModel::Model
def new(user)
@user = user
@settings = user.settings
end
attr_accessor :name, :admin
def persisted? # default false if not overridden!
@user.persisted?
end
def persist!
@user.name = name
@user.save!
@settings.admin = admin
@settings.save!
end
end
Friday, August 9, 13
67. ACTIVEMODEL::MODEL
class UserFormModel
include ActiveModel::Model
def new(user)
@user = user
@settings = user.settings
end
attr_accessor :name, :admin
def persisted?
@user.persisted?
end
def persist!
@user.name = name
@user.save!
@settings.admin = admin
@settings.save!
end
end
Friday, August 9, 13
75. ACTIONCONTROLLER::LIVE
class MyController < ActionController::Base
include ActionController::Live
def stream
response.headers['Content-Type'] = 'text/event-stream'
100.times {
response.stream.write "hello worldn"
sleep 1
}
ensure
response.stream.close
end
end
Friday, August 9, 13
76. ACTIONCONTROLLER::LIVE
class MyController < ActionController::Base
include ActionController::Live
def stream
response.headers['Content-Type'] = 'text/event-stream'
100.times {
response.stream.write "hello worldn"
sleep 1
}
ensure
response.stream.close
end
end
Friday, August 9, 13
77. ACTIONCONTROLLER::LIVE
class MyController < ActionController::Base
include ActionController::Live
def stream
response.headers['Content-Type'] = 'text/event-stream'
100.times {
response.stream.write "hello worldn"
sleep 1
}
ensure
response.stream.close
end
end
Friday, August 9, 13
78. ACTIONCONTROLLER::LIVE
class MyController < ActionController::Base
include ActionController::Live
def stream
response.headers['Content-Type'] = 'text/event-stream'
100.times {
response.stream.write "hello worldn"
sleep 1
}
ensure
response.stream.close
end
end
Friday, August 9, 13
79. ACTIONCONTROLLER::LIVE
•Don’t try to change headers after calling
response.stream.write...
•Don’t forget to close...
•Stream actions automatically happen in a separate
thread.
•(So make sure it’s thread-safe!)
Friday, August 9, 13
80. ANY TIME LEFT?
(IF SO, I’LL DO
MODULE#PREPEND ON A
WHITEBOARD OR SOMETHING.)
Friday, August 9, 13