h2. Active Support Overview
Active Support is the Rails component responsible for providing Ruby language extensions, utilities, and other transversal stuff. It offers a richer bottom-line at the language level, targeted both at the development of Rails applications, and at the development of Rails itself.
By referring to this guide you will learn:
* The extensions to the Ruby core modules and classes provided by Rails.
* The rest of fundamental libraries available in Rails.
endprologue.
h3. Extensions to All Objects
h4. +blank?+ and +present?+
h3. Extensions to +Module+
...
h3. Extensions to +Class+
h4. Class Attribute Accessors
The macros +cattr_reader+, +cattr_writer+, and +cattr_accessor+ are analogous to their +attr_*+ counterparts but for classes. They initialize a class variable to +nil+ unless it already exists, and generate the corresponding class methods to access it:
class MysqlAdapter < AbstractAdapter
# Generates class methods to access @@emulate_booleans.
cattr_accessor :emulate_booleans
self.emulate_booleans = true
end
Instance methods are created as well for convenience. For example given
module ActionController
class Base
cattr_accessor :logger
end
end
we can access +logger+ in actions. The generation of the writer instance method can be prevented setting +:instance_writer+ to +false+ (not any false value, but exactly +false+):
module ActiveRecord
class Base
# No pluralize_table_names= instance writer is generated.
cattr_accessor :pluralize_table_names, :instance_writer => false
end
end
h4. Class Inheritable Attributes
Class variables are shared down the inheritance tree. Class instance variables are not shared, but they are not inherited either. The macros +class_inheritable_reader+, +class_inheritable_writer+, and +class_inheritable_accessor+ provide accesors for class-level data which is inherited but not shared with children:
module ActionController
class Base
# FIXME: REVISE/SIMPLIFY THIS COMMENT.
# The value of allow_forgery_protection is inherited,
# but its value in a particular class does not affect
# the value in the rest of the controllers hierarchy.
class_inheritable_accessor :allow_forgery_protection
end
end
They accomplish this with class instance variables and cloning on subclassing, there are no class variables involved. Cloning is performed with +dup+ as long as the value is duplicable.
There are some variants specialised in arrays and hashes:
class_inheritable_array
class_inheritable_hash
Those writers take any inherited array or hash into account and extend them rather than overwrite them.
As with vanilla class attribute accessors these macros create convenience instance methods for reading and writing. The generation of the writer instance method can be prevented setting +:instance_writer+ to +false+ (not any false value, but exactly +false+):
module ActiveRecord
class Base
class_inheritable_accessor :default_scoping, :instance_writer => false
end
end
Since values are copied when a subclass is defined, if the base class changes the attribute after that, the subclass does not see the new value. That's the point.
There's a related macro called +superclass_delegating_accessor+, however, that does not copy the value when the base class is subclassed. Instead, it delegates reading to the superclass as long as the attribute is not set via its own writer. For example, +ActionMailer::Base+ defines +delivery_method+ this way:
module ActionMailer
class Base
superclass_delegating_accessor :delivery_method
self.delivery_method = :smtp
end
end
If for whatever reason an application loads the definition of a mailer class and after that sets +ActionMailer::Base.delivery_method+, the mailer class will still see the new value. In addition, the mailer class is able to change the +delivery_method+ without affecting the value in the parent using its own inherited class attribute writer.
h4. Subclasses
The +subclasses+ method returns the names of all subclasses of a given class as an array of strings. That comprises not only direct subclasses, but all descendants down the hierarchy:
class C; end
C.subclasses # => []
Integer.subclasses # => ["Bignum", "Fixnum"]
module M
class A; end
class B1 < A; end
class B2 < A; end
end
module N
class C < M::B1; end
end
M::A.subclasses # => ["N::C", "M::B2", "M::B1"]
The order in which these class names are returned is unspecified.
See also +Object#subclasses_of+ in "Extensions to All Objects FIX THIS LINK":FIXME.
h4. Class Removal
Roughly speaking, the +remove_class+ method removes the class objects passed as arguments:
Class.remove_class(Hash, Dir) # => [Hash, Dir]
Hash # => NameError: uninitialized constant Hash
Dir # => NameError: uninitialized constant Dir
More specifically, +remove_class+ attempts to remove constants with the same name as the passed class objects from their parent modules. So technically this method does not guarantee the class objects themselves are not still valid and alive somewhere after the method call:
module M
class A; end
class B < A; end
end
A2 = M::A
M::A.object_id # => 13053950
Class.remove_class(M::A)
M::B.superclass.object_id # => 13053950 (same object as before)
A2.name # => "M::A" (name is hard-coded in object)
WARNING: Removing fundamental classes like +String+ can result in really funky behaviour.
The method +remove_subclasses+ provides a shortcut for removing all descendants of a given class, where "removing" has the meaning explained above:
class A; end
class B1 < A; end
class B2 < A; end
class C < A; end
A.subclasses # => ["C", "B2", "B1"]
A.remove_subclasses
A.subclasses # => []
C # => NameError: uninitialized constant C
See also +Object#remove_subclasses_of+ in "Extensions to All Objects FIX THIS LINK":FIXME.
h3. Extensions to +NilClass+
...
h3. Extensions to +TrueClass+
...
h3. Extensions to +FalseClass+
...
h3. Extensions to +Symbol+
...
h3. Extensions to +String+
...
h3. Extensions to +Numeric+
...
h3. Extensions to +Integer+
...
h3. Extensions to +Float+
...
h3. Extensions to +BigDecimal+
...
h3. Extensions to +Enumerable+
...
h3. Extensions to +Array+
h4. Accessing
Active Support augments the API of arrays to ease certain ways of accessing them or subsets of them. For example, +to+ returns the subarray of elements up to the one at the passed index:
%w(a b c d).to(2) # => %w(a b c)
[].to(7) # => []
Similarly, +from+ returns the tail from the element at the passed index on:
%w(a b c d).from(2) # => %w(c d)
%w(a b c d).from(10) # => nil
[].from(0) # => nil
The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is builtin). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available.
You can pick a random element with +rand+:
shape_type = [Circle, Square, Triangle].rand
h3. Extensions to +Hash+
...
h3. Extensions to +Range+
...
h3. Extensions to +Proc+
...
h3. Extensions to +Date+
...
h3. Extensions to +DateTime+
...
h3. Extensions to +Time+
...
h3. Extensions to +Process+
...
h3. Extensions to +Pathname+
...
h3. Extensions to +File+
...
h3. Extensions to +Exception+
...
h3. Extensions to +NameError+
...
h3. Extensions to +LoadError+
...
h3. Extensions to +CGI+
...
h3. Extensions to +Benchmark+
...
h3. Changelog
"Lighthouse ticket":https://rails.lighthouseapp.com/projects/16213/tickets/67
* April 18, 2009: Initial version by "Xavier Noria":credits.html#fxn