1. ROR lab. DD-1
- The 1st round -
Active Support
Core Extensions
March 16, 2013
Hyoseong Choi
2. Active Support
• Ruby on Rails components
• actionmailer
• actionpack
• activerecord
• activesupport ...
3. Active Support
• Ruby on Rails components
• actionmailer
• actionpack
• activerecord
• activesupport ...
4. Active Support
• Ruby language extensions
• Utility classes
• Other transversal stuff
5. Core Extensions
Stand-Alone Active Support
require 'active_support'
“blank?” method
Cherry-picking
require 'active_support/core_ext/object/blank'
Grouped Core Extensions
require 'active_support/core_ext/object'
All Core Extensions
require 'active_support/core_ext'
All Active Support
require 'active_support/all'
6. Core Extensions
Active Support within ROR Application
Default
require 'active_support/all'
Barebone setting with Cherry-pickings
config.active_support.bare = true
7. Ext. to All Objects
• blank?
‣ nil and false 0 and 0.0
‣ whitespaces : spaces, tabs, newlines
‣ empty arrays and hashes !
blank
‣ empty? true
• present?
active_support/core_ext/object/
‣ !blank? blank.rb
8. Ext. to All Objects
• presence
host = config[:host].presence || 'localhost'
active_support/core_ext/object/
blank.rb
9. Ext. to All Objects
• duplicable?
"".duplicable? # => true
false.duplicable? # => false
Singletons : nil, false, true, symobls, numbers,
and class and module objects
active_support/core_ext/object/
duplicable.rb
10. Ext. to All Objects
• try
def log_info(sql, name, ms)
if @logger.try(:debug?)
name = '%s (%.1fms)' % [name || 'SQL', ms]
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
end
end
@person.try { |p| "#{p.first_name} #{p.last_name}" }
• try!
active_support/core_ext/object/try.rb
11. Ext. to All Objects
• singleton_class
nil => NilClass
true => TrueClass
false => FalseClass
active_support/core_ext/kernel/
singleton_class.rb
12. o us
ym s
Singleton Class?
on as
an cl
• When you add a method to a specific object, Ruby inserts
a new anonymous class into the inheritance hierarchy as
a container to hold these types of methods.
foobar = [ ]
def foobar.say
“Hello”
end
http://www.devalot.com/articles/2008/09/ruby-singleton
13. o us
ym s
Singleton Class?
on as
an cl
foobar = Array.new module Foo
def foo
def foobar.size "Hello World!"
"Hello World!" end
end end
foobar.size # => "Hello World!"
foobar.class # => Array foobar = []
bizbat = Array.new foobar.extend(Foo)
bizbat.size # => 0 foobar.singleton_methods # => ["foo"]
foobar = [] foobar = []
class << foobar foobar.instance_eval <<EOT
def foo def foo
"Hello World!" "Hello World!"
end end
end EOT
foobar.singleton_methods # => ["foo"] foobar.singleton_methods # => ["foo"]
http://www.devalot.com/articles/2008/09/ruby-singleton
14. o us
ym s
Singleton Class?
on as
an cl
• Practical Uses of Singleton Classes
class Foo
class
def self.one () 1 end
method
class << self
def two () 2 end class
end method
def three () 3 end
self.singleton_methods # => ["two", "one"]
self.class # => Class
self # => Foo
end
http://www.devalot.com/articles/2008/09/ruby-singleton
15. Ext. to All Objects
• class_eval(*args, &block)
class Proc
def bind(object)
block, time = self, Time.now
object.class_eval do
method_name = "__bind_#{time.to_i}_#{time.usec}"
define_method(method_name, &block)
method = instance_method(method_name)
remove_method(method_name)
method
end.bind(object)
end
end
active_support/core_ext/kernel/
singleton_class.rb
16. Ext. to All Objects
• acts_like?(duck) same interface?
def acts_like_string?
end
some_klass.acts_like?(:string)
or ple
f m
e xa acts_like_date? (Date class)
acts_like_time? (Time class)
active_support/core_ext/object/
acts_likes.rb
17. Ext. to All Objects
• to_param(=> to_s) a value for :id placeholder
class User
overwriting
def to_param
"#{id}-#{name.parameterize}"
end
end
➧ user_path(@user) # => "/users/357-john-smith"
=> The return value should not be escaped!
active_support/core_ext/object/
to_param.rb
18. Ext. to All Objects
• to_query a value for :id placeholder
class User
def to_param
"#{id}-#{name.parameterize}"
end
end
➧ current_user.to_query('user') # => user=357-john-smith
=> escaped!
active_support/core_ext/object/
to_query.rb
19. Ext. to All Objects
es
ca
•
pe
to_query d
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
{:c => 3, :b => 2, :a => 1}.to_query
# => "a=1&b=2&c=3"
{:id => 89, :name => "John Smith"}.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
active_support/core_ext/object/
to_query.rb
20. Ext. to All Objects
• with_options
class Account < ActiveRecord::Base
has_many :customers, :dependent => :destroy
has_many :products, :dependent => :destroy
has_many :invoices, :dependent => :destroy
has_many :expenses, :dependent => :destroy
end
class Account < ActiveRecord::Base
with_options :dependent => :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
assoc.has_many :expenses
end
end
active_support/core_ext/object/
with_options.rb
21. Ext. to All Objects
• with_options
I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
subject i18n.t(:subject)
body i18n.t(:body, user_name: user.name)
end
interpolation
key
# app/views/home/index.html.erb
<%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>
# config/locales/en.yml
en:
greet_username: "%{message}, %{user}!"
http://guides.rubyonrails.org/i18n.html
active_support/core_ext/object/
with_options.rb
22. Ext. to All Objects
• with_options
en:
scope of
activerecord: i18n
models:
user: Dude
attributes:
user:
login: "Handle"
# will translate User attribute "login" as "Handle"
config/locales/en.yml
http://guides.rubyonrails.org/i18n.html
active_support/core_ext/object/
with_options.rb
23. Ext. to All Objects
• Instance Variables
class C
def initialize(x, y)
@x, @y = x, y
end
end
C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
active_support/core_ext/object/
instance_variable.rb
24. E
Ext. to All Objects
• Silencing Warnings, Streams, and Exceptions
B OS
E R
$V
silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
si
le
st nc
re in
silence_stream(STDOUT) do am g
s
# STDOUT is silent here
end
su ev
bp en
ro i
ce n
ss
quietly { system 'bundle install' } es
si
ex le
ce nc
pt in
# If the user is locked the increment is lost, no big deal. io g
suppress(ActiveRecord::StaleObjectError) do ns
current_user.increment! :visits
end
active_support/core_ext/kernel/
reporting.rb