2. Ext. to Module
• alias_method_chain
active_support/core_ext/module/
aliasing.rb
• “alias chaining”? ➧ wrapping
http://erniemiller.org/2011/02/03/when-to-use-alias_method_chain/
ActionController::TestCase.class_eval do
def process_with_stringified_params(...)
params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
process_without_stringified_params(action,
params, session, flash, http_method)
end
alias_method_chain :process, :stringified_params
end
3. Ext. to Module
• alias_attribute
active_support/core_ext/module/
aliasing.rb
class User < ActiveRecord::Base
# let me refer to the email column as "login",
# possibly meaningful for authentication code
alias_attribute :login, :email
end
4. Ext. to Module
• attr_accessor_with_default
active_support/core_ext/module/
attr_accessor_with_default.rb
class Url
attr_accessor_with_default :port, 80
end
Url.new.port # => 80
class User
attr_accessor :name, :surname
attr_accessor_with_default(:full_name) do
[name, surname].compact.join(" ")
end
end
u = User.new
u.name = 'Xavier'
u.surname = 'Noria'
u.full_name # => "Xavier Noria"
not
cached
5. Ext. to Module
• attr_internal or attr_internal_accessor
active_support/core_ext/module/
attr_internal.rb
# library
class ThirdPartyLibrary::Crawler
attr_internal :log_level
end
# client code
class MyCrawler < ThirdPartyLibrary::Crawler
attr_accessor :log_level
end
@_log_level
Module.attr_internal_naming_format = “@_%s”
sprintf-like format
6. Ext. to Module
• attr_internal or attr_internal_accessor
active_support/core_ext/module/
attr_internal.rb
module ActionView
class Base
attr_internal :captures
attr_internal :request, :layout
attr_internal :controller, :template
end
end
9. Ext. to Module
• Parents
active_support/core_ext/module/
introspection.rb
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.parent # => X::Y
M.parent # => X::Y
• parent
10. Ext. to Module
• Parents
active_support/core_ext/module/
introspection.rb
• parent_name
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.parent_name # => "X::Y"
M.parent_name # => "X::Y"
11. Ext. to Module
• Parents
active_support/core_ext/module/
introspection.rb
• parents
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.parents # => [X::Y, X, Object]
M.parents # => [X::Y, X, Object]
12. Ext. to Module
• local_constants
module X
X1 = 1
X2 = 2
module Y
Y1 = :y1
X1 = :overrides_X1_above
end
end
X.local_constants # => ["X2", "X1", "Y"], assumes Ruby 1.8
X::Y.local_constants # => ["X1", "Y1"], assumes Ruby 1.8
active_support/core_ext/module/
introspection.rb
• local_constant_names ⟶ always, strings
as symbols in Ruby 1.9
deprecated!!!
14. Ext. to Module
• const_defined? /_get /_set
module Foo
class Bar
VAL = 10
end
class Baz < Bar; end
end
Object.const_get 'Foo::Baz::VAL' # => 10
Object.const_get 'Foo::Baz::VAL', false # => NameError
active_support/core_ext/module/
introspection.rb
standard ruby methods
bare constant names
flag for inherit
15. Ext. to Module
• qualified_const_defined? /_get /_set
module M
X = 1
end
module N
class C
include M
end
end
active_support/core_ext/module/
qualified_const.rb
new extended methods
N.qualified_const_defined?("C::X", false)
N.qualified_const_defined?("C::X", true)
N.qualified_const_defined?("C::X")
relative to their receiver
qualified constant names
16. Ext. to Module
• synchronize
class Counter
@@mutex = Mutex.new
attr_reader :value
def initialize
@value = 0
end
def incr
@value += 1 # non-atomic
end
synchronize :incr, :with => '@@mutex'
end
active_support/core_ext/module/
synchronization.rb
DEPRECATION WARNING: synchronize
is deprecated and will be
removed from Rails 4.0.
17. Ext. to Module
• reachable?
module M
end
M.reachable? # => true
orphan = Object.send(:remove_const, :M)
# The module object is orphan now but it still has a name.
orphan.name # => "M"
# You cannot reach it via the constant M because it does not even exist.
orphan.reachable? # => false
# Let's define a module called "M" again.
module M
end
# The constant M exists now again, and it stores a module
# object called "M", but it is a new instance.
orphan.reachable? # => false
active_support/core_ext/module/
reachable.rb
The constant M exists now,
and it stores a module object called "M"
18. Ext. to Module
• anonymous?
module M
end
M.name # => "M"
N = Module.new
N.name # => "N"
Module.new.name # => "" in 1.8, nil in 1.9
M.anonymous? # => false
Module.new.anonymous? # => true
m = Object.send(:remove_const, :M)
m.reachable? # => false
m.anonymous? # => false
active_support/core_ext/module/
anonymous.rb
19. Ext. to Module
• delegate
class User < ActiveRecord::Base
has_one :profile
end
class User < ActiveRecord::Base
has_one :profile
def name
profile.name
end
end
class User < ActiveRecord::Base
has_one :profile
delegate :name, :to => :profile
end
delegate :name, :age, :address, :twitter, :to => :profile
delegate :name, :to => :profile, :allow_nil => true
delegate :street, :to => :address, :prefix => true
delegate :size, :to => :attachment, :prefix => :avatar
active_support/core_ext/module/
delegation.rb
20. Ext. to Module
• redefine_method
redefine_method("#{reflection.name}=") do |new_value|
association = association_instance_get(reflection.name)
if association.nil? || association.target != new_value
association = association_proxy_class.new(self, reflection)
end
association.replace(new_value)
association_instance_set(reflection.name, new_value.nil? ?
nil : association)
end
active_support/core_ext/module/
remove_method.rb