1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge branch 'master' of github.com:lifo/docrails

Conflicts:
	activesupport/lib/active_support/core_ext/hash/slice.rb
	guides/source/active_support_core_extensions.md
This commit is contained in:
Vijay Dev 2012-10-21 18:49:19 +05:30
commit f938019da2
52 changed files with 674 additions and 482 deletions

View file

@ -19,13 +19,13 @@ module ActionController
end
end
# == Action Controller Parameters
# == Action Controller \Parameters
#
# Allows to choose which attributes should be whitelisted for mass updating
# and thus prevent accidentally exposing that which shouldnt be exposed.
# Provides two methods for this purpose: #require and #permit. The former is
# used to mark parameters as required. The latter is used to set the parameter
# as permitted and limit which attributes should be allowed for mass updating.
# as permitted and limit which attributes should be allowed for mass updating.
#
# params = ActionController::Parameters.new({
# person: {
@ -77,12 +77,12 @@ module ActionController
#
# params = ActionController::Parameters.new(name: 'Francesco')
# params.permitted? # => false
# Person.new(params) # => ActiveModel::ForbiddenAttributesError
# Person.new(params) # => ActiveModel::ForbiddenAttributesError
#
# ActionController::Parameters.permit_all_parameters = true
#
# params = ActionController::Parameters.new(name: 'Francesco')
# params.permitted? # => true
# params.permitted? # => true
# Person.new(params) # => #<Person id: nil, name: "Francesco">
def initialize(attributes = nil)
super(attributes)
@ -106,7 +106,7 @@ module ActionController
# end
#
# params = ActionController::Parameters.new(name: 'Francesco')
# params.permitted? # => false
# params.permitted? # => false
# Person.new(params) # => ActiveModel::ForbiddenAttributesError
# params.permit!
# params.permitted? # => true
@ -125,7 +125,7 @@ module ActionController
# the parameter at the given +key+, otherwise raises an
# <tt>ActionController::ParameterMissing</tt> error.
#
# ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
# ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
# # => {"name"=>"Francesco"}
#
# ActionController::Parameters.new(person: nil).require(:person)
@ -141,13 +141,13 @@ module ActionController
alias :required :require
# Returns a new <tt>ActionController::Parameters</tt> instance that
# includes only the given +filters+ and sets the +permitted+ for the
# object to +true+. This is useful for limiting which attributes
# includes only the given +filters+ and sets the +permitted+ attribute
# for the object to +true+. This is useful for limiting which attributes
# should be allowed for mass updating.
#
# params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
# permitted = params.require(:user).permit(:name, :age)
# permitted.permitted? # => true
# permitted.permitted? # => true
# permitted.has_key?(:name) # => true
# permitted.has_key?(:age) # => true
# permitted.has_key?(:role) # => false
@ -155,7 +155,7 @@ module ActionController
# You can also use +permit+ on nested parameters, like:
#
# params = ActionController::Parameters.new({
# person: {
# person: {
# name: 'Francesco',
# age: 22,
# pets: [{
@ -168,7 +168,7 @@ module ActionController
# permitted = params.permit(person: [ :name, { pets: :name } ])
# permitted.permitted? # => true
# permitted[:person][:name] # => "Francesco"
# permitted[:person][:age] # => nil
# permitted[:person][:age] # => nil
# permitted[:person][:pets][0][:name] # => "Purplish"
# permitted[:person][:pets][0][:category] # => nil
#
@ -229,7 +229,7 @@ module ActionController
# returns +nil+.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
# params[:person] # => {"name"=>"Francesco"}
# params[:person] # => {"name"=>"Francesco"}
# params[:none] # => nil
def [](key)
convert_hashes_to_parameters(key, super)
@ -242,10 +242,10 @@ module ActionController
# is given, then that will be run and its result returned.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
# params.fetch(:person) # => {"name"=>"Francesco"}
# params.fetch(:none) # => ActionController::ParameterMissing: param not found: none
# params.fetch(:person) # => {"name"=>"Francesco"}
# params.fetch(:none) # => ActionController::ParameterMissing: param not found: none
# params.fetch(:none, 'Francesco') # => "Francesco"
# params.fetch(:none) { 'Francesco' } # => "Francesco"
# params.fetch(:none) { 'Francesco' } # => "Francesco"
def fetch(key, *args)
convert_hashes_to_parameters(key, super)
rescue KeyError
@ -303,7 +303,7 @@ module ActionController
# == Strong \Parameters
#
# It provides an interface for protecting attributes from end-user
# assignment. This makes Action Controller parameters forbidden
# assignment. This makes Action Controller parameters forbidden
# to be used in Active Model mass assignment until they have been
# whitelisted.
#
@ -332,7 +332,7 @@ module ActionController
#
# private
# # Using a private method to encapsulate the permissible parameters is
# # just a good pattern since you'll be able to reuse the same permit
# # just a good pattern since you'll be able to reuse the same permit
# # list between create and update. Also, you can specialize this method
# # with per-user checking of permissible attributes.
# def person_params
@ -340,6 +340,31 @@ module ActionController
# end
# end
#
# In order to use <tt>accepts_nested_attribute_for</tt> with Strong \Parameters, you
# will need to specify which nested attributes should be whitelisted.
#
# class Person
# has_many :pets
# accepts_nested_attributes_for :pets
# end
#
# class PeopleController < ActionController::Base
# def create
# Person.create(person_params)
# end
#
# ...
#
# private
#
# def person_params
# # It's mandatory to specify the nested attributes that should be whitelisted.
# # If you use `permit` with just the key that points to the nested attributes hash,
# # it will return an empty hash.
# params.require(:person).permit(:name, :age, pets_attributes: { :name, :category })
# end
# end
#
# See ActionController::Parameters.require and ActionController::Parameters.permit
# for more information.
module StrongParameters

View file

@ -75,7 +75,11 @@ behavior out of the box:
* Tracking value changes
The ActiveModel::Dirty module allows for tracking attribute changes:
class Person
include ActiveModel::Dirty
attr_accessor :name
end
person = Person.new
person.name # => nil
@ -152,9 +156,31 @@ behavior out of the box:
ActiveModel::Serialization provides a standard interface for your object
to provide +to_json+ or +to_xml+ serialization.
class SerialPerson
include ActiveModel::Serialization
attr_accessor :name
def attributes
{'name' => name}
end
end
s = SerialPerson.new
s.serializable_hash # => {"name"=>nil}
class SerialPerson
include ActiveModel::Serializers::JSON
end
s = SerialPerson.new
s.to_json # => "{\"name\":null}"
class SerialPerson
include ActiveModel::Serializers::Xml
end
s = SerialPerson.new
s.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
{Learn more}[link:classes/ActiveModel/Serialization.html]

View file

@ -11,7 +11,7 @@ module ActiveModel
# # => ActiveModel::MissingAttributeError: missing attribute: user_id
class MissingAttributeError < NoMethodError
end
# == Active Model Attribute Methods
# == Active \Model Attribute Methods
#
# <tt>ActiveModel::AttributeMethods</tt> provides a way to add prefixes and
# suffixes to your methods as well as handling the creation of Active Record

View file

@ -1,7 +1,7 @@
require 'active_support/callbacks'
module ActiveModel
# == Active Model Callbacks
# == Active \Model \Callbacks
#
# Provides an interface for any class to have Active Record like callbacks.
#

View file

@ -1,7 +1,7 @@
require 'active_support/inflector'
module ActiveModel
# == Active Model Conversions
# == Active \Model Conversions
#
# Handles default conversions: to_model, to_key, to_param, and to_partial_path.
#

View file

@ -3,7 +3,7 @@ require 'active_support/hash_with_indifferent_access'
require 'active_support/core_ext/object/duplicable'
module ActiveModel
# == Active Model Dirty
# == Active \Model \Dirty
#
# Provides a way to track changes in your object in the same way as
# Active Record does.

View file

@ -4,7 +4,7 @@ require 'active_support/core_ext/array/conversions'
require 'active_support/core_ext/string/inflections'
module ActiveModel
# == Active Model Errors
# == Active \Model \Errors
#
# Provides a modified +Hash+ that you can include in your object
# for handling error messages and interacting with Action Pack helpers.

View file

@ -1,8 +1,8 @@
module ActiveModel
module Lint
# == Active Model Lint Tests
# == Active \Model \Lint \Tests
#
# You can test whether an object is compliant with the Active Model API by
# You can test whether an object is compliant with the Active \Model API by
# including <tt>ActiveModel::Lint::Tests</tt> in your TestCase. It will
# include tests that tell you whether your object is fully compliant,
# or if not, which aspects of the API are not implemented.
@ -71,7 +71,7 @@ module ActiveModel
assert_boolean model.persisted?, "persisted?"
end
# == Naming
# == \Naming
#
# Model.model_name must return a string with some convenience methods:
# <tt>:human</tt>, <tt>:singular</tt> and <tt>:plural</tt>. Check
@ -85,7 +85,7 @@ module ActiveModel
assert model_name.plural.respond_to?(:to_str)
end
# == Errors Testing
# == \Errors Testing
#
# Returns an object that implements [](attribute) defined which returns an
# Array of Strings that are the errors for the attribute in question.

View file

@ -1,6 +1,6 @@
module ActiveModel
# == Active Model Basic Model
# == Active \Model Basic \Model
#
# Includes the required interface for an object to interact with
# <tt>ActionPack</tt>, using different <tt>ActiveModel</tt> modules.

View file

@ -195,7 +195,7 @@ module ActiveModel
end
end
# == Active Model Naming
# == Active \Model \Naming
#
# Creates a +model_name+ method on your object.
#

View file

@ -8,7 +8,7 @@ require 'active_support/core_ext/object/try'
require 'active_support/descendants_tracker'
module ActiveModel
# == Active Model Observers Activation
# == Active \Model Observers Activation
module Observing
extend ActiveSupport::Concern
@ -229,7 +229,7 @@ module ActiveModel
end
end
# == Active Model Observers
# == Active \Model Observers
#
# Observer classes respond to life cycle callbacks to implement trigger-like
# behavior outside the original class. This is a great way to reduce the
@ -257,7 +257,7 @@ module ActiveModel
#
# This Observer uses logger to log when specific callbacks are triggered.
#
# == Observing a class that can't be inferred
# == \Observing a class that can't be inferred
#
# Observers will by default be mapped to the class with which they share a
# name. So <tt>CommentObserver</tt> will be tied to observing <tt>Comment</tt>,

View file

@ -2,7 +2,7 @@ require "active_model"
require "rails"
module ActiveModel
class Railtie < Rails::Railtie
class Railtie < Rails::Railtie # :nodoc:
config.eager_load_namespaces << ActiveModel
end
end
end

View file

@ -44,7 +44,7 @@ module ActiveModel
if options.fetch(:validations, true)
validates_confirmation_of :password
validates_presence_of :password, :on => :create
before_create { raise "Password digest missing on new record" if password_digest.blank? }
end
@ -68,7 +68,7 @@ module ActiveModel
# user = User.new(name: 'david', password: 'mUc3m00RsqyRe')
# user.save
# user.authenticate('notright') # => false
#  user.authenticate('mUc3m00RsqyRe') # => user
# user.authenticate('mUc3m00RsqyRe') # => user
def authenticate(unencrypted_password)
BCrypt::Password.new(password_digest) == unencrypted_password && self
end
@ -84,7 +84,7 @@ module ActiveModel
# user.password = nil
# user.password_digest # => nil
# user.password = 'mUc3m00RsqyRe'
# user.password_digest # => "$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/xeUVtMTYqwIvYY76EW5GUqDiP4."
# user.password_digest # => "$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/xeUVtMTYqwIvYY76EW5GUqDiP4."
def password=(unencrypted_password)
unless unencrypted_password.blank?
@password = unencrypted_password

View file

@ -2,7 +2,7 @@ require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/slice'
module ActiveModel
# == Active Model Serialization
# == Active \Model \Serialization
#
# Provides a basic serialization to a serializable_hash for your object.
#

View file

@ -1,6 +1,6 @@
module ActiveModel
# == Active Model Translation
# == Active \Model \Translation
#
# Provides integration between your object and the Rails internationalization
# (i18n) framework.

View file

@ -7,7 +7,7 @@ require 'active_model/validator'
module ActiveModel
# == Active Model Validations
# == Active \Model Validations
#
# Provides a full validation framework to your objects.
#

View file

@ -1,6 +1,6 @@
module ActiveModel
# == Active Model Acceptance Validator
# == Active \Model Acceptance \Validator
module Validations
class AcceptanceValidator < EachValidator #:nodoc:
def initialize(options)

View file

@ -2,7 +2,7 @@ require 'active_support/callbacks'
module ActiveModel
module Validations
# == Active Model Validation callbacks
# == Active \Model Validation Callbacks
#
# Provides an interface for any class to have +before_validation+ and
# +after_validation+ callbacks.

View file

@ -1,6 +1,6 @@
module ActiveModel
# == Active Model Confirmation Validator
# == Active \Model Confirmation \Validator
module Validations
class ConfirmationValidator < EachValidator #:nodoc:
def validate_each(record, attribute, value)

View file

@ -2,7 +2,7 @@ require "active_model/validations/clusivity"
module ActiveModel
# == Active Model Exclusion Validator
# == Active \Model Exclusion \Validator
module Validations
class ExclusionValidator < EachValidator #:nodoc:
include Clusivity

View file

@ -2,7 +2,7 @@ require "active_model/validations/clusivity"
module ActiveModel
# == Active Model Inclusion Validator
# == Active \Model Inclusion \Validator
module Validations
class InclusionValidator < EachValidator #:nodoc:
include Clusivity

View file

@ -1,8 +1,8 @@
module ActiveModel
# == Active Model Length Validator
# == Active \Model Length \Validator
module Validations
class LengthValidator < EachValidator #:nodoc:
class LengthValidator < EachValidator # :nodoc:
MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze
CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze
@ -37,7 +37,7 @@ module ActiveModel
value = tokenize(value)
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
errors_options = options.except(*RESERVED_OPTIONS)
CHECKS.each do |key, validity_check|
next unless check_value = options[key]
next if value_length.send(validity_check, check_value)

View file

@ -1,8 +1,8 @@
module ActiveModel
# == Active Model Numericality Validator
# == Active \Model Numericality \Validator
module Validations
class NumericalityValidator < EachValidator #:nodoc:
class NumericalityValidator < EachValidator # :nodoc:
CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=,
:equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=,
:odd => :odd?, :even => :even?, :other_than => :!= }.freeze

View file

@ -1,9 +1,9 @@
module ActiveModel
# == Active Model Presence Validator
# == Active \Model Presence \Validator
module Validations
class PresenceValidator < EachValidator #:nodoc:
class PresenceValidator < EachValidator # :nodoc:
def validate(record)
record.errors.add_on_blank(attributes, options)
end

View file

@ -2,7 +2,7 @@ require "active_support/core_ext/module/anonymous"
module ActiveModel
# == Active Model Validator
# == Active \Model \Validator
#
# A simple base class that can be used along with
# ActiveModel::Validations::ClassMethods.validates_with

View file

@ -2,7 +2,7 @@ require 'active_support/core_ext/enumerable'
module ActiveRecord
# = Active Record Attribute Methods
module AttributeMethods #:nodoc:
module AttributeMethods
extend ActiveSupport::Concern
include ActiveModel::AttributeMethods
@ -20,7 +20,7 @@ module ActiveRecord
module ClassMethods
# Generates all the attribute related methods for columns in the database
# accessors, mutators and query methods.
def define_attribute_methods
def define_attribute_methods # :nodoc:
# Use a mutex; we don't want two thread simaltaneously trying to define
# attribute methods.
@attribute_methods_mutex.synchronize do
@ -31,15 +31,29 @@ module ActiveRecord
end
end
def attribute_methods_generated?
def attribute_methods_generated? # :nodoc:
@attribute_methods_generated ||= false
end
def undefine_attribute_methods
def undefine_attribute_methods # :nodoc:
super if attribute_methods_generated?
@attribute_methods_generated = false
end
# Raises a <tt>ActiveRecord::DangerousAttributeError</tt> exception when an
# \Active \Record method is defined in the model, otherwise +false+.
#
# class Person < ActiveRecord::Base
# def save
# 'already defined by Active Record'
# end
# end
#
# Person.instance_method_already_implemented?(:save)
# # => ActiveRecord::DangerousAttributeError: save is defined by ActiveRecord
#
# Person.instance_method_already_implemented?(:name)
# # => false
def instance_method_already_implemented?(method_name)
if dangerous_attribute_method?(method_name)
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord"
@ -56,11 +70,11 @@ module ActiveRecord
# A method name is 'dangerous' if it is already defined by Active Record, but
# not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
def dangerous_attribute_method?(name)
def dangerous_attribute_method?(name) # :nodoc:
method_defined_within?(name, Base)
end
def method_defined_within?(name, klass, sup = klass.superclass)
def method_defined_within?(name, klass, sup = klass.superclass) # :nodoc:
if klass.method_defined?(name) || klass.private_method_defined?(name)
if sup.method_defined?(name) || sup.private_method_defined?(name)
klass.instance_method(name).owner != sup.instance_method(name).owner
@ -72,13 +86,27 @@ module ActiveRecord
end
end
# Returns +true+ if +attribute+ is an attribute method and table exists,
# +false+ otherwise.
#
# class Person < ActiveRecord::Base
# end
#
# Person.attribute_method?('name') # => true
# Person.attribute_method?(:age=) # => true
# Person.attribute_method?(:nothing) # => false
def attribute_method?(attribute)
super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, '')))
end
# Returns an array of column names as strings if it's not
# an abstract class and table exists.
# Otherwise it returns an empty array.
# Returns an array of column names as strings if it's not an abstract class and
# table exists. Otherwise it returns an empty array.
#
# class Person < ActiveRecord::Base
# end
#
# Person.attribute_names
# # => ["id", "created_at", "updated_at", "name", "age"]
def attribute_names
@attribute_names ||= if !abstract_class? && table_exists?
column_names
@ -90,7 +118,7 @@ module ActiveRecord
# If we haven't generated any methods yet, generate them, then
# see if we've created the method we're looking for.
def method_missing(method, *args, &block)
def method_missing(method, *args, &block) # :nodoc:
unless self.class.attribute_methods_generated?
self.class.define_attribute_methods
@ -104,7 +132,7 @@ module ActiveRecord
end
end
def attribute_missing(match, *args, &block)
def attribute_missing(match, *args, &block) # :nodoc:
if self.class.columns_hash[match.attr_name]
ActiveSupport::Deprecation.warn(
"The method `#{match.method_name}', matching the attribute `#{match.attr_name}' has " \
@ -118,22 +146,60 @@ module ActiveRecord
super
end
# A Person object with a name attribute can ask <tt>person.respond_to?(:name)</tt>,
# <tt>person.respond_to?(:name=)</tt>, and <tt>person.respond_to?(:name?)</tt>
# which will all return +true+. It also define the attribute methods if they have
# not been generated.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person.respond_to(:name) # => true
# person.respond_to(:name=) # => true
# person.respond_to(:name?) # => true
# person.respond_to('age') # => true
# person.respond_to('age=') # => true
# person.respond_to('age?') # => true
# person.respond_to(:nothing) # => false
def respond_to?(name, include_private = false)
self.class.define_attribute_methods unless self.class.attribute_methods_generated?
super
end
# Returns true if the given attribute is in the attributes hash
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person.has_attribute?(:name) # => true
# person.has_attribute?('age') # => true
# person.has_attribute?(:nothing) # => false
def has_attribute?(attr_name)
@attributes.has_key?(attr_name.to_s)
end
# Returns an array of names for the attributes available on this object.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person.attribute_names
# # => ["id", "created_at", "updated_at", "name", "age"]
def attribute_names
@attributes.keys
end
# Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.create(name: 'Francesco', age: 22)
# person.attributes
# # => {"id"=>3, "created_at"=>Sun, 21 Oct 2012 04:53:04, "updated_at"=>Sun, 21 Oct 2012 04:53:04, "name"=>"Francesco", "age"=>22}
def attributes
attribute_names.each_with_object({}) { |name, attrs|
attrs[name] = read_attribute(name)
@ -146,7 +212,7 @@ module ActiveRecord
# <tt>:db</tt> format. Other attributes return the value of
# <tt>#inspect</tt> without modification.
#
# person = Person.create!(:name => "David Heinemeier Hansson " * 3)
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
#
# person.attribute_for_inspect(:name)
# # => '"David Heinemeier Hansson David Heinemeier Hansson D..."'
@ -165,14 +231,34 @@ module ActiveRecord
end
end
# Returns true if the specified +attribute+ has been set by the user or by a database load and is neither
# nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings).
# Returns +true+ if the specified +attribute+ has been set by the user or by a
# database load and is neither +nil+ nor <tt>empty?</tt> (the latter only applies
# to objects that respond to <tt>empty?</tt>, most notably Strings). Otherwise, +false+.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new(name: '')
# person.attribute_present?(:name) # => false
# person.name = 'Francesco'
# person.attribute_present?(:name) # => true
def attribute_present?(attribute)
value = read_attribute(attribute)
!value.nil? && !(value.respond_to?(:empty?) && value.empty?)
end
# Returns the column object for the named attribute.
# Returns the column object for the named attribute. Returns +nil+ if the
# named attribute not exists.
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
# # => #<ActiveRecord::ConnectionAdapters::SQLite3Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
#
# person.column_for_attribute(:nothing)
# # => nil
def column_for_attribute(name)
# FIXME: should this return a null object for columns that don't exist?
self.class.columns_hash[name.to_s]
@ -180,42 +266,57 @@ module ActiveRecord
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
# (Alias for the protected read_attribute method).
# (Alias for the protected <tt>read_attribute</tt> method).
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new(name: 'Francesco', age: '22'
# person[:name] # => "Francesco"
# person[:age] # => 22
def [](attr_name)
read_attribute(attr_name)
end
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
# (Alias for the protected write_attribute method).
# (Alias for the protected <tt>write_attribute</tt> method).
#
# class Person < ActiveRecord::Base
# end
#
# person = Person.new
# person[:age] = '22'
# person[:age] # => 22
# person[:age] # => Fixnum
def []=(attr_name, value)
write_attribute(attr_name, value)
end
protected
def clone_attributes(reader_method = :read_attribute, attributes = {})
def clone_attributes(reader_method = :read_attribute, attributes = {}) # :nodoc:
attribute_names.each do |name|
attributes[name] = clone_attribute_value(reader_method, name)
end
attributes
end
def clone_attribute_value(reader_method, attribute_name)
def clone_attribute_value(reader_method, attribute_name) # :nodoc:
value = send(reader_method, attribute_name)
value.duplicable? ? value.clone : value
rescue TypeError, NoMethodError
value
end
def arel_attributes_with_values_for_create(attribute_names)
def arel_attributes_with_values_for_create(attribute_names) # :nodoc:
arel_attributes_with_values(attributes_for_create(attribute_names))
end
def arel_attributes_with_values_for_update(attribute_names)
def arel_attributes_with_values_for_update(attribute_names) # :nodoc:
arel_attributes_with_values(attributes_for_update(attribute_names))
end
def attribute_method?(attr_name)
def attribute_method?(attr_name) # :nodoc:
defined?(@attributes) && @attributes.include?(attr_name)
end

View file

@ -200,6 +200,42 @@ module ActiveRecord
# Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
# methods on the model, which are called last.
#
# == Ordering callbacks
#
# Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
# callback (+log_children+ in this case) should be executed before the children get destroyed by the +dependent: destroy+ option.
#
# Let's look at the code below:
#
# class Topic < ActiveRecord::Base
# has_many :children, dependent: destroy
#
# before_destroy :log_children
#
# def log_children
# children.each do |child|
# # Some child processing
# end
# end
# end
#
# In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
# because the +destroy+ callback gets executed first. You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
#
# class Topic < ActiveRecord::Base
# has_many :children, dependent: destroy
#
# before_destroy :log_children, prepend: true
#
# def log_children
# children.each do |child|
# # Some child processing
# end
# end
# end
#
# This way, the +before_destroy+ gets executed before the <tt>dependent: destroy</tt> is called, and the data is still available.
#
# == Transactions
#
# The entire callback chain of a +save+, <tt>save!</tt>, or +destroy+ call runs

View file

@ -4,8 +4,8 @@ require 'rails/generators/active_model'
require 'active_record'
module ActiveRecord
module Generators
class Base < Rails::Generators::NamedBase #:nodoc:
module Generators # :nodoc:
class Base < Rails::Generators::NamedBase # :nodoc:
include Rails::Generators::Migration
# Set the current directory as base for the inherited generators.
@ -14,7 +14,7 @@ module ActiveRecord
end
# Implement the required interface for Rails::Generators::Migration.
def self.next_migration_number(dirname) #:nodoc:
def self.next_migration_number(dirname)
next_migration_number = current_migration_number(dirname) + 1
ActiveRecord::Migration.next_migration_number(next_migration_number)
end

View file

@ -1,8 +1,8 @@
require 'rails/generators/active_record'
module ActiveRecord
module Generators
class MigrationGenerator < Base
module Generators # :nodoc:
class MigrationGenerator < Base # :nodoc:
argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
def create_migration_file
@ -42,7 +42,7 @@ module ActiveRecord
attribute.name.singularize.foreign_key
end.to_sym
end
private
def validate_file_name!

View file

@ -1,8 +1,8 @@
require 'rails/generators/active_record'
module ActiveRecord
module Generators
class ModelGenerator < Base
module Generators # :nodoc:
class ModelGenerator < Base # :nodoc:
argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
check_class_collision

View file

@ -1,8 +1,8 @@
require 'rails/generators/active_record'
module ActiveRecord
module Generators
class ObserverGenerator < Base
module Generators # :nodoc:
class ObserverGenerator < Base # :nodoc:
check_class_collision :suffix => "Observer"
def create_observer_file

View file

@ -23,7 +23,7 @@ class Array
# The last point is particularly worth comparing for some enumerables:
#
# Array(foo: :bar) # => [[:foo, :bar]]
# Array.wrap(foo: :bar) # => [{:foo => :bar}]
# Array.wrap(foo: :bar) # => [{foo: :bar}]
#
# There's also a related idiom that uses the splat operator:
#

View file

@ -131,7 +131,7 @@ class Hash
else
xml_value = Hash[value.map { |k,v| [k, typecast_xml_value(v)] }]
# Turn { :files => { :file => #<StringIO> } } into { :files => #<StringIO> } so it is compatible with
# Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
# how multipart uploaded files from HTML appear
xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
end

View file

@ -21,7 +21,7 @@ class Hash
# Returns a hash containing the removed key/value pairs.
#
# { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)
# # => {:c => 3, :d => 4}
# # => {c: 3, d: 4}
def slice!(*keys)
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
omit = slice(*self.keys - keys)

View file

@ -2,13 +2,13 @@ require 'active_support/deprecation/method_wrappers'
class Module
# deprecate :foo
# deprecate :bar => 'message'
# deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
# deprecate bar: 'message'
# deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'
#
# You can also use custom deprecator instance:
#
# deprecate :foo, :deprecator => MyLib::Deprecator.new
# deprecate :foo, :bar => "warning!", :deprecator => MyLib::Deprecator.new
# deprecate :foo, deprecator: MyLib::Deprecator.new
# deprecate :foo, bar: "warning!", deprecator: MyLib::Deprecator.new
#
# \Custom deprecators must respond to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt>
# method where you can implement your custom warning behavior.

View file

@ -135,7 +135,7 @@ class Time
# Returns a new Time representing the start of the day (0:00)
def beginning_of_day
#(self - seconds_since_midnight).change(:usec => 0)
#(self - seconds_since_midnight).change(usec: 0)
change(:hour => 0)
end
alias :midnight :beginning_of_day

View file

@ -12,8 +12,8 @@ Blog::Application.routes.draw do
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
# match 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# This route can be invoked with purchase_url(id: product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# resources :products
@ -40,7 +40,7 @@ Blog::Application.routes.draw do
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', :on => :collection
# get 'recent', on: :collection
# end
# end

View file

@ -3,8 +3,8 @@ require 'rails/performance_test_help'
class BrowsingTest < ActionDispatch::PerformanceTest
# Refer to the documentation for all available options
# self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory],
# :output => 'tmp/performance', :formats => [:flat] }
# self.profile_options = { runs: 5, metrics: [:wall_time, :memory],
# output: 'tmp/performance', formats: [:flat] }
def test_homepage
get '/'

View file

@ -51,7 +51,7 @@ We can see how it works by looking at some `rails console` output:
```ruby
$ rails console
>> p = Person.new(:name => "John Doe")
>> p = Person.new(name: "John Doe")
=> #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
>> p.new_record?
=> true
@ -95,9 +95,9 @@ The following methods skip validations, and will save the object to the database
* `update_columns`
* `update_counters`
Note that `save` also has the ability to skip validations if passed `:validate => false` as argument. This technique should be used with caution.
Note that `save` also has the ability to skip validations if passed `validate: false` as argument. This technique should be used with caution.
* `save(:validate => false)`
* `save(validate: false)`
### `valid?` and `invalid?`
@ -105,11 +105,11 @@ To verify whether or not an object is valid, Rails uses the `valid?` method. You
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
validates :name, presence: true
end
Person.create(:name => "John Doe").valid? # => true
Person.create(:name => nil).valid? # => false
Person.create(name: "John Doe").valid? # => true
Person.create(name: nil).valid? # => false
```
After Active Record has performed validations, any errors found can be accessed through the `errors` instance method, which returns a collection of errors. By definition, an object is valid if this collection is empty after running validations.
@ -118,7 +118,7 @@ Note that an object instantiated with `new` will not report errors even if it's
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
validates :name, presence: true
end
>> p = Person.new
@ -129,12 +129,12 @@ end
>> p.valid?
#=> false
>> p.errors
#=> {:name=>["can't be blank"]}
#=> {name:["can't be blank"]}
>> p = Person.create
#=> #<Person id: nil, name: nil>
>> p.errors
#=> {:name=>["can't be blank"]}
#=> {name:["can't be blank"]}
>> p.save
#=> false
@ -156,7 +156,7 @@ This method is only useful _after_ validations have been run, because it only in
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
validates :name, presence: true
end
>> Person.new.errors[:name].any? # => false
@ -180,7 +180,7 @@ Validates that a checkbox on the user interface was checked when a form was subm
```ruby
class Person < ActiveRecord::Base
validates :terms_of_service, :acceptance => true
validates :terms_of_service, acceptance: true
end
```
@ -190,7 +190,7 @@ It can receive an `:accept` option, which determines the value that will be cons
```ruby
class Person < ActiveRecord::Base
validates :terms_of_service, :acceptance => { :accept => 'yes' }
validates :terms_of_service, acceptance: { accept: 'yes' }
end
```
@ -217,7 +217,7 @@ You should use this helper when you have two text fields that should receive exa
```ruby
class Person < ActiveRecord::Base
validates :email, :confirmation => true
validates :email, confirmation: true
end
```
@ -232,8 +232,8 @@ This check is performed only if `email_confirmation` is not `nil`. To require co
```ruby
class Person < ActiveRecord::Base
validates :email, :confirmation => true
validates :email_confirmation, :presence => true
validates :email, confirmation: true
validates :email_confirmation, presence: true
end
```
@ -245,8 +245,8 @@ This helper validates that the attributes' values are not included in a given se
```ruby
class Account < ActiveRecord::Base
validates :subdomain, :exclusion => { :in => %w(www us ca jp),
:message => "Subdomain %{value} is reserved." }
validates :subdomain, exclusion: { in: %w(www us ca jp),
message: "Subdomain %{value} is reserved." }
end
```
@ -260,8 +260,8 @@ This helper validates the attributes' values by testing whether they match a giv
```ruby
class Product < ActiveRecord::Base
validates :legacy_code, :format => { :with => /\A[a-zA-Z]+\z/,
:message => "Only letters allowed" }
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
message: "Only letters allowed" }
end
```
@ -273,8 +273,8 @@ This helper validates that the attributes' values are included in a given set. I
```ruby
class Coffee < ActiveRecord::Base
validates :size, :inclusion => { :in => %w(small medium large),
:message => "%{value} is not a valid size" }
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }
end
```
@ -288,10 +288,10 @@ This helper validates the length of the attributes' values. It provides a variet
```ruby
class Person < ActiveRecord::Base
validates :name, :length => { :minimum => 2 }
validates :bio, :length => { :maximum => 500 }
validates :password, :length => { :in => 6..20 }
validates :registration_number, :length => { :is => 6 }
validates :name, length: { minimum: 2 }
validates :bio, length: { maximum: 500 }
validates :password, length: { in: 6..20 }
validates :registration_number, length: { is: 6 }
end
```
@ -306,8 +306,8 @@ The default error messages depend on the type of length validation being perform
```ruby
class Person < ActiveRecord::Base
validates :bio, :length => { :maximum => 1000,
:too_long => "%{count} characters is the maximum allowed" }
validates :bio, length: { maximum: 1000,
too_long: "%{count} characters is the maximum allowed" }
end
```
@ -315,12 +315,12 @@ This helper counts characters by default, but you can split the value in a diffe
```ruby
class Essay < ActiveRecord::Base
validates :content, :length => {
:minimum => 300,
:maximum => 400,
:tokenizer => lambda { |str| str.scan(/\w+/) },
:too_short => "must have at least %{count} words",
:too_long => "must have at most %{count} words"
validates :content, length: {
minimum: 300,
maximum: 400,
tokenizer: lambda { |str| str.scan(/\w+/) },
too_short: "must have at least %{count} words",
too_long: "must have at most %{count} words"
}
end
```
@ -345,8 +345,8 @@ WARNING. Note that the regular expression above allows a trailing newline charac
```ruby
class Player < ActiveRecord::Base
validates :points, :numericality => true
validates :games_played, :numericality => { :only_integer => true }
validates :points, numericality: true
validates :games_played, numericality: { only_integer: true }
end
```
@ -368,7 +368,7 @@ This helper validates that the specified attributes are not empty. It uses the `
```ruby
class Person < ActiveRecord::Base
validates :name, :login, :email, :presence => true
validates :name, :login, :email, presence: true
end
```
@ -377,13 +377,13 @@ If you want to be sure that an association is present, you'll need to test wheth
```ruby
class LineItem < ActiveRecord::Base
belongs_to :order
validates :order_id, :presence => true
validates :order_id, presence: true
end
```
If you validate the presence of an object associated via a `has_one` or `has_many` relationship, it will check that the object is neither `blank?` nor `marked_for_destruction?`.
Since `false.blank?` is true, if you want to validate the presence of a boolean field you should use `validates :field_name, :inclusion => { :in => [true, false] }`.
Since `false.blank?` is true, if you want to validate the presence of a boolean field you should use `validates :field_name, inclusion: { in: [true, false] }`.
The default error message is "_can't be empty_".
@ -393,7 +393,7 @@ This helper validates that the attribute's value is unique right before the obje
```ruby
class Account < ActiveRecord::Base
validates :email, :uniqueness => true
validates :email, uniqueness: true
end
```
@ -403,8 +403,8 @@ There is a `:scope` option that you can use to specify other attributes that are
```ruby
class Holiday < ActiveRecord::Base
validates :name, :uniqueness => { :scope => :year,
:message => "should happen once per year" }
validates :name, uniqueness: { scope: :year,
message: "should happen once per year" }
end
```
@ -412,7 +412,7 @@ There is also a `:case_sensitive` option that you can use to define whether the
```ruby
class Person < ActiveRecord::Base
validates :name, :uniqueness => { :case_sensitive => false }
validates :name, uniqueness: { case_sensitive: false }
end
```
@ -448,7 +448,7 @@ Like all other validations, `validates_with` takes the `:if`, `:unless` and `:on
```ruby
class Person < ActiveRecord::Base
validates_with GoodnessValidator, :fields => [:first_name, :last_name]
validates_with GoodnessValidator, fields: [:first_name, :last_name]
end
class GoodnessValidator < ActiveModel::Validator
@ -485,8 +485,8 @@ The `:allow_nil` option skips the validation when the value being validated is `
```ruby
class Coffee < ActiveRecord::Base
validates :size, :inclusion => { :in => %w(small medium large),
:message => "%{value} is not a valid size" }, :allow_nil => true
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }, allow_nil: true
end
```
@ -498,7 +498,7 @@ The `:allow_blank` option is similar to the `:allow_nil` option. This option wil
```ruby
class Topic < ActiveRecord::Base
validates :title, :length => { :is => 5 }, :allow_blank => true
validates :title, length: { is: 5 }, allow_blank: true
end
Topic.create("title" => "").valid? # => true
@ -513,18 +513,18 @@ As you've already seen, the `:message` option lets you specify the message that
### `:on`
The `:on` option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use `:on => :create` to run the validation only when a new record is created or `:on => :update` to run the validation only when a record is updated.
The `:on` option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use `on: :create` to run the validation only when a new record is created or `on: :update` to run the validation only when a record is updated.
```ruby
class Person < ActiveRecord::Base
# it will be possible to update email with a duplicated value
validates :email, :uniqueness => true, :on => :create
validates :email, uniqueness: true, on: :create
# it will be possible to create the record with a non-numerical age
validates :age, :numericality => true, :on => :update
validates :age, numericality: true, on: :update
# the default (validates on both create and update)
validates :name, :presence => true, :on => :save
validates :name, presence: true, on: :save
end
```
@ -535,7 +535,7 @@ You can also specify validations to be strict and raise `ActiveModel::StrictVali
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => { :strict => true }
validates :name, presence: { strict: true }
end
Person.new.valid? #=> ActiveModel::StrictValidationFailed: Name can't be blank
@ -545,7 +545,7 @@ There is also an ability to pass custom exception to `:strict` option
```ruby
class Person < ActiveRecord::Base
validates :token, :presence => true, :uniqueness => true, :strict => TokenGenerationException
validates :token, presence: true, uniqueness: true, strict: TokenGenerationException
end
Person.new.valid? #=> TokenGenerationException: Token can't be blank
@ -562,7 +562,7 @@ You can associate the `:if` and `:unless` options with a symbol corresponding to
```ruby
class Order < ActiveRecord::Base
validates :card_number, :presence => true, :if => :paid_with_card?
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
@ -576,7 +576,7 @@ You can also use a string that will be evaluated using `eval` and needs to conta
```ruby
class Person < ActiveRecord::Base
validates :surname, :presence => true, :if => "name.nil?"
validates :surname, presence: true, if: "name.nil?"
end
```
@ -586,8 +586,8 @@ Finally, it's possible to associate `:if` and `:unless` with a `Proc` object whi
```ruby
class Account < ActiveRecord::Base
validates :password, :confirmation => true,
:unless => Proc.new { |a| a.password.blank? }
validates :password, confirmation: true,
unless: Proc.new { |a| a.password.blank? }
end
```
@ -597,14 +597,14 @@ Sometimes it is useful to have multiple validations use one condition, it can be
```ruby
class User < ActiveRecord::Base
with_options :if => :is_admin? do |admin|
admin.validates :password, :length => { :minimum => 10 }
admin.validates :email, :presence => true
with_options if: :is_admin? do |admin|
admin.validates :password, length: { minimum: 10 }
admin.validates :email, presence: true
end
end
```
All validations inside of `with_options` block will have automatically passed the condition `:if => :is_admin?`
All validations inside of `with_options` block will have automatically passed the condition `if: :is_admin?`
### Combining validation conditions
@ -612,9 +612,9 @@ On the other hand, when multiple conditions define whether or not a validation s
```ruby
class Computer < ActiveRecord::Base
validates :mouse, :presence => true,
:if => ["market.retail?", :desktop?]
:unless => Proc.new { |c| c.trackpad.present? }
validates :mouse, presence: true,
if: ["market.retail?", :desktop?]
unless: Proc.new { |c| c.trackpad.present? }
end
```
@ -656,7 +656,7 @@ class EmailValidator < ActiveModel::EachValidator
end
class Person < ActiveRecord::Base
validates :email, :presence => true, :email => true
validates :email, presence: true, email: true
end
```
@ -691,7 +691,7 @@ By default such validations will run every time you call `valid?`. It is also po
```ruby
class Invoice < ActiveRecord::Base
validate :active_customer, :on => :create
validate :active_customer, on: :create
def active_customer
errors.add(:customer_id, "is not active") unless customer.active?
@ -704,7 +704,7 @@ You can even create your own validation helpers and reuse them in several differ
```ruby
ActiveRecord::Base.class_eval do
def self.validates_as_choice(attr_name, n, options={})
validates attr_name, :inclusion => { { :in => 1..n }.merge!(options) }
validates attr_name, inclusion: { { in: 1..n }.merge!(options) }
end
end
```
@ -730,15 +730,15 @@ Returns an instance of the class `ActiveModel::Errors` containing all errors. Ea
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new
person.valid? # => false
person.errors
# => {:name => ["can't be blank", "is too short (minimum is 3 characters)"]}
# => {name: ["can't be blank", "is too short (minimum is 3 characters)"]}
person = Person.new(:name => "John Doe")
person = Person.new(name: "John Doe")
person.valid? # => true
person.errors # => []
```
@ -749,14 +749,14 @@ person.errors # => []
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new(:name => "John Doe")
person = Person.new(name: "John Doe")
person.valid? # => true
person.errors[:name] # => []
person = Person.new(:name => "JD")
person = Person.new(name: "JD")
person.valid? # => false
person.errors[:name] # => ["is too short (minimum is 3 characters)"]
@ -777,7 +777,7 @@ class Person < ActiveRecord::Base
end
end
person = Person.create(:name => "!@#")
person = Person.create(name: "!@#")
person.errors[:name]
# => ["cannot contain the characters !@#%*()_-+="]
@ -795,7 +795,7 @@ Another way to do this is using `[]=` setter
end
end
person = Person.create(:name => "!@#")
person = Person.create(name: "!@#")
person.errors[:name]
# => ["cannot contain the characters !@#%*()_-+="]
@ -822,7 +822,7 @@ The `clear` method is used when you intentionally want to clear all the messages
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new
@ -845,14 +845,14 @@ The `size` method returns the total number of error messages for the object.
```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
validates :name, presence: true, length: { minimum: 3 }
end
person = Person.new
person.valid? # => false
person.errors.size # => 2
person = Person.new(:name => "Andrea", :email => "andrea@example.com")
person = Person.new(name: "Andrea", email: "andrea@example.com")
person.valid? # => true
person.errors.size # => 0
```
@ -876,8 +876,8 @@ When creating a form with the `form_for` helper, you can use the `error_messages
```ruby
class Product < ActiveRecord::Base
validates :description, :value, :presence => true
validates :value, :numericality => true, :allow_nil => true
validates :description, :value, presence: true
validates :value, numericality: true, allow_nil: true
end
```
@ -915,9 +915,9 @@ The displayed text for each error message will always be formed by the capitaliz
Both the `form.error_messages` and the `error_messages_for` helpers accept options that let you customize the `div` element that holds the messages, change the header text, change the message below the header, and specify the tag used for the header element. For example,
```erb
<%= f.error_messages :header_message => "Invalid product!",
:message => "You'll need to fix the following fields:",
:header_tag => :h3 %>
<%= f.error_messages header_message: "Invalid product!",
message: "You'll need to fix the following fields:",
header_tag: :h3 %>
```
results in:
@ -973,7 +973,7 @@ In order to use the available callbacks, you need to register them. You can impl
```ruby
class User < ActiveRecord::Base
validates :login, :email, :presence => true
validates :login, :email, presence: true
before_validation :ensure_login_has_a_value
@ -990,7 +990,7 @@ The macro-style class methods can also receive a block. Consider using this styl
```ruby
class User < ActiveRecord::Base
validates :login, :email, :presence => true
validates :login, :email, presence: true
before_create do |user|
user.name = user.login.capitalize if user.name.blank?
@ -999,12 +999,13 @@ end
```
Callbacks can also be registered to only fire on certain lifecycle events:
<ruby>
```ruby
class User < ActiveRecord::Base
before_validation :normalize_name, :on => :create
before_validation :normalize_name, on: :create
# :on takes an array as well
after_validation :set_location, :on => [ :create, :update ]
after_validation :set_location, on: [ :create, :update ]
protected
def normalize_name
@ -1015,7 +1016,7 @@ class User < ActiveRecord::Base
self.location = LocationService.query(self)
end
end
</ruby>
```
It is considered good practice to declare callback methods as protected or private. If left public, they can be called from outside of the model and violate the principle of object encapsulation.
@ -1096,7 +1097,7 @@ The following methods trigger callbacks:
* `increment!`
* `save`
* `save!`
* `save(:validate => false)`
* `save(validate: false)`
* `toggle!`
* `update`
* `update_attribute`
@ -1109,14 +1110,16 @@ Additionally, the `after_find` callback is triggered by the following finder met
* `all`
* `first`
* `find`
* `find_all_by_<em>attribute</em>`
* `find_by_<em>attribute</em>`
* `find_by_<em>attribute</em>!`
* `find_all_by_*`
* `find_by_*`
* `find_by_*!`
* `find_by_sql`
* `last`
The `after_initialize` callback is triggered every time a new object of the class is initialized.
NOTE: The `find_all_by_*`, `find_by_*` and `find_by_*!` methods are dynamic finders generated automatically for every attribute. Learn more about them at the [Dynamic finders section](active_record_querying.html#dynamic-finders)
Skipping Callbacks
------------------
@ -1151,7 +1154,7 @@ Callbacks work through model relationships, and can even be defined by them. Sup
```ruby
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
has_many :posts, dependent: :destroy
end
class Post < ActiveRecord::Base
@ -1182,7 +1185,7 @@ You can associate the `:if` and `:unless` options with a symbol corresponding to
```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => :paid_with_card?
before_save :normalize_card_number, if: :paid_with_card?
end
```
@ -1192,7 +1195,7 @@ You can also use a string that will be evaluated using `eval` and hence needs to
```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => "paid_with_card?"
before_save :normalize_card_number, if: "paid_with_card?"
end
```
@ -1203,7 +1206,7 @@ Finally, it is possible to associate `:if` and `:unless` with a `Proc` object. T
```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number,
:if => Proc.new { |order| order.paid_with_card? }
if: Proc.new { |order| order.paid_with_card? }
end
```
@ -1213,8 +1216,8 @@ When writing conditional callbacks, it is possible to mix both `:if` and `:unles
```ruby
class Comment < ActiveRecord::Base
after_create :send_email_to_author, :if => :author_wants_emails?,
:unless => Proc.new { |comment| comment.post.ignore_comments? }
after_create :send_email_to_author, if: :author_wants_emails?,
unless: Proc.new { |comment| comment.post.ignore_comments? }
end
```

View file

@ -358,13 +358,13 @@ Arrays return the result of applying `to_query` to each element with `_key_[]` a
Hashes also respond to `to_query` but with a different signature. If no argument is passed a call generates a sorted series of key/value assignments calling `to_query(key)` on its values. Then it joins the result with "&":
```ruby
{:c => 3, :b => 2, :a => 1}.to_query # => "a=1&b=2&c=3"
{c: 3, b: 2, a: 1}.to_query # => "a=1&b=2&c=3"
```
The method `Hash#to_query` accepts an optional namespace for the keys:
```ruby
{:id => 89, :name => "John Smith"}.to_query('user')
{id: 89, name: "John Smith"}.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
```
@ -378,10 +378,10 @@ Given a default options hash, `with_options` yields a proxy object to a block. W
```ruby
class Account < ActiveRecord::Base
has_many :customers, :dependent => :destroy
has_many :products, :dependent => :destroy
has_many :invoices, :dependent => :destroy
has_many :expenses, :dependent => :destroy
has_many :customers, dependent: :destroy
has_many :products, dependent: :destroy
has_many :invoices, dependent: :destroy
has_many :expenses, dependent: :destroy
end
```
@ -389,7 +389,7 @@ this way:
```ruby
class Account < ActiveRecord::Base
with_options :dependent => :destroy do |assoc|
with_options dependent: :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
@ -401,9 +401,9 @@ end
That idiom may convey _grouping_ to the reader as well. For example, say you want to send a newsletter whose language depends on the user. Somewhere in the mailer you could group locale-dependent bits like this:
```ruby
I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
subject i18n.t :subject
body i18n.t :body, :user_name => user.name
body i18n.t :body, user_name: user.name
end
```
@ -892,7 +892,7 @@ That is what `delegate` does for you:
class User < ActiveRecord::Base
has_one :profile
delegate :name, :to => :profile
delegate :name, to: :profile
end
```
@ -903,17 +903,17 @@ The method must be public in the target.
The `delegate` macro accepts several methods:
```ruby
delegate :name, :age, :address, :twitter, :to => :profile
delegate :name, :age, :address, :twitter, to: :profile
```
When interpolated into a string, the `:to` option should become an expression that evaluates to the object the method is delegated to. Typically a string or symbol. Such an expression is evaluated in the context of the receiver:
```ruby
# delegates to the Rails constant
delegate :logger, :to => :Rails
delegate :logger, to: :Rails
# delegates to the receiver's class
delegate :table_name, :to => 'self.class'
delegate :table_name, to: 'self.class'
```
WARNING: If the `:prefix` option is `true` this is less generic, see below.
@ -921,7 +921,7 @@ WARNING: If the `:prefix` option is `true` this is less generic, see below.
By default, if the delegation raises `NoMethodError` and the target is `nil` the exception is propagated. You can ask that `nil` is returned instead with the `:allow_nil` option:
```ruby
delegate :name, :to => :profile, :allow_nil => true
delegate :name, to: :profile, allow_nil: true
```
With `:allow_nil` the call `user.name` returns `nil` if the user has no profile.
@ -929,7 +929,7 @@ With `:allow_nil` the call `user.name` returns `nil` if the user has no profile.
The option `:prefix` adds a prefix to the name of the generated method. This may be handy for example to get a better name:
```ruby
delegate :street, :to => :address, :prefix => true
delegate :street, to: :address, prefix: true
```
The previous example generates `address_street` rather than `street`.
@ -939,7 +939,7 @@ WARNING: Since in this case the name of the generated method is composed of the
A custom prefix may also be configured:
```ruby
delegate :size, :to => :attachment, :prefix => :avatar
delegate :size, to: :attachment, prefix: :avatar
```
In the previous example the macro generates `avatar_size` rather than `size`.
@ -1003,10 +1003,10 @@ For example `ActionMailer::Base` defines:
```ruby
class_attribute :default_params
self.default_params = {
:mime_version => "1.0",
:charset => "UTF-8",
:content_type => "text/plain",
:parts_order => [ "text/plain", "text/enriched", "text/html" ]
mime_version: "1.0",
charset: "UTF-8",
content_type: "text/plain",
parts_order: [ "text/plain", "text/enriched", "text/html" ]
}.freeze
```
@ -1028,7 +1028,7 @@ The generation of the writer instance method can be prevented by setting the opt
```ruby
module ActiveRecord
class Base
class_attribute :table_name_prefix, :instance_writer => false
class_attribute :table_name_prefix, instance_writer: false
self.table_name_prefix = ""
end
end
@ -1040,7 +1040,7 @@ The generation of the reader instance method can be prevented by setting the opt
```ruby
class A
class_attribute :x, :instance_reader => false
class_attribute :x, instance_reader: false
end
A.new.x = 1 # NoMethodError
@ -1083,11 +1083,11 @@ The generation of the reader instance method can be prevented by setting `:insta
module A
class B
# No first_name instance reader is generated.
cattr_accessor :first_name, :instance_reader => false
cattr_accessor :first_name, instance_reader: false
# No last_name= instance writer is generated.
cattr_accessor :last_name, :instance_writer => false
cattr_accessor :last_name, instance_writer: false
# No surname instance reader or surname= writer is generated.
cattr_accessor :surname, :instance_accessor => false
cattr_accessor :surname, instance_accessor: false
end
end
```
@ -1260,7 +1260,7 @@ The method `truncate` returns a copy of its receiver truncated after a given `le
Ellipsis can be customized with the `:omission` option:
```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '&hellip;')
"Oh dear! Oh dear! I shall be late!".truncate(20, omission: '&hellip;')
# => "Oh dear! Oh &hellip;"
```
@ -1271,14 +1271,14 @@ Pass a `:separator` to truncate the string at a natural break:
```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18)
# => "Oh dear! Oh dea..."
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ')
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: ' ')
# => "Oh dear! Oh..."
```
The option `:separator` can be a regexp:
```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => /\s/)
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."
```
@ -1757,7 +1757,7 @@ def full_messages
each do |attribute, messages|
...
attr_name = attribute.to_s.gsub('.', '_').humanize
attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
...
end
@ -1861,13 +1861,13 @@ These methods use Time#advance for precise date calculations when using from_now
as well as adding or subtracting their results from a Time object. For example:
```ruby
# equivalent to Time.current.advance(:months => 1)
# equivalent to Time.current.advance(months: 1)
1.month.from_now
# equivalent to Time.current.advance(:years => 2)
# equivalent to Time.current.advance(years: 2)
2.years.from_now
# equivalent to Time.current.advance(:months => 4, :years => 5)
# equivalent to Time.current.advance(months: 4, years: 5)
(4.months + 5.years).from_now
```
@ -1900,13 +1900,13 @@ Produce a string representation of a number as a telephone number:
# => 555-1234
1235551234.to_s(:phone)
# => 123-555-1234
1235551234.to_s(:phone, :area_code => true)
1235551234.to_s(:phone, area_code: true)
# => (123) 555-1234
1235551234.to_s(:phone, :delimiter => " ")
1235551234.to_s(:phone, delimiter: " ")
# => 123 555 1234
1235551234.to_s(:phone, :area_code => true, :extension => 555)
1235551234.to_s(:phone, area_code: true, extension: 555)
# => (123) 555-1234 x 555
1235551234.to_s(:phone, :country_code => 1)
1235551234.to_s(:phone, country_code: 1)
# => +1-123-555-1234
```
@ -1915,7 +1915,7 @@ Produce a string representation of a number as currency:
```ruby
1234567890.50.to_s(:currency) # => $1,234,567,890.50
1234567890.506.to_s(:currency) # => $1,234,567,890.51
1234567890.506.to_s(:currency, :precision => 3) # => $1,234,567,890.506
1234567890.506.to_s(:currency, precision: 3) # => $1,234,567,890.506
```
Produce a string representation of a number as a percentage:
@ -1923,11 +1923,11 @@ Produce a string representation of a number as a percentage:
```ruby
100.to_s(:percentage)
# => 100.000%
100.to_s(:percentage, :precision => 0)
100.to_s(:percentage, precision: 0)
# => 100%
1000.to_s(:percentage, :delimiter => '.', :separator => ',')
1000.to_s(:percentage, delimiter: '.', separator: ',')
# => 1.000,000%
302.24398923423.to_s(:percentage, :precision => 5)
302.24398923423.to_s(:percentage, precision: 5)
# => 302.24399%
```
@ -1936,19 +1936,19 @@ Produce a string representation of a number in delimited form:
```ruby
12345678.to_s(:delimited) # => 12,345,678
12345678.05.to_s(:delimited) # => 12,345,678.05
12345678.to_s(:delimited, :delimiter => ".") # => 12.345.678
12345678.to_s(:delimited, :delimiter => ",") # => 12,345,678
12345678.05.to_s(:delimited, :separator => " ") # => 12,345,678 05
12345678.to_s(:delimited, delimiter: ".") # => 12.345.678
12345678.to_s(:delimited, delimiter: ",") # => 12,345,678
12345678.05.to_s(:delimited, separator: " ") # => 12,345,678 05
```
Produce a string representation of a number rounded to a precision:
```ruby
111.2345.to_s(:rounded) # => 111.235
111.2345.to_s(:rounded, :precision => 2) # => 111.23
13.to_s(:rounded, :precision => 5) # => 13.00000
389.32314.to_s(:rounded, :precision => 0) # => 389
111.2345.to_s(:rounded, :significant => true) # => 111
111.2345.to_s(:rounded, precision: 2) # => 111.23
13.to_s(:rounded, precision: 5) # => 13.00000
389.32314.to_s(:rounded, precision: 0) # => 389
111.2345.to_s(:rounded, significant: true) # => 111
```
Produce a string representation of a number as a human-readable number of bytes:
@ -2042,7 +2042,7 @@ Addition only assumes the elements respond to `+`:
```ruby
[[1, 2], [2, 3], [3, 4]].sum # => [1, 2, 2, 3, 3, 4]
%w(foo bar baz).sum # => "foobarbaz"
{:a => 1, :b => 2, :c => 3}.sum # => [:b, 2, :c, 3, :a, 1]
{a: 1, b: 2, c: 3}.sum # => [:b, 2, :c, 3, :a, 1]
```
The sum of an empty collection is zero by default, but this is customizable:
@ -2176,7 +2176,7 @@ NOTE: Defined in `active_support/core_ext/array/prepend_and_append.rb`.
When the last argument in a method call is a hash, except perhaps for a `&block` argument, Ruby allows you to omit the brackets:
```ruby
User.exists?(:email => params[:email])
User.exists?(email: params[:email])
```
That syntactic sugar is used a lot in Rails to avoid positional arguments where there would be too many, offering instead interfaces that emulate named parameters. In particular it is very idiomatic to use a trailing hash for options.
@ -2305,7 +2305,7 @@ If there's any element that does not belong to the type of the first one the roo
If the receiver is an array of hashes the root element is by default also "objects":
```ruby
[{:a => 1, :b => 2}, {:c => 3}].to_xml
[{a: 1, b: 2}, {c: 3}].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
@ -2326,7 +2326,7 @@ The name of children nodes is by default the name of the root node singularized.
The default XML builder is a fresh instance of `Builder::XmlMarkup`. You can configure your own builder via the `:builder` option. The method also accepts options like `:dasherize` and friends, they are forwarded to the builder:
```ruby
Contributor.limit(2).order(:rank).to_xml(:skip_types => true)
Contributor.limit(2).order(:rank).to_xml(skip_types: true)
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors>
@ -2372,8 +2372,8 @@ This method is similar in purpose to `Kernel#Array`, but there are some differen
The last point is particularly worth comparing for some enumerables:
```ruby
Array.wrap(:foo => :bar) # => [{:foo => :bar}]
Array(:foo => :bar) # => [[:foo, :bar]]
Array.wrap(foo: :bar) # => [{foo: :bar}]
Array(foo: :bar) # => [[:foo, :bar]]
```
There's also a related idiom that uses the splat operator:
@ -2556,8 +2556,8 @@ NOTE: Defined in `active_support/core_ext/hash/conversions.rb`.
Ruby has a built-in method `Hash#merge` that merges two hashes:
```ruby
{:a => 1, :b => 1}.merge(:a => 0, :c => 2)
# => {:a => 0, :b => 1, :c => 2}
{a: 1, b: 1}.merge(a: 0, c: 2)
# => {a: 0, b: 1, c: 2}
```
Active Support defines a few more ways of merging hashes that may be convenient.
@ -2567,19 +2567,19 @@ Active Support defines a few more ways of merging hashes that may be convenient.
In case of collision the key in the hash of the argument wins in `merge`. You can support option hashes with default values in a compact way with this idiom:
```ruby
options = {:length => 30, :omission => "..."}.merge(options)
options = {length: 30, omission: "..."}.merge(options)
```
Active Support defines `reverse_merge` in case you prefer this alternative notation:
```ruby
options = options.reverse_merge(:length => 30, :omission => "...")
options = options.reverse_merge(length: 30, omission: "...")
```
And a bang version `reverse_merge!` that performs the merge in place:
```ruby
options.reverse_merge!(:length => 30, :omission => "...")
options.reverse_merge!(length: 30, omission: "...")
```
WARNING. Take into account that `reverse_merge!` may change the hash in the caller, which may or may not be a good idea.
@ -2601,8 +2601,8 @@ As you can see in the previous example if a key is found in both hashes the valu
Active Support defines `Hash#deep_merge`. In a deep merge, if a key is found in both hashes and their values are hashes in turn, then their _merge_ becomes the value in the resulting hash:
```ruby
{:a => {:b => 1}}.deep_merge(:a => {:c => 2})
# => {:a => {:b => 1, :c => 2}}
{a: {b: 1}}.deep_merge(a: {c: 2})
# => {a: {b: 1, c: 2}}
```
The method `deep_merge!` performs a deep merge in place.
@ -2614,7 +2614,7 @@ NOTE: Defined in `active_support/core_ext/hash/deep_merge.rb`.
The method `Hash.deep_dup` duplicates itself and all keys and values inside recursively with ActiveSupport method `Object#deep_dup`. It works like `Enumerator#each_with_object` with sending `deep_dup` method to each pair inside.
```ruby
hash = { :a => 1, :b => { :c => 2, :d => [3, 4] } }
hash = { a: 1, b: { c: 2, d: [3, 4] } }
dup = hash.deep_dup
dup[:b][:e] = 5
@ -2637,21 +2637,21 @@ The method `diff` returns a hash that represents a diff of the receiver and the
* The rest is just merged.
```ruby
{:a => 1}.diff(:a => 1)
{a: 1}.diff(a: 1)
# => {}, first rule
{:a => 1}.diff(:a => 2)
# => {:a => 1}, second rule
{a: 1}.diff(a: 2)
# => {a: 1}, second rule
{:a => 1}.diff(:b => 2)
# => {:a => 1, :b => 2}, third rule
{a: 1}.diff(b: 2)
# => {a: 1, b: 2}, third rule
{:a => 1, :b => 2, :c => 3}.diff(:b => 1, :c => 3, :d => 4)
# => {:a => 1, :b => 2, :d => 4}, all rules
{a: 1, b: 2, c: 3}.diff(b: 1, c: 3, d: 4)
# => {a: 1, b: 2, d: 4}, all rules
{}.diff({}) # => {}
{:a => 1}.diff({}) # => {:a => 1}
{}.diff(:a => 1) # => {:a => 1}
{a: 1}.diff({}) # => {a: 1}
{}.diff(a: 1) # => {a: 1}
```
An important property of this diff hash is that you can retrieve the original hash by applying `diff` twice:
@ -2671,14 +2671,14 @@ NOTE: Defined in `active_support/core_ext/hash/diff.rb`.
The method `except` returns a hash with the keys in the argument list removed, if present:
```ruby
{:a => 1, :b => 2}.except(:a) # => {:b => 2}
{a: 1, b: 2}.except(:a) # => {b: 2}
```
If the receiver responds to `convert_key`, the method is called on each of the arguments. This allows `except` to play nice with hashes with indifferent access for instance:
```ruby
{:a => 1}.with_indifferent_access.except(:a) # => {}
{:a => 1}.with_indifferent_access.except("a") # => {}
{a: 1}.with_indifferent_access.except(:a) # => {}
{a: 1}.with_indifferent_access.except("a") # => {}
```
The method `except` may come in handy for example when you want to protect some parameter that can't be globally protected with `attr_protected`:
@ -2697,14 +2697,14 @@ NOTE: Defined in `active_support/core_ext/hash/except.rb`.
The method `transform_keys` accepts a block and returns a hash that has applied the block operations to each of the keys in the receiver:
```ruby
{nil => nil, 1 => 1, :a => :a}.transform_keys{ |key| key.to_s.upcase }
{nil => nil, 1 => 1, a: :a}.transform_keys{ |key| key.to_s.upcase }
# => {"" => nil, "A" => :a, "1" => 1}
```
The result in case of collision is undefined:
```ruby
{"a" => 1, :a => 2}.transform_keys{ |key| key.to_s.upcase }
{"a" => 1, a: 2}.transform_keys{ |key| key.to_s.upcase }
# => {"A" => 2}, in my test, can't rely on this result though
```
@ -2725,7 +2725,7 @@ There's also the bang variant `transform_keys!` that applies the block operation
Besides that, one can use `deep_transform_keys` and `deep_transform_keys!` to perform the block operation on all the keys in the given hash and all the hashes nested into it. An example of the result is:
```ruby
{nil => nil, 1 => 1, :nested => {:a => 3, 5 => 5}}.deep_transform_keys{ |key| key.to_s.upcase }
{nil => nil, 1 => 1, nested: {a: 3, 5 => 5}}.deep_transform_keys{ |key| key.to_s.upcase }
# => {""=>nil, "1"=>1, "NESTED"=>{"A"=>3, "5"=>5}}
```
@ -2736,14 +2736,14 @@ NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
The method `stringify_keys` returns a hash that has a stringified version of the keys in the receiver. It does so by sending `to_s` to them:
```ruby
{nil => nil, 1 => 1, :a => :a}.stringify_keys
{nil => nil, 1 => 1, a: :a}.stringify_keys
# => {"" => nil, "a" => :a, "1" => 1}
```
The result in case of collision is undefined:
```ruby
{"a" => 1, :a => 2}.stringify_keys
{"a" => 1, a: 2}.stringify_keys
# => {"a" => 2}, in my test, can't rely on this result though
```
@ -2764,7 +2764,7 @@ There's also the bang variant `stringify_keys!` that stringifies keys in the ver
Besides that, one can use `deep_stringify_keys` and `deep_stringify_keys!` to stringify all the keys in the given hash and all the hashes nested into it. An example of the result is:
```ruby
{nil => nil, 1 => 1, :nested => {:a => 3, 5 => 5}}.deep_stringify_keys
{nil => nil, 1 => 1, nested: {a: 3, 5 => 5}}.deep_stringify_keys
# => {""=>nil, "1"=>1, "nested"=>{"a"=>3, "5"=>5}}
```
@ -2776,7 +2776,7 @@ The method `symbolize_keys` returns a hash that has a symbolized version of the
```ruby
{nil => nil, 1 => 1, "a" => "a"}.symbolize_keys
# => {1 => 1, nil => nil, :a => "a"}
# => {1 => 1, nil => nil, a: "a"}
```
WARNING. Note in the previous example only one key was symbolized.
@ -2784,8 +2784,8 @@ WARNING. Note in the previous example only one key was symbolized.
The result in case of collision is undefined:
```ruby
{"a" => 1, :a => 2}.symbolize_keys
# => {:a => 2}, in my test, can't rely on this result though
{"a" => 1, a: 2}.symbolize_keys
# => {a: 2}, in my test, can't rely on this result though
```
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionController::UrlRewriter` defines
@ -2806,7 +2806,7 @@ Besides that, one can use `deep_symbolize_keys` and `deep_symbolize_keys!` to sy
```ruby
{nil => nil, 1 => 1, "nested" => {"a" => 3, 5 => 5}}.deep_symbolize_keys
# => {nil=>nil, 1=>1, :nested=>{:a=>3, 5=>5}}
# => {nil=>nil, 1=>1, nested:{a:3, 5=>5}}
```
NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
@ -2822,8 +2822,8 @@ NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
The method `assert_valid_keys` receives an arbitrary number of arguments, and checks whether the receiver has any key outside that white list. If it does `ArgumentError` is raised.
```ruby
{:a => 1}.assert_valid_keys(:a) # passes
{:a => 1}.assert_valid_keys("a") # ArgumentError
{a: 1}.assert_valid_keys(:a) # passes
{a: 1}.assert_valid_keys("a") # ArgumentError
```
Active Record does not accept unknown options when building associations, for example. It implements that control via `assert_valid_keys`.
@ -2835,18 +2835,18 @@ NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes:
```ruby
{:a => 1, :b => 2, :c => 3}.slice(:a, :c)
# => {:c => 3, :a => 1}
{a: 1, b: 2, c: 3}.slice(:a, :c)
# => {c: 3, a: 1}
{:a => 1, :b => 2, :c => 3}.slice(:b, :X)
# => {:b => 2} # non-existing keys are ignored
{a: 1, b: 2, c: 3}.slice(:b, :X)
# => {b: 2} # non-existing keys are ignored
```
If the receiver responds to `convert_key` keys are normalized:
```ruby
{:a => 1, :b => 2}.with_indifferent_access.slice("a")
# => {:a => 1}
{a: 1, b: 2}.with_indifferent_access.slice("a")
# => {a: 1}
```
NOTE. Slicing may come in handy for sanitizing option hashes with a white list of keys.
@ -2854,9 +2854,9 @@ NOTE. Slicing may come in handy for sanitizing option hashes with a white list o
There's also `slice!` which in addition to perform a slice in place returns what's removed:
```ruby
hash = {:a => 1, :b => 2}
rest = hash.slice!(:a) # => {:b => 2}
hash # => {:a => 1}
hash = {a: 1, b: 2}
rest = hash.slice!(:a) # => {b: 2}
hash # => {a: 1}
```
NOTE: Defined in `active_support/core_ext/hash/slice.rb`.
@ -2866,15 +2866,15 @@ NOTE: Defined in `active_support/core_ext/hash/slice.rb`.
The method `extract!` removes and returns the key/value pairs matching the given keys.
```ruby
hash = {:a => 1, :b => 2}
rest = hash.extract!(:a, :x) # => {:a => 1} # non-existing keys are ignored
hash # => {:b => 2}
hash = {a: 1, b: 2}
rest = hash.extract!(:a) # => {a: 1}
hash # => {b: 2}
```
The method `extract!` returns the same subclass of Hash, that the receiver is.
```ruby
hash = {:a => 1, :b => 2}.with_indifferent_access
hash = {a: 1, b: 2}.with_indifferent_access
rest = hash.extract!(:a).class
# => ActiveSupport::HashWithIndifferentAccess
```
@ -2886,7 +2886,7 @@ NOTE: Defined in `active_support/core_ext/hash/slice.rb`.
The method `with_indifferent_access` returns an `ActiveSupport::HashWithIndifferentAccess` out of its receiver:
```ruby
{:a => 1}.with_indifferent_access["a"] # => 1
{a: 1}.with_indifferent_access["a"] # => 1
```
NOTE: Defined in `active_support/core_ext/hash/indifferent_access.rb`.
@ -2990,7 +2990,7 @@ An unbound method is not callable as is, you need to bind it first to an object
```ruby
clear = Hash.instance_method(:clear)
clear.bind({:a => 1}).call # => {}
clear.bind({a: 1}).call # => {}
```
Active Support defines `Proc#bind` with an analogous purpose:
@ -3249,8 +3249,8 @@ The most generic way to jump to other days is `advance`. This method receives a
```ruby
date = Date.new(2010, 6, 6)
date.advance(:years => 1, :weeks => 2) # => Mon, 20 Jun 2011
date.advance(:months => 2, :days => -2) # => Wed, 04 Aug 2010
date.advance(years: 1, weeks: 2) # => Mon, 20 Jun 2011
date.advance(months: 2, days: -2) # => Wed, 04 Aug 2010
```
Note in the previous example that increments may be negative.
@ -3260,14 +3260,14 @@ To perform the computation the method first increments years, then months, then
The method `advance` advances first one month, and then one day, the result is:
```ruby
Date.new(2010, 2, 28).advance(:months => 1, :days => 1)
Date.new(2010, 2, 28).advance(months: 1, days: 1)
# => Sun, 29 Mar 2010
```
While if it did it the other way around the result would be different:
```ruby
Date.new(2010, 2, 28).advance(:days => 1).advance(:months => 1)
Date.new(2010, 2, 28).advance(days: 1).advance(months: 1)
# => Thu, 01 Apr 2010
```
@ -3276,14 +3276,14 @@ Date.new(2010, 2, 28).advance(:days => 1).advance(:months => 1)
The method `change` allows you to get a new date which is the same as the receiver except for the given year, month, or day:
```ruby
Date.new(2010, 12, 23).change(:year => 2011, :month => 11)
Date.new(2010, 12, 23).change(year: 2011, month: 11)
# => Wed, 23 Nov 2011
```
This method is not tolerant to non-existing dates, if the change is invalid `ArgumentError` is raised:
```ruby
Date.new(2010, 1, 31).change(:month => 2)
Date.new(2010, 1, 31).change(month: 2)
# => ArgumentError: invalid date
```
@ -3469,7 +3469,7 @@ The most generic way to jump to another datetime is `advance`. This method recei
```ruby
d = DateTime.current
# => Thu, 05 Aug 2010 11:33:31 +0000
d.advance(:years => 1, :months => 1, :days => 1, :hours => 1, :minutes => 1, :seconds => 1)
d.advance(years: 1, months: 1, days: 1, hours: 1, minutes: 1, seconds: 1)
# => Tue, 06 Sep 2011 12:34:32 +0000
```
@ -3480,14 +3480,14 @@ If we first move the date bits (that have also a relative order of processing, a
```ruby
d = DateTime.new(2010, 2, 28, 23, 59, 59)
# => Sun, 28 Feb 2010 23:59:59 +0000
d.advance(:months => 1, :seconds => 1)
d.advance(months: 1, seconds: 1)
# => Mon, 29 Mar 2010 00:00:00 +0000
```
but if we computed them the other way around, the result would be different:
```ruby
d.advance(:seconds => 1).advance(:months => 1)
d.advance(seconds: 1).advance(months: 1)
# => Thu, 01 Apr 2010 00:00:00 +0000
```
@ -3500,28 +3500,28 @@ The method `change` allows you to get a new datetime which is the same as the re
```ruby
now = DateTime.current
# => Tue, 08 Jun 2010 01:56:22 +0000
now.change(:year => 2011, :offset => Rational(-6, 24))
now.change(year: 2011, offset: Rational(-6, 24))
# => Wed, 08 Jun 2011 01:56:22 -0600
```
If hours are zeroed, then minutes and seconds are too (unless they have given values):
```ruby
now.change(:hour => 0)
now.change(hour: 0)
# => Tue, 08 Jun 2010 00:00:00 +0000
```
Similarly, if minutes are zeroed, then seconds are too (unless it has given a value):
```ruby
now.change(:min => 0)
now.change(min: 0)
# => Tue, 08 Jun 2010 01:00:00 +0000
```
This method is not tolerant to non-existing dates, if the change is invalid `ArgumentError` is raised:
```ruby
DateTime.current.change(:month => 2, :day => 30)
DateTime.current.change(month: 2, day: 30)
# => ArgumentError: invalid date
```
@ -3604,7 +3604,7 @@ Time.zone_default
# In Barcelona, 2010/03/28 02:00 +0100 becomes 2010/03/28 03:00 +0200 due to DST.
t = Time.local_time(2010, 3, 28, 1, 59, 59)
# => Sun Mar 28 01:59:59 +0100 2010
t.advance(:seconds => 1)
t.advance(seconds: 1)
# => Sun Mar 28 03:00:00 +0200 2010
```

View file

@ -37,7 +37,7 @@ ActionController
```ruby
{
:key => 'posts/1-dasboard-view'
key: 'posts/1-dasboard-view'
}
```
@ -49,7 +49,7 @@ ActionController
```ruby
{
:key => 'posts/1-dasboard-view'
key: 'posts/1-dasboard-view'
}
```
@ -61,7 +61,7 @@ ActionController
```ruby
{
:key => 'posts/1-dasboard-view'
key: 'posts/1-dasboard-view'
}
```
@ -73,7 +73,7 @@ ActionController
```ruby
{
:key => 'posts/1-dasboard-view'
key: 'posts/1-dasboard-view'
}
```
@ -85,7 +85,7 @@ ActionController
```ruby
{
:path => '/users/1'
path: '/users/1'
}
```
@ -97,7 +97,7 @@ ActionController
```ruby
{
:path => '/users/1'
path: '/users/1'
}
```
@ -114,12 +114,12 @@ ActionController
```ruby
{
:controller => "PostsController",
:action => "new",
:params => { "action" => "new", "controller" => "posts" },
:format => :html,
:method => "GET",
:path => "/posts/new"
controller: "PostsController",
action: "new",
params: { "action" => "new", "controller" => "posts" },
format: :html,
method: "GET",
path: "/posts/new"
}
```
@ -137,15 +137,15 @@ ActionController
```ruby
{
:controller => "PostsController",
:action => "index",
:params => {"action" => "index", "controller" => "posts"},
:format => :html,
:method => "GET",
:path => "/posts",
:status => 200,
:view_runtime => 46.848,
:db_runtime => 0.157
controller: "PostsController",
action: "index",
params: {"action" => "index", "controller" => "posts"},
format: :html,
method: "GET",
path: "/posts",
status: 200,
view_runtime: 46.848,
db_runtime: 0.157
}
```
@ -170,8 +170,8 @@ INFO. Additional keys may be added by the caller.
```ruby
{
:status => 302,
:location => "http://localhost:3000/posts/new"
status: 302,
location: "http://localhost:3000/posts/new"
}
```
@ -183,7 +183,7 @@ INFO. Additional keys may be added by the caller.
```ruby
{
:filter => ":halting_filter"
filter: ":halting_filter"
}
```
@ -199,8 +199,8 @@ ActionView
```ruby
{
:identifier => "/Users/adam/projects/notifications/app/views/posts/index.html.erb",
:layout => "layouts/application"
identifier: "/Users/adam/projects/notifications/app/views/posts/index.html.erb",
layout: "layouts/application"
}
```
@ -212,7 +212,7 @@ ActionView
```ruby
{
:identifier => "/Users/adam/projects/notifications/app/views/posts/_form.html.erb",
identifier: "/Users/adam/projects/notifications/app/views/posts/_form.html.erb",
}
```
@ -231,10 +231,10 @@ INFO. The adapters will add their own data as well.
```ruby
{
:sql => "SELECT \"posts\".* FROM \"posts\" ",
:name => "Post Load",
:connection_id => 70307250813140,
:binds => []
sql: "SELECT \"posts\".* FROM \"posts\" ",
name: "Post Load",
connection_id: 70307250813140,
binds: []
}
```
@ -265,13 +265,13 @@ ActionMailer
```ruby
{
:mailer => "Notification",
:message_id => "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
:subject => "Rails Guides",
:to => ["users@rails.com", "ddh@rails.com"],
:from => ["me@rails.com"],
:date => Sat, 10 Mar 2012 14:18:09 +0100,
:mail=> "..." # ommitted for beverity
mailer: "Notification",
message_id: "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
subject: "Rails Guides",
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
mail: "..." # ommitted for beverity
}
```
@ -291,13 +291,13 @@ ActionMailer
```ruby
{
:mailer => "Notification",
:message_id => "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
:subject => "Rails Guides",
:to => ["users@rails.com", "ddh@rails.com"],
:from => ["me@rails.com"],
:date => Sat, 10 Mar 2012 14:18:09 +0100,
:mail=> "..." # ommitted for beverity
mailer: "Notification",
message_id: "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
subject: "Rails Guides",
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
mail: "..." # ommitted for beverity
}
```
@ -335,7 +335,7 @@ INFO. Options passed to fetch will be merged with the payload when writing to th
```ruby
{
:key => 'name-of-complicated-computation'
key: 'name-of-complicated-computation'
}
```
@ -352,7 +352,7 @@ INFO. Options passed to fetch will be merged with the payload.
```ruby
{
:key => 'name-of-complicated-computation'
key: 'name-of-complicated-computation'
}
```
@ -366,7 +366,7 @@ INFO. Cache stores my add their own keys
```ruby
{
:key => 'name-of-complicated-computation'
key: 'name-of-complicated-computation'
}
```
@ -378,7 +378,7 @@ INFO. Cache stores my add their own keys
```ruby
{
:key => 'name-of-complicated-computation'
key: 'name-of-complicated-computation'
}
```
@ -390,7 +390,7 @@ INFO. Cache stores my add their own keys
```ruby
{
:key => 'name-of-complicated-computation'
key: 'name-of-complicated-computation'
}
```
@ -434,7 +434,7 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
event.name # => "process_action.action_controller"
event.duration # => 10 (in milliseconds)
event.payload # => { :extra => :information }
event.payload # => { extra: :information }
Rails.logger.info "#{event} Received!"
end
@ -445,7 +445,7 @@ Most times you only care about the data itself. Here is a shortuct to just get t
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
data = args.extract_options!
data # { :extra => :information }
data # { extra: :information }
```
You may also subscribe to events matching a regular expresssion. This enables you to subscribe to
@ -468,7 +468,7 @@ as well as the unique ID. All data passed into the `insturment` call will make i
Here's an example:
```ruby
ActiveSupport::Notifications.instrument "my.custom.event", :this => :data do
ActiveSupport::Notifications.instrument "my.custom.event", this: :data do
# do your custom stuff here
end
```
@ -477,7 +477,7 @@ Now you can listen to this event with:
```ruby
ActiveSupport::Notifications.subscribe "my.custom.event" do |name, started, finished, unique_id, data|
puts data.inspect # { :this => :data }
puts data.inspect # { this: :data }
end
```

View file

@ -64,7 +64,7 @@ On the other hand, big chunks of structured documentation may have a separate "E
#
# Person.exists?(5)
# Person.exists?('5')
# Person.exists?(:name => "David")
# Person.exists?(name: "David")
# Person.exists?(['name LIKE ?', "%#{query}%"])
```
@ -88,7 +88,7 @@ If a line is too long, the comment may be placed on the next line:
# label(:post, :title, "A short title")
# # => <label for="post_title">A short title</label>
#
# label(:post, :title, "A short title", :class => "title_label")
# label(:post, :title, "A short title", class: "title_label")
# # => <label for="post_title" class="title_label">A short title</label>
```

View file

@ -637,7 +637,7 @@ The `create_association` method returns a new object of the associated type. Thi
#### Options for `belongs_to`
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `belongs_to` association reference. Such customizations can easily be accomplished by passing options and scope blocks when you create the association. For example, this assocation uses two such options:
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `belongs_to` association reference. Such customizations can easily be accomplished by passing options and scope blocks when you create the association. For example, this association uses two such options:
```ruby
class Order < ActiveRecord::Base
@ -932,7 +932,7 @@ The `create_association` method returns a new object of the associated type. Thi
#### Options for `has_one`
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_one` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_one` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this association uses two such options:
```ruby
class Supplier < ActiveRecord::Base
@ -1143,7 +1143,7 @@ When you declare a `has_many` association, the declaring class automatically gai
* `collection.build(attributes = {}, ...)`
* `collection.create(attributes = {})`
In all of these methods, `collection` is replaced with the symbol passed as the first argument to `has_many`, and `collection_singular` is replaced with the singularized version of that symbol.. For example, given the declaration:
In all of these methods, `collection` is replaced with the symbol passed as the first argument to `has_many`, and `collection_singular` is replaced with the singularized version of that symbol. For example, given the declaration:
```ruby
class Customer < ActiveRecord::Base
@ -1286,7 +1286,7 @@ The `collection.create` method returns a new object of the associated type. This
#### Options for `has_many`
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_many` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_many` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this association uses two such options:
```ruby
class Customer < ActiveRecord::Base
@ -1737,7 +1737,7 @@ The `collection.create` method returns a new object of the associated type. This
#### Options for `has_and_belongs_to_many`
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_and_belongs_to_many` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the `has_and_belongs_to_many` association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this association uses two such options:
```ruby
class Parts < ActiveRecord::Base

View file

@ -91,7 +91,7 @@ Or, you can set custom gzip compression level (level names are taken from `Zlib`
caches_page :image, :gzip => :best_speed
```
NOTE: Page caching ignores all parameters. For example `/products?page=1` will be written out to the filesystem as `products.html` with no reference to the `page` parameter. Thus, if someone requests `/products?page=2` later, they will get the cached first page. A workaround for this limitation is to include the parameters in the page's path, e.g. `/productions/page/1`.
NOTE: Page caching ignores all parameters. For example `/products?page=1` will be written out to the filesystem as `products.html` with no reference to the `page` parameter. Thus, if someone requests `/products?page=2` later, they will get the cached first page. A workaround for this limitation is to include the parameters in the page's path, e.g. `/products/page/1`.
INFO: Page caching runs in an after filter. Thus, invalid requests won't generate spurious cache entries as long as you halt them. Typically, a redirection in some before filter that checks request preconditions does the job.

View file

@ -22,7 +22,7 @@ NOTE: Bugs in the most recent released version of Ruby on Rails are likely to ge
### Creating a Bug Report
If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under [Issues](https://github.com/rails/rails/issues in case it was already reported. If you find no issue addressing it you can [add a new one](https://github.com/rails/rails/issues/new). (See the next section for reporting security issues).
If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under [Issues](https://github.com/rails/rails/issues) in case it was already reported. If you find no issue addressing it you can [add a new one](https://github.com/rails/rails/issues/new). (See the next section for reporting security issues).
At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need at least to post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself -- and others -- to replicate the bug and figure out a fix.
@ -287,7 +287,7 @@ You can also add bullet points:
TIP. Please squash your commits into a single commit when appropriate. This simplifies future cherry picks, and also keeps the git log clean.
### Update Master
### Update Your Branch
Its pretty likely that other changes to master have happened while you were working. Go get them:
@ -348,7 +348,7 @@ Update your fork:
$ git push origin master
```
If you want to update another branches:
If you want to update another branch:
```bash
$ git checkout branch_name

View file

@ -63,7 +63,7 @@ And if you are on Fedora or CentOS, you're done with
$ sudo yum install sqlite3 sqlite3-devel
```
Get a recent version of [Bundler](http://gembundler.com/:)
Get a recent version of [Bundler](http://gembundler.com/)
```bash
$ gem install bundler

View file

@ -233,20 +233,20 @@ Blog::Application.routes.draw do
# ...
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
# root :to => "welcome#index"
# root to: "welcome#index"
```
This is your application's _routing file_ which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. This file contains many sample routes on commented lines, and one of them actually shows you how to connect the root of your site to a specific controller and action. Find the line beginning with `root :to` and uncomment it. It should look something like the following:
```ruby
root :to => "welcome#index"
root to: "welcome#index"
```
The `root :to => "welcome#index"` tells Rails to map requests to the root of the application to the welcome controller's index action and `get "welcome/index"` tells Rails to map requests to <http://localhost:3000/welcome/index> to the welcome controller's index action. This was created earlier when you ran the controller generator (`rails generate controller welcome index`).
The `root to: "welcome#index"` tells Rails to map requests to the root of the application to the welcome controller's index action and `get "welcome/index"` tells Rails to map requests to <http://localhost:3000/welcome/index> to the welcome controller's index action. This was created earlier when you ran the controller generator (`rails generate controller welcome index`).
If you navigate to <http://localhost:3000> in your browser, you'll see the `Hello, Rails!` message you put into `app/views/welcome/index.html.erb`, indicating that this new route is indeed going to `WelcomeController`'s `index` action and is rendering the view correctly.
NOTE. For more information about routing, refer to [Rails Routing from the Outside In](routing.html).
TIP: For more information about routing, refer to [Rails Routing from the Outside In](routing.html).
Getting Up and Running
----------------------
@ -318,14 +318,14 @@ You're getting this error now because Rails expects plain actions like this one
In the above image, the bottom line has been truncated. Let's see what the full thing looks like:
<blockquote>
Missing template posts/new, application/new with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
Missing template posts/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
</blockquote>
That's quite a lot of text! Let's quickly go through and understand what each part of it does.
The first part identifies what template is missing. In this case, it's the `posts/new` template. Rails will first look for this template. If not found, then it will attempt to load a template called `application/new`. It looks for one here because the `PostsController` inherits from `ApplicationController`.
The next part of the message contains a hash. The `:locale` key in this hash simply indicates what spoken language template should be retrieved. By default, this is the English -- or "en" -- template. The next key, `:formats` specifies the format of template to be served in response . The default format is `:html`, and so Rails is looking for an HTML template. The final key, `:handlers`, is telling us what _template handlers_ could be used to render our template. `:erb` is most commonly used for HTML templates, `:builder` is used for XML templates, and `:coffee` uses CoffeeScript to build JavaScript templates.
The next part of the message contains a hash. The `:locale` key in this hash simply indicates what spoken language template should be retrieved. By default, this is the English -- or "en" -- template. The next key, `:formats` specifies the format of template to be served in response. The default format is `:html`, and so Rails is looking for an HTML template. The final key, `:handlers`, is telling us what _template handlers_ could be used to render our template. `:erb` is most commonly used for HTML templates, `:builder` is used for XML templates, and `:coffee` uses CoffeeScript to build JavaScript templates.
The final part of this message tells us where Rails has looked for the templates. Templates within a basic Rails application like this are kept in a single location, but in more complex applications it could be many different paths.
@ -380,7 +380,7 @@ like this is called "create", and so the form should be pointed to that action.
Edit the `form_for` line inside `app/views/posts/new.html.erb` to look like this:
```html+erb
<%= form_for :post, :url => { :action => :create } do |f| %>
<%= form_for :post, url: { action: :create } do |f| %>
```
In this example, a `Hash` object is passed to the `:url` option. What Rails will do with this is that it will point the form to the `create` action of the current controller, the `PostsController`, and will send a `POST` request to that route. For this to work, you will need to add a route to `config/routes.rb`, right underneath the one for "posts/new":
@ -417,7 +417,7 @@ When a form is submitted, the fields of the form are sent to Rails as _parameter
```ruby
def create
render :text => params[:post].inspect
render text: params[:post].inspect
end
```
@ -489,9 +489,10 @@ run this migration. The action defined in this method is also reversible, which
means Rails knows how to reverse the change made by this migration, in case you
want to reverse it later. When you run this migration it will create a
`posts` table with one string column and a text column. It also creates two
timestamp fields to allow Rails to track post creation and update times. More
information about Rails migrations can be found in the "Rails Database
Migrations":migrations.html guide.
timestamp fields to allow Rails to track post creation and update times.
TIP: For more information about migrations, refer to [Rails Database
Migrations](migrations.html).
At this point, you can use a rake command to run the migration:
@ -526,7 +527,7 @@ def create
@post = Post.new(params[:post])
@post.save
redirect_to :action => :show, :id => @post.id
redirect_to action: :show, id: @post.id
end
```
@ -539,7 +540,7 @@ Finally, we redirect the user to the `show` action,
which we'll define later.
TIP: As we'll see later, `@post.save` returns a boolean indicating
wherever the model was saved or not.
whether the model was saved or not.
### Showing Posts
@ -639,7 +640,7 @@ Open `app/views/welcome/index.html.erb` and modify it as follows:
```html+erb
<h1>Hello, Rails!</h1>
<%= link_to "My Blog", :controller => "posts" %>
<%= link_to "My Blog", controller: "posts" %>
```
The `link_to` method is one of Rails' built-in view helpers. It creates a
@ -649,7 +650,7 @@ for posts.
Let's add links to the other views as well, starting with adding this "New Post" link to `app/views/posts/index.html.erb`, placing it above the `<table>` tag:
```erb
<%= link_to 'New post', :action => :new %>
<%= link_to 'New post', action: :new %>
```
This link will allow you to bring up the form that lets you create a new post. You should also add a link to this template -- `app/views/posts/new.html.erb` -- to go back to the `index` action. Do this by adding this underneath the form in this template:
@ -659,7 +660,7 @@ This link will allow you to bring up the form that lets you create a new post. Y
...
<% end %>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
Finally, add another link to the `app/views/posts/show.html.erb` template to go back to the `index` action as well, so that people who are viewing a single post can go back and view the whole list again:
@ -675,7 +676,7 @@ Finally, add another link to the `app/views/posts/show.html.erb` template to go
<%= @post.text %>
</p>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
TIP: If you want to link to an action in the same controller, you don't
@ -723,8 +724,8 @@ Open the `app/models/post.rb` file and edit it:
class Post < ActiveRecord::Base
attr_accessible :text, :title
validates :title, :presence => true,
:length => { :minimum => 5 }
validates :title, presence: true,
length: { minimum: 5 }
end
```
@ -749,7 +750,7 @@ def create
@post = Post.new(params[:post])
if @post.save
redirect_to :action => :show, :id => @post.id
redirect_to action: :show, id: @post.id
else
render 'new'
end
@ -770,7 +771,7 @@ something went wrong. To do that, you'll modify
`app/views/posts/new.html.erb` to check for error messages:
```html+erb
<%= form_for :post, :url => { :action => :create } do |f| %>
<%= form_for :post, url: { action: :create } do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
@ -797,7 +798,7 @@ something went wrong. To do that, you'll modify
</p>
<% end %>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
A few things are going on. We check if there are any errors with
@ -824,7 +825,7 @@ attempt to do just that on the new post form [(http://localhost:3000/posts/new)]
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating posts.
The first step we'll take is adding a `edit` action to `posts_controller`.
The first step we'll take is adding an `edit` action to `posts_controller`.
Start by adding a route to `config/routes.rb`:
@ -847,8 +848,8 @@ it look as follows:
```html+erb
<h1>Editing post</h1>
<%= form_for :post, :url => { :action => :update, :id => @post.id },
:method => :put do |f| %>
<%= form_for :post, url: { action: :update, id: @post.id },
method: :put do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
@ -875,14 +876,14 @@ it look as follows:
</p>
<% end %>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
This time we point the form to the `update` action, which is not defined yet
but will be very soon.
The `:method => :put` option tells Rails that we want this form to be
submitted via the `PUT`, HTTP method which is the HTTP method you're expected to use to
The `method: :put` option tells Rails that we want this form to be
submitted via the `PUT` HTTP method which is the HTTP method you're expected to use to
**update** resources according to the REST protocol.
TIP: By default forms built with the _form_for_ helper are sent via `POST`.
@ -901,7 +902,7 @@ def update
@post = Post.find(params[:id])
if @post.update_attributes(params[:post])
redirect_to :action => :show, :id => @post.id
redirect_to action: :show, id: @post.id
else
render 'edit'
end
@ -913,8 +914,8 @@ that already exists, and it accepts a hash containing the attributes
that you want to update. As before, if there was an error updating the
post we want to show the form back to the user.
TIP: you don't need to pass all attributes to `update_attributes`. For
example, if you'd call `@post.update_attributes(:title => 'A new title')`
TIP: You don't need to pass all attributes to `update_attributes`. For
example, if you'd call `@post.update_attributes(title: 'A new title')`
Rails would only update the `title` attribute, leaving all other
attributes untouched.
@ -935,8 +936,8 @@ appear next to the "Show" link:
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', :action => :show, :id => post.id %></td>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
<td><%= link_to 'Show', action: :show, id: post.id %></td>
<td><%= link_to 'Edit', action: :edit, id: post.id %></td>
</tr>
<% end %>
</table>
@ -949,8 +950,8 @@ the template:
```html+erb
...
<%= link_to 'Back', :action => :index %>
| <%= link_to 'Edit', :action => :edit, :id => @post.id %>
<%= link_to 'Back', action: :index %>
| <%= link_to 'Edit', action: :edit, id: @post.id %>
```
And here's how our app looks so far:
@ -985,7 +986,7 @@ TIP: You can read more about partials in the
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
Our `edit` action looks very similar to the `new` action, in fact they
both share the same code for displaying the form. Lets clean them up by
both share the same code for displaying the form. Let's clean them up by
using a partial.
Create a new file `app/views/posts/_form.html.erb` with the following
@ -1031,7 +1032,7 @@ completely:
<%= render 'form' %>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
Then do the same for the `app/views/posts/edit.html.erb` view:
@ -1041,7 +1042,7 @@ Then do the same for the `app/views/posts/edit.html.erb` view:
<%= render 'form' %>
<%= link_to 'Back', :action => :index %>
<%= link_to 'Back', action: :index %>
```
Point your browser to <http://localhost:3000/posts/new> and
@ -1082,7 +1083,7 @@ To fix this, open `config/routes.rb` and modify the `get "posts/:id"`
line like this:
```ruby
get "posts/:id" => "posts#show", :as => :post
get "posts/:id" => "posts#show", as: :post
```
The `:as` option tells the `get` method that we want to make routing helpers
@ -1108,7 +1109,7 @@ resources. If this was left as a typical `get` route, it could be possible for
people to craft malicious URLs like this:
```html
<a href='http://yoursite.com/posts/1/destroy'>look at this cat!</a>
<a href='http://example.com/posts/1/destroy'>look at this cat!</a>
```
We use the `delete` method for destroying resources, and this route is mapped to
@ -1120,7 +1121,7 @@ def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to :action => :index
redirect_to action: :index
end
```
@ -1147,9 +1148,9 @@ together.
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', :action => :show, :id => post.id %></td>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
<td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
<td><%= link_to 'Show', action: :show, id: post.id %></td>
<td><%= link_to 'Edit', action: :edit, id: post.id %></td>
<td><%= link_to 'Destroy', { action: :destroy, id: post.id }, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
@ -1181,7 +1182,7 @@ declaring separate routes with the appropriate verbs into
get "posts" => "posts#index"
get "posts/new"
post "posts" => "posts#create"
get "posts/:id" => "posts#show", :as => :post
get "posts/:id" => "posts#show", as: :post
get "posts/:id/edit" => "posts#edit"
put "posts/:id" => "posts#update"
delete "posts/:id" => "posts#destroy"
@ -1197,7 +1198,7 @@ Blog::Application.routes.draw do
resources :posts
root :to => "welcome#index"
root to: "welcome#index"
end
```
@ -1324,8 +1325,8 @@ You'll need to edit the `post.rb` file to add the other side of the association:
```ruby
class Post < ActiveRecord::Base
validates :title, :presence => true,
:length => { :minimum => 5 }
validates :title, presence: true,
length: { minimum: 5 }
has_many :comments
end
@ -1420,14 +1421,14 @@ This adds a form on the `Post` show page that creates a new comment by
calling the `CommentsController` `create` action. The `form_for` call here uses
an array, which will build a nested route, such as `/posts/1/comments`.
Let's wire up the `create`:
Let's wire up the `create` in `app/controllers/comments_controller.rb`:
```ruby
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(params[:comment])
redirect_to post_path(@post)
redirect_to post_url(@post)
end
end
```
@ -1635,13 +1636,13 @@ So first, let's add the delete link in the
<p>
<%= link_to 'Destroy Comment', [comment.post, comment],
:method => :delete,
:data => { :confirm => 'Are you sure?' } %>
method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
```
Clicking this new "Destroy Comment" link will fire off a `DELETE
/posts/:id/comments/:id` to our `CommentsController`, which can then use
/posts/:post_id/comments/:id` to our `CommentsController`, which can then use
this to find the comment we want to delete, so let's add a destroy action to our
controller:
@ -1678,9 +1679,9 @@ model, `app/models/post.rb`, as follows:
```ruby
class Post < ActiveRecord::Base
validates :title, :presence => true,
:length => { :minimum => 5 }
has_many :comments, :dependent => :destroy
validates :title, presence: true,
length: { minimum: 5 }
has_many :comments, dependent: :destroy
end
```
@ -1705,7 +1706,7 @@ action, except for `index` and `show`, so we write that:
```ruby
class PostsController < ApplicationController
http_basic_authenticate_with :name => "dhh", :password => "secret", :except => [:index, :show]
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def index
@posts = Post.all
@ -1720,7 +1721,7 @@ We also only want to allow authenticated users to delete comments, so in the
```ruby
class CommentsController < ApplicationController
http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy
http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy
def create
@post = Post.find(params[:post_id])
@ -1752,6 +1753,8 @@ Rails also comes with built-in help that you can generate using the rake command
* Running `rake doc:guides` will put a full copy of the Rails Guides in the `doc/guides` folder of your application. Open `doc/guides/index.html` in your web browser to explore the Guides.
* Running `rake doc:rails` will put a full copy of the API documentation for Rails in the `doc/api` folder of your application. Open `doc/api/index.html` in your web browser to explore the API documentation.
TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake task you need to install the RedCloth gem. Add it to your `Gemfile` and run `bundle install` and you're ready to go.
Configuration Gotchas
---------------------
@ -1773,7 +1776,7 @@ Two very common sources of data that are not UTF-8:
* Your text editor: Most text editors (such as Textmate), default to saving files as
UTF-8. If your text editor does not, this can result in special characters that you
enter in your templates (such as é) to appear as a diamond with a question mark inside
in the browser. This also applies to your I18N translation files.
in the browser. This also applies to your i18n translation files.
Most editors that do not already default to UTF-8 (such as some versions of
Dreamweaver) offer a way to change the default to UTF-8. Do so.
* Your database. Rails defaults to converting data from your database into UTF-8 at

View file

@ -205,7 +205,7 @@ The most usual way of setting (and passing) the locale would be to include it in
This approach has almost the same set of advantages as setting the locale from the domain name: namely that it's RESTful and in accord with the rest of the World Wide Web. It does require a little bit more work to implement, though.
Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL (e.g. `link_to( books_url(:locale => I18n.locale))`) would be tedious and probably impossible, of course.
Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL (e.g. `link_to( books_url(locale: I18n.locale))`) would be tedious and probably impossible, of course.
Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
@ -215,7 +215,7 @@ We can include something like this in our `ApplicationController` then:
# app/controllers/application_controller.rb
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ :locale => I18n.locale }
{ locale: I18n.locale }
end
```
@ -238,14 +238,14 @@ If you don't want to force the use of a locale in your routes you can use an opt
```ruby
# config/routes.rb
scope "(:locale)", :locale => /en|nl/ do
scope "(:locale)", locale: /en|nl/ do
resources :books
end
```
With this approach you will not get a `Routing Error` when accessing your resources such as `http://localhost:3001/books` without a locale. This is useful for when you want to use the default locale when one is not specified.
Of course, you need to take special care of the root URL (usually "homepage" or "dashboard") of your application. An URL like `http://localhost:3001/nl` will not work automatically, because the `root :to => "books#index"` declaration in your `routes.rb` doesn't take locale into account. (And rightly so: there's only one "root" URL.)
Of course, you need to take special care of the root URL (usually "homepage" or "dashboard") of your application. An URL like `http://localhost:3001/nl` will not work automatically, because the `root to: "books#index"` declaration in your `routes.rb` doesn't take locale into account. (And rightly so: there's only one "root" URL.)
You would probably need to map URLs like these:
@ -303,7 +303,7 @@ You most probably have something like this in one of your applications:
```ruby
# config/routes.rb
Yourapp::Application.routes.draw do
root :to => "home#index"
root to: "home#index"
end
```
@ -381,7 +381,7 @@ You can use variables in the translation messages and pass their values from the
```erb
# app/views/home/index.html.erb
<%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>
<%=t 'greet_username', user: "Bill", message: "Goodbye" %>
```
```yaml
@ -398,7 +398,7 @@ OK! Now let's add a timestamp to the view, so we can demo the **date/time locali
# app/views/home/index.html.erb
<h1><%=t :hello_world %></h1>
<p><%= flash[:notice] %></p
<p><%= l Time.now, :format => :short %></p>
<p><%= l Time.now, format: :short %></p>
```
And in our pirate translations file let's add a time format (it's already there in Rails' defaults for English):
@ -495,7 +495,7 @@ I18n.t 'message'
The `translate` method also takes a `:scope` option which can contain one or more additional keys that will be used to specify a “namespace” or scope for a translation key:
```ruby
I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
```
This looks up the `:record_invalid` message in the Active Record error messages.
@ -510,9 +510,9 @@ Thus the following calls are equivalent:
```ruby
I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t 'errors.messages.record_invalid', :scope => :active_record
I18n.t :record_invalid, :scope => 'activerecord.errors.messages'
I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
I18n.t 'errors.messages.record_invalid', scope: :active_record
I18n.t :record_invalid, scope: 'activerecord.errors.messages'
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
```
#### Defaults
@ -520,7 +520,7 @@ I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
When a `:default` option is given, its value will be returned if the translation is missing:
```ruby
I18n.t :missing, :default => 'Not here'
I18n.t :missing, default: 'Not here'
# => 'Not here'
```
@ -529,7 +529,7 @@ If the `:default` value is a Symbol, it will be used as a key and translated. On
E.g., the following first tries to translate the key `:missing` and then the key `:also_missing.` As both do not yield a result, the string "Not here" will be returned:
```ruby
I18n.t :missing, :default => [:also_missing, 'Not here']
I18n.t :missing, default: [:also_missing, 'Not here']
# => 'Not here'
```
@ -538,7 +538,7 @@ I18n.t :missing, :default => [:also_missing, 'Not here']
To look up multiple translations at once, an array of keys can be passed:
```ruby
I18n.t [:odd, :even], :scope => 'errors.messages'
I18n.t [:odd, :even], scope: 'errors.messages'
# => ["must be odd", "must be even"]
```
@ -546,7 +546,7 @@ Also, a key can translate to a (potentially nested) hash of grouped translations
```ruby
I18n.t 'activerecord.errors.messages'
# => { :inclusion => "is not included in the list", :exclusion => ... }
# => { inclusion: "is not included in the list", exclusion: ... }
```
#### "Lazy" Lookup
@ -573,8 +573,8 @@ In many cases you want to abstract your translations so that **variables can be
All options besides `:default` and `:scope` that are passed to `#translate` will be interpolated to the translation:
```ruby
I18n.backend.store_translations :en, :thanks => 'Thanks %{name}!'
I18n.translate :thanks, :name => 'Jeremy'
I18n.backend.store_translations :en, thanks: 'Thanks %{name}!'
I18n.translate :thanks, name: 'Jeremy'
# => 'Thanks Jeremy!'
```
@ -587,14 +587,14 @@ In English there are only one singular and one plural form for a given string, e
The `:count` interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:
```ruby
I18n.backend.store_translations :en, :inbox => {
:one => 'one message',
:other => '%{count} messages'
I18n.backend.store_translations :en, inbox: {
one: 'one message',
other: '%{count} messages'
}
I18n.translate :inbox, :count => 2
I18n.translate :inbox, count: 2
# => '2 messages'
I18n.translate :inbox, :count => 1
I18n.translate :inbox, count: 1
# => 'one message'
```
@ -623,8 +623,8 @@ I18n.l Time.now
Explicitly passing a locale:
```ruby
I18n.t :foo, :locale => :de
I18n.l Time.now, :locale => :de
I18n.t :foo, locale: :de
I18n.l Time.now, locale: :de
```
The `I18n.locale` defaults to `I18n.default_locale` which defaults to :`en`. The default locale can be set like this:
@ -665,9 +665,9 @@ For example a Ruby Hash providing translations can look like this:
```ruby
{
:pt => {
:foo => {
:bar => "baz"
pt: {
foo: {
bar: "baz"
}
}
}
@ -698,9 +698,9 @@ So, all of the following equivalent lookups will return the `:short` date format
```ruby
I18n.t 'date.formats.short'
I18n.t 'formats.short', :scope => :date
I18n.t :short, :scope => 'date.formats'
I18n.t :short, :scope => [:date, :formats]
I18n.t 'formats.short', scope: :date
I18n.t :short, scope: 'date.formats'
I18n.t :short, scope: [:date, :formats]
```
Generally we recommend using YAML as a format for storing translations. There are cases, though, where you want to store Ruby lambdas as part of your locale data, e.g. for special date formats.
@ -734,7 +734,7 @@ Consider a User model with a validation for the name attribute like this:
```ruby
class User < ActiveRecord::Base
validates :name, :presence => true
validates :name, presence: true
end
```
@ -764,7 +764,7 @@ For example, you might have an Admin model inheriting from User:
```ruby
class Admin < User
validates :name, :presence => true
validates :name, presence: true
end
```
@ -930,7 +930,7 @@ Another example where the default behaviour is less desirable is the Rails Trans
To do so, the helper forces `I18n#translate` to raise exceptions no matter what exception handler is defined by setting the `:raise` option:
```ruby
I18n.t :foo, :raise => true # always re-raises exceptions from the backend
I18n.t :foo, raise: true # always re-raises exceptions from the backend
```
Conclusion

View file

@ -332,7 +332,7 @@ end
As always, what has been generated for you is just a starting point. You can add
or remove from it as you see fit by editing the
@db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb@ file.
`db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb` file.
NOTE: The generated migration file for destructive migrations will still be
old-style using the `up` and `down` methods. This is because Rails needs to know
@ -978,12 +978,13 @@ this, then you should set the schema format to `:sql`.
Instead of using Active Record's schema dumper, the database's structure will be
dumped using a tool specific to the database (via the `db:structure:dump` Rake task)
into `db/structure.sql`. For example, for the PostgreSQL RDBMS, the
`pg_dump` utility is used. For MySQL, this file will contain the output of `SHOW
CREATE TABLE` for the various tables. Loading these schemas is simply a question
of executing the SQL statements they contain. By definition, this will create a
perfect copy of the database's structure. Using the `:sql` schema format will,
however, prevent loading the schema into a RDBMS other than the one used to
create it.
`pg_dump` utility is used. For MySQL, this file will contain the output of
`SHOW CREATE TABLE` for the various tables.
Loading these schemas is simply a question of executing the SQL statements they
contain. By definition, this will create a perfect copy of the database's
structure. Using the `:sql` schema format will, however, prevent loading the
schema into a RDBMS other than the one used to create it.
### Schema Dumps and Source Control

View file

@ -65,8 +65,8 @@ require 'rails/performance_test_help'
class HomepageTest < ActionDispatch::PerformanceTest
# Refer to the documentation for all available options
# self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory],
# :output => 'tmp/performance', :formats => [:flat] }
# self.profile_options = { runs: 5, metrics: [:wall_time, :memory],
# output: 'tmp/performance', formats: [:flat] }
test "homepage" do
get '/'

View file

@ -390,11 +390,8 @@ NOTE: Creating your own assertions is an advanced topic that we won't cover in t
Rails adds some custom assertions of its own to the `test/unit` framework:
NOTE: `assert_valid(record)` has been deprecated. Please use `assert(record.valid?)` instead.
| Assertion | Purpose |
| --------------------------------------------------------------------------------- | ------- |
| `assert_valid(record)` | Ensures that the passed record is valid by Active Record standards and returns any error messages if it is not.|
| `assert_difference(expressions, difference = 1, message = nil) {...}` | Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
| `assert_no_difference(expressions, message = nil, &amp;block)` | Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
| `assert_recognizes(expected_options, path, extras={}, message=nil)` | Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|

View file

@ -27,7 +27,7 @@
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Don't fallback to assets pipeline if a precompiled asset is missed.
# Whether to fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.