1 Comment charger les extensions de base
1.1 Active Support autonome
Afin d'avoir la plus petite empreinte possible par défaut, Active Support charge les dépendances minimales par défaut. Il est divisé en petites parties afin que seules les extensions souhaitées puissent être chargées. Il dispose également de points d'entrée pratiques pour charger des extensions connexes en une seule fois, voire tout.
Ainsi, après un simple require comme :
require "active_support"
seules les extensions requises par le framework Active Support sont chargées.
1.1.1 Sélectionner une définition
Cet exemple montre comment charger Hash#with_indifferent_access
. Cette extension permet la conversion d'un Hash
en ActiveSupport::HashWithIndifferentAccess
qui permet d'accéder aux clés sous forme de chaînes de caractères ou de symboles.
{ a: 1 }.with_indifferent_access["a"] # => 1
Pour chaque méthode définie en tant qu'extension de base, ce guide comporte une note indiquant où cette méthode est définie. Dans le cas de with_indifferent_access
, la note indique :
NOTE : Défini dans active_support/core_ext/hash/indifferent_access.rb
.
Cela signifie que vous pouvez le requérir comme ceci :
require "active_support"
require "active_support/core_ext/hash/indifferent_access"
Active Support a été soigneusement révisé de manière à ce que la sélection d'un fichier ne charge que les dépendances strictement nécessaires, le cas échéant.
1.1.2 Charger les extensions de base groupées
Le niveau suivant consiste simplement à charger toutes les extensions de Hash
. En règle générale, les extensions de SomeClass
sont disponibles en une seule fois en chargeant active_support/core_ext/some_class
.
Ainsi, pour charger toutes les extensions de Hash
(y compris with_indifferent_access
) :
require "active_support"
require "active_support/core_ext/hash"
1.1.3 Charger toutes les extensions de base
Vous pouvez préférer simplement charger toutes les extensions de base, il y a un fichier pour cela :
require "active_support"
require "active_support/core_ext"
1.1.4 Charger tout Active Support
Et enfin, si vous souhaitez avoir tout Active Support disponible, il suffit de lancer :
require "active_support/all"
Cela ne met même pas tout Active Support en mémoire à l'avance, en effet, certaines choses sont configurées via autoload
, donc elles ne sont chargées que si elles sont utilisées.
1.2 Active Support dans une application Ruby on Rails
Une application Ruby on Rails charge tout Active Support à moins que config.active_support.bare
ne soit vrai. Dans ce cas, l'application ne chargera que ce que le framework lui-même sélectionne pour ses propres besoins, et peut toujours se sélectionner elle-même à n'importe quel niveau de granularité, comme expliqué dans la section précédente.
2 Extensions pour tous les objets
2.1 blank?
et present?
Les valeurs suivantes sont considérées comme vides dans une application Rails :
nil
etfalse
,les chaînes de caractères composées uniquement d'espaces (voir la note ci-dessous),
les tableaux et les hachages vides, et
tout autre objet qui répond à
empty?
et qui est vide.
INFO : Le prédicat pour les chaînes de caractères utilise la classe de caractères sensible à l'Unicode [:space:]
, donc par exemple U+2029 (séparateur de paragraphe) est considéré comme un espace.
AVERTISSEMENT: Notez que les nombres ne sont pas mentionnés. En particulier, 0 et 0.0 ne sont pas vides.
Par exemple, cette méthode de ActionController::HttpAuthentication::Token::ControllerMethods
utilise blank?
pour vérifier si un jeton est présent:
def authenticate(controller, &login_procedure)
token, options = token_and_options(controller.request)
unless token.blank?
login_procedure.call(token, options)
end
end
La méthode present?
est équivalente à !blank?
. Cet exemple est tiré de ActionDispatch::Http::Cache::Response
:
def set_conditional_cache_control!
return if self["Cache-Control"].present?
# ...
end
Défini dans active_support/core_ext/object/blank.rb
.
2.2 presence
La méthode presence
renvoie son receveur s'il est present?
, et nil
sinon. Elle est utile pour des idiomes comme celui-ci:
host = config[:host].presence || 'localhost'
Défini dans active_support/core_ext/object/blank.rb
.
2.3 duplicable?
À partir de Ruby 2.5, la plupart des objets peuvent être dupliqués via dup
ou clone
:
"foo".dup # => "foo"
"".dup # => ""
Rational(1).dup # => (1/1)
Complex(0).dup # => (0+0i)
1.method(:+).dup # => TypeError (allocator undefined for Method)
Active Support fournit duplicable?
pour interroger un objet à ce sujet:
"foo".duplicable? # => true
"".duplicable? # => true
Rational(1).duplicable? # => true
Complex(1).duplicable? # => true
1.method(:+).duplicable? # => false
AVERTISSEMENT: Toute classe peut interdire la duplication en supprimant dup
et clone
ou en levant des exceptions à partir d'eux. Ainsi, seul rescue
peut dire si un objet arbitraire donné est duplicable. duplicable?
dépend de la liste codée en dur ci-dessus, mais il est beaucoup plus rapide que rescue
. Utilisez-le uniquement si vous savez que la liste codée en dur est suffisante dans votre cas d'utilisation.
Défini dans active_support/core_ext/object/duplicable.rb
.
2.4 deep_dup
La méthode deep_dup
renvoie une copie en profondeur d'un objet donné. Normalement, lorsque vous dupliquez
un objet qui contient d'autres objets, Ruby ne les duplique
pas, il crée donc une copie superficielle de l'objet. Si vous avez un tableau avec une chaîne, par exemple, cela ressemblera à ceci:
array = ['string']
duplicate = array.dup
duplicate.push 'another-string'
# l'objet a été dupliqué, donc l'élément a été ajouté uniquement à la copie
array # => ['string']
duplicate # => ['string', 'another-string']
duplicate.first.gsub!('string', 'foo')
# le premier élément n'a pas été dupliqué, il sera modifié dans les deux tableaux
array # => ['foo']
duplicate # => ['foo', 'another-string']
Comme vous pouvez le voir, après avoir dupliqué l'instance Array
, nous avons obtenu un autre objet, donc nous pouvons le modifier et l'objet original restera inchangé. Cependant, cela n'est pas vrai pour les éléments du tableau. Comme dup
ne fait pas de copie en profondeur, la chaîne à l'intérieur du tableau est toujours le même objet.
Si vous avez besoin d'une copie en profondeur d'un objet, vous devez utiliser deep_dup
. Voici un exemple:
array = ['string']
duplicate = array.deep_dup
duplicate.first.gsub!('string', 'foo')
array # => ['string']
duplicate # => ['foo']
Si l'objet n'est pas duplicable, deep_dup
le renverra simplement:
number = 1
duplicate = number.deep_dup
number.object_id == duplicate.object_id # => true
Défini dans active_support/core_ext/object/deep_dup.rb
.
2.5 try
Lorsque vous souhaitez appeler une méthode sur un objet uniquement s'il n'est pas nil
, la manière la plus simple de le faire est d'utiliser des instructions conditionnelles, ce qui ajoute un encombrement inutile. L'alternative est d'utiliser try
. try
est comme Object#public_send
, sauf qu'il renvoie nil
s'il est envoyé à nil
.
Voici un exemple :
# sans try
unless @number.nil?
@number.next
end
# avec try
@number.try(:next)
Un autre exemple est ce code de ActiveRecord::ConnectionAdapters::AbstractAdapter
où @logger
pourrait être nil
. Vous pouvez voir que le code utilise try
et évite une vérification inutile.
def log_info(sql, name, ms)
if @logger.try(:debug?)
name = '%s (%.1fms)' % [name || 'SQL', ms]
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
end
end
try
peut également être appelé sans arguments mais avec un bloc, qui ne sera exécuté que si l'objet n'est pas nul :
@person.try { |p| "#{p.first_name} #{p.last_name}" }
Notez que try
va ignorer les erreurs de méthode inexistante, renvoyant à la place nil
. Si vous voulez vous protéger contre les fautes de frappe, utilisez try!
à la place :
@number.try(:nest) # => nil
@number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer
NOTE : Défini dans active_support/core_ext/object/try.rb
.
2.6 class_eval(*args, &block)
Vous pouvez évaluer du code dans le contexte de la classe singleton de n'importe quel objet en utilisant class_eval
:
class Proc
def bind(object)
block, time = self, Time.current
object.class_eval do
method_name = "__bind_#{time.to_i}_#{time.usec}"
define_method(method_name, &block)
method = instance_method(method_name)
remove_method(method_name)
method
end.bind(object)
end
end
NOTE : Défini dans active_support/core_ext/kernel/singleton_class.rb
.
2.7 acts_like?(duck)
La méthode acts_like?
permet de vérifier si une classe se comporte comme une autre classe en se basant sur une simple convention : une classe qui fournit la même interface que String
définit
def acts_like_string?
end
qui est simplement un marqueur, son corps ou sa valeur de retour sont sans importance. Ensuite, le code client peut interroger la conformité au type de canard de cette manière :
some_klass.acts_like?(:string)
Rails possède des classes qui se comportent comme Date
ou Time
et qui suivent ce contrat.
NOTE : Défini dans active_support/core_ext/object/acts_like.rb
.
2.8 to_param
Tous les objets dans Rails répondent à la méthode to_param
, qui est censée renvoyer quelque chose qui les représente comme des valeurs dans une chaîne de requête ou comme des fragments d'URL.
Par défaut, to_param
appelle simplement to_s
:
7.to_param # => "7"
La valeur de retour de to_param
ne doit pas être échappée :
"Tom & Jerry".to_param # => "Tom & Jerry"
Plusieurs classes dans Rails redéfinissent cette méthode.
Par exemple, nil
, true
et false
renvoient eux-mêmes. Array#to_param
appelle to_param
sur les éléments et joint le résultat avec "/":
[0, true, String].to_param # => "0/true/String"
Il est important de noter que le système de routage de Rails appelle to_param
sur les modèles pour obtenir une valeur pour le paramètre :id
. ActiveRecord::Base#to_param
renvoie l'id
d'un modèle, mais vous pouvez redéfinir cette méthode dans vos modèles. Par exemple, avec :
class User
def to_param
"#{id}-#{name.parameterize}"
end
end
nous obtenons :
user_path(@user) # => "/users/357-john-smith"
ATTENTION. Les contrôleurs doivent être conscients de toute redéfinition de to_param
car lorsque cette requête arrive, "357-john-smith" est la valeur de params[:id]
.
NOTE : Défini dans active_support/core_ext/object/to_param.rb
.
2.9 to_query
La méthode to_query
construit une chaîne de requête qui associe une clé donnée à la valeur renvoyée par to_param
. Par exemple, avec la définition to_param
suivante :
class User
def to_param
"#{id}-#{name.parameterize}"
end
end
nous obtenons :
current_user.to_query('user') # => "user=357-john-smith"
Cette méthode échappe tout ce qui est nécessaire, à la fois pour la clé et pour la valeur :
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"
ainsi sa sortie est prête à être utilisée dans une chaîne de requête.
Les tableaux renvoient le résultat de l'application de to_query
à chaque élément avec key[]
comme clé, et joignent le résultat avec "&":
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
Les hachages répondent également à to_query
mais avec une signature différente. Si aucun argument n'est passé, un appel génère une série triée d'assignations clé/valeur en appelant to_query(key)
sur ses valeurs. Ensuite, il joint le résultat avec "&":
{ c: 3, b: 2, a: 1 }.to_query # => "a=1&b=2&c=3"
La méthode Hash#to_query
accepte un espace de noms facultatif pour les clés:
{ id: 89, name: "John Smith" }.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
NOTE : Défini dans active_support/core_ext/object/to_query.rb
.
2.10 with_options
La méthode with_options
permet de regrouper des options communes dans une série d'appels de méthode.
Étant donné un hachage d'options par défaut, with_options
renvoie un objet proxy à un bloc. Dans le bloc, les méthodes appelées sur le proxy sont transmises au receveur avec leurs options fusionnées. Par exemple, vous pouvez vous débarrasser de la duplication dans :
class Account < ApplicationRecord
has_many :customers, dependent: :destroy
has_many :products, dependent: :destroy
has_many :invoices, dependent: :destroy
has_many :expenses, dependent: :destroy
end
de cette manière :
class Account < ApplicationRecord
with_options dependent: :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
assoc.has_many :expenses
end
end
Cette expression peut également transmettre un regroupement au lecteur. Par exemple, supposons que vous souhaitiez envoyer une newsletter dont la langue dépend de l'utilisateur. Vous pouvez regrouper les éléments dépendant de la langue quelque part dans le mailer de cette manière :
I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
subject i18n.t :subject
body i18n.t :body, user_name: user.name
end
CONSEIL : Comme with_options
transmet les appels à son receveur, ils peuvent être imbriqués. Chaque niveau d'imbrication fusionnera les valeurs par défaut héritées en plus des siennes propres.
NOTE : Défini dans active_support/core_ext/object/with_options.rb
.
2.11 Support JSON
Active Support fournit une meilleure implémentation de to_json
que la gemme json
ne le fait normalement pour les objets Ruby. Cela est dû au fait que certaines classes, comme Hash
et Process::Status
, nécessitent un traitement spécial pour fournir une représentation JSON appropriée.
NOTE : Défini dans active_support/core_ext/object/json.rb
.
2.12 Variables d'instance
Active Support fournit plusieurs méthodes pour faciliter l'accès aux variables d'instance.
2.12.1 instance_values
La méthode instance_values
renvoie un hachage qui fait correspondre les noms de variables d'instance sans "@" à leurs valeurs correspondantes. Les clés sont des chaînes de caractères :
class C
def initialize(x, y)
@x, @y = x, y
end
end
C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
NOTE : Défini dans active_support/core_ext/object/instance_variables.rb
.
2.12.2 instance_variable_names
La méthode instance_variable_names
renvoie un tableau. Chaque nom inclut le signe "@".
class C
def initialize(x, y)
@x, @y = x, y
end
end
C.new(0, 1).instance_variable_names # => ["@x", "@y"]
NOTE : Défini dans active_support/core_ext/object/instance_variables.rb
.
2.13 Suppression des avertissements et des exceptions
Les méthodes silence_warnings
et enable_warnings
modifient la valeur de $VERBOSE
en conséquence pendant la durée de leur bloc, puis la réinitialisent :
silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
Il est également possible de supprimer les exceptions avec suppress
. Cette méthode reçoit un nombre arbitraire de classes d'exceptions. Si une exception est levée pendant l'exécution du bloc et qu'elle est kind_of?
l'un des arguments, suppress
la capture et la renvoie silencieusement. Sinon, l'exception n'est pas capturée :
```ruby
Si l'utilisateur est verrouillé, l'incrément est perdu, pas de problème majeur.
suppress(ActiveRecord::StaleObjectError) do current_user.increment! :visits end ```
NOTE : Défini dans active_support/core_ext/kernel/reporting.rb
.
2.14 in?
Le prédicat in?
teste si un objet est inclus dans un autre objet. Une exception ArgumentError
sera levée si l'argument passé ne répond pas à include?
.
Exemples de in?
:
1.in?([1, 2]) # => true
"lo".in?("hello") # => true
25.in?(30..50) # => false
1.in?(1) # => ArgumentError
NOTE : Défini dans active_support/core_ext/object/inclusion.rb
.
3 Extensions à Module
3.1 Attributs
3.1.1 alias_attribute
Les attributs du modèle ont un lecteur, un écrivain et un prédicat. Vous pouvez créer un alias pour un attribut du modèle en utilisant alias_attribute
, qui définit automatiquement les trois méthodes correspondantes pour vous. Comme pour les autres méthodes d'aliasing, le nouveau nom est le premier argument et l'ancien nom est le deuxième (un moyen mnémotechnique est de les mettre dans le même ordre que si vous faisiez une affectation) :
class User < ApplicationRecord
# Vous pouvez vous référer à la colonne email en tant que "login".
# Cela peut être utile pour le code d'authentification.
alias_attribute :login, :email
end
NOTE : Défini dans active_support/core_ext/module/aliasing.rb
.
3.1.2 Attributs internes
Lorsque vous définissez un attribut dans une classe destinée à être sous-classée, les collisions de noms sont un risque. Cela est particulièrement important pour les bibliothèques.
Active Support définit les macros attr_internal_reader
, attr_internal_writer
et attr_internal_accessor
. Elles fonctionnent comme leurs homologues Ruby attr_*
, à la différence qu'elles nomment la variable d'instance sous-jacente de manière à réduire les risques de collision.
La macro attr_internal
est un synonyme de attr_internal_accessor
:
# bibliothèque
class ThirdPartyLibrary::Crawler
attr_internal :log_level
end
# code client
class MyCrawler < ThirdPartyLibrary::Crawler
attr_accessor :log_level
end
Dans l'exemple précédent, il se peut que :log_level
n'appartienne pas à l'interface publique de la bibliothèque et qu'il ne soit utilisé que pour le développement. Le code client, ignorant le risque de conflit, sous-classe et définit son propre :log_level
. Grâce à attr_internal
, il n'y a pas de collision.
Par défaut, la variable d'instance interne est nommée avec un tiret bas en préfixe, @_log_level
dans l'exemple ci-dessus. Cela peut être configuré via Module.attr_internal_naming_format
, vous pouvez passer n'importe quelle chaîne de format sprintf
avec un @
en préfixe et un %s
quelque part, où le nom sera placé. La valeur par défaut est "@_%s"
.
Rails utilise des attributs internes à quelques endroits, par exemple pour les vues :
module ActionView
class Base
attr_internal :captures
attr_internal :request, :layout
attr_internal :controller, :template
end
end
NOTE : Défini dans active_support/core_ext/module/attr_internal.rb
.
3.1.3 Attributs de module
Les macros mattr_reader
, mattr_writer
et mattr_accessor
sont identiques aux macros cattr_*
définies pour les classes. En fait, les macros cattr_*
ne sont que des alias des macros mattr_*
. Voir Attributs de classe.
Par exemple, l'API pour le journal de Active Storage est générée avec mattr_accessor
:
module ActiveStorage
mattr_accessor :logger
end
NOTE : Défini dans active_support/core_ext/module/attribute_accessors.rb
.
3.2 Parents
3.2.1 module_parent
La méthode module_parent
sur un module nommé imbriqué renvoie le module qui contient sa constante correspondante :
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.module_parent # => X::Y
M.module_parent # => X::Y
Si le module est anonyme ou appartient au niveau supérieur, module_parent
renvoie Object
.
AVERTISSEMENT: Notez que dans ce cas, module_parent_name
renvoie nil
.
Défini dans active_support/core_ext/module/introspection.rb
.
3.2.2 module_parent_name
La méthode module_parent_name
sur un module nommé imbriqué renvoie le nom entièrement qualifié du module qui contient sa constante correspondante:
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.module_parent_name # => "X::Y"
M.module_parent_name # => "X::Y"
Pour les modules de niveau supérieur ou anonymes, module_parent_name
renvoie nil
.
AVERTISSEMENT: Notez que dans ce cas, module_parent
renvoie Object
.
Défini dans active_support/core_ext/module/introspection.rb
.
3.2.3 module_parents
La méthode module_parents
appelle module_parent
sur le receveur et remonte jusqu'à ce que Object
soit atteint. La chaîne est renvoyée dans un tableau, du bas vers le haut:
module X
module Y
module Z
end
end
end
M = X::Y::Z
X::Y::Z.module_parents # => [X::Y, X, Object]
M.module_parents # => [X::Y, X, Object]
Défini dans active_support/core_ext/module/introspection.rb
.
3.3 Anonyme
Un module peut avoir ou non un nom:
module M
end
M.name # => "M"
N = Module.new
N.name # => "N"
Module.new.name # => nil
Vous pouvez vérifier si un module a un nom avec le prédicat anonymous?
:
module M
end
M.anonymous? # => false
Module.new.anonymous? # => true
Notez que le fait d'être inaccessible n'implique pas d'être anonyme:
module M
end
m = Object.send(:remove_const, :M)
m.anonymous? # => false
bien qu'un module anonyme soit inaccessible par définition.
Défini dans active_support/core_ext/module/anonymous.rb
.
3.4 Délégation de méthode
3.4.1 delegate
La macro delegate
offre un moyen facile de déléguer des méthodes.
Imaginons que les utilisateurs dans une application aient des informations de connexion dans le modèle User
mais un nom et d'autres données dans un modèle séparé Profile
:
class User < ApplicationRecord
has_one :profile
end
Avec cette configuration, vous obtenez le nom d'un utilisateur via son profil, user.profile.name
, mais il pourrait être pratique de pouvoir toujours accéder à cet attribut directement:
class User < ApplicationRecord
has_one :profile
def name
profile.name
end
end
C'est ce que fait delegate
pour vous:
class User < ApplicationRecord
has_one :profile
delegate :name, to: :profile
end
C'est plus court et l'intention est plus évidente.
La méthode doit être publique dans la cible.
La macro delegate
accepte plusieurs méthodes:
delegate :name, :age, :address, :twitter, to: :profile
Lorsqu'elle est interpolée dans une chaîne, l'option :to
doit devenir une expression qui s'évalue à l'objet auquel la méthode est déléguée. Typiquement une chaîne de caractères ou un symbole. Une telle expression est évaluée dans le contexte du receveur:
# délègue à la constante Rails
delegate :logger, to: :Rails
# délègue à la classe du receveur
delegate :table_name, to: :class
AVERTISSEMENT: Si l'option :prefix
est true
, cela est moins générique, voir ci-dessous.
Par défaut, si la délégation génère une NoMethodError
et que la cible est nil
, l'exception est propagée. Vous pouvez demander que nil
soit renvoyé à la place avec l'option :allow_nil
:
delegate :name, to: :profile, allow_nil: true
Avec :allow_nil
, l'appel user.name
renvoie nil
si l'utilisateur n'a pas de profil.
L'option :prefix
ajoute un préfixe au nom de la méthode générée. Cela peut être pratique, par exemple, pour obtenir un meilleur nom:
ruby
delegate :street, to: :address, prefix: true
L'exemple précédent génère address_street
plutôt que street
.
AVERTISSEMENT: Dans ce cas, le nom de la méthode générée est composé des noms de l'objet cible et de la méthode cible, l'option :to
doit donc être un nom de méthode.
Un préfixe personnalisé peut également être configuré:
delegate :size, to: :attachment, prefix: :avatar
Dans l'exemple précédent, la macro génère avatar_size
plutôt que size
.
L'option :private
modifie la portée des méthodes:
delegate :date_of_birth, to: :profile, private: true
Les méthodes déléguées sont publiques par défaut. Passez private: true
pour changer cela.
Défini dans active_support/core_ext/module/delegation.rb
3.4.2 delegate_missing_to
Imaginez que vous souhaitez déléguer tout ce qui manque à l'objet User
à l'objet Profile
. La macro delegate_missing_to
vous permet de mettre en œuvre cela facilement:
class User < ApplicationRecord
has_one :profile
delegate_missing_to :profile
end
La cible peut être n'importe quoi de callable dans l'objet, par exemple des variables d'instance, des méthodes, des constantes, etc. Seules les méthodes publiques de la cible sont déléguées.
Défini dans active_support/core_ext/module/delegation.rb
.
3.5 Redéfinition des méthodes
Il existe des cas où vous devez définir une méthode avec define_method
, mais vous ne savez pas si une méthode portant ce nom existe déjà. Si c'est le cas, un avertissement est émis s'ils sont activés. Ce n'est pas grave, mais ce n'est pas propre non plus.
La méthode redefine_method
évite un tel avertissement potentiel, en supprimant la méthode existante si nécessaire.
Vous pouvez également utiliser silence_redefinition_of_method
si vous avez besoin de définir la méthode de remplacement vous-même (parce que vous utilisez delegate
, par exemple).
Défini dans active_support/core_ext/module/redefine_method.rb
.
4 Extensions à Class
4.1 Attributs de classe
4.1.1 class_attribute
La méthode class_attribute
déclare un ou plusieurs attributs de classe héritables qui peuvent être remplacés à n'importe quel niveau de la hiérarchie.
class A
class_attribute :x
end
class B < A; end
class C < B; end
A.x = :a
B.x # => :a
C.x # => :a
B.x = :b
A.x # => :a
C.x # => :b
C.x = :c
A.x # => :a
B.x # => :b
Par exemple, ActionMailer::Base
définit:
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" ]
}.freeze
Ils peuvent également être accédés et remplacés au niveau de l'instance.
A.x = 1
a1 = A.new
a2 = A.new
a2.x = 2
a1.x # => 1, provient de A
a2.x # => 2, remplacé dans a2
La génération de la méthode d'instance writer peut être empêchée en définissant l'option :instance_writer
sur false
.
module ActiveRecord
class Base
class_attribute :table_name_prefix, instance_writer: false, default: "my"
end
end
Un modèle peut trouver cette option utile comme moyen d'empêcher l'attribution en masse de définir l'attribut.
La génération de la méthode d'instance reader peut être empêchée en définissant l'option :instance_reader
sur false
.
class A
class_attribute :x, instance_reader: false
end
A.new.x = 1
A.new.x # NoMethodError
Pour plus de commodité, class_attribute
définit également un prédicat d'instance qui est la double négation de ce que renvoie le lecteur d'instance. Dans les exemples ci-dessus, il serait appelé x?
.
Lorsque :instance_reader
est false
, le prédicat d'instance renvoie une NoMethodError
tout comme la méthode de lecture.
Si vous ne souhaitez pas utiliser le prédicat d'instance, passez instance_predicate: false
et il ne sera pas défini.
NOTE : Défini dans active_support/core_ext/class/attribute.rb
.
4.1.2 cattr_reader
, cattr_writer
et cattr_accessor
Les macros cattr_reader
, cattr_writer
et cattr_accessor
sont analogues à leurs homologues attr_*
mais pour les classes. Elles initialisent une variable de classe à nil
sauf si elle existe déjà, et génèrent les méthodes de classe correspondantes pour y accéder :
class MysqlAdapter < AbstractAdapter
# Génère les méthodes de classe pour accéder à @@emulate_booleans.
cattr_accessor :emulate_booleans
end
De plus, vous pouvez passer un bloc à cattr_*
pour configurer l'attribut avec une valeur par défaut :
class MysqlAdapter < AbstractAdapter
# Génère les méthodes de classe pour accéder à @@emulate_booleans avec une valeur par défaut de true.
cattr_accessor :emulate_booleans, default: true
end
Des méthodes d'instance sont également créées pour plus de commodité, ce sont simplement des proxies vers l'attribut de classe. Ainsi, les instances peuvent modifier l'attribut de classe, mais ne peuvent pas le remplacer comme c'est le cas avec class_attribute
(voir ci-dessus). Par exemple, étant donné
module ActionView
class Base
cattr_accessor :field_error_proc, default: Proc.new { ... }
end
end
nous pouvons accéder à field_error_proc
dans les vues.
La génération de la méthode de lecture de l'instance peut être empêchée en définissant :instance_reader
sur false
et la génération de la méthode d'écriture de l'instance peut être empêchée en définissant :instance_writer
sur false
. La génération des deux méthodes peut être empêchée en définissant :instance_accessor
sur false
. Dans tous les cas, la valeur doit être exactement false
et non une fausse valeur quelconque.
module A
class B
# Aucune méthode de lecture de l'instance first_name n'est générée.
cattr_accessor :first_name, instance_reader: false
# Aucune méthode d'écriture de l'instance last_name= n'est générée.
cattr_accessor :last_name, instance_writer: false
# Aucune méthode de lecture de l'instance surname ou de l'écriture surname= n'est générée.
cattr_accessor :surname, instance_accessor: false
end
end
Un modèle peut trouver utile de définir :instance_accessor
sur false
comme moyen d'empêcher l'assignation en masse de définir l'attribut.
NOTE : Défini dans active_support/core_ext/module/attribute_accessors.rb
.
4.2 Sous-classes et descendants
4.2.1 subclasses
La méthode subclasses
renvoie les sous-classes du receveur :
class C; end
C.subclasses # => []
class B < C; end
C.subclasses # => [B]
class A < B; end
C.subclasses # => [B]
class D < C; end
C.subclasses # => [B, D]
L'ordre dans lequel ces classes sont renvoyées n'est pas spécifié.
NOTE : Défini dans active_support/core_ext/class/subclasses.rb
.
4.2.2 descendants
La méthode descendants
renvoie toutes les classes qui sont <
que son receveur :
class C; end
C.descendants # => []
class B < C; end
C.descendants # => [B]
class A < B; end
C.descendants # => [B, A]
class D < C; end
C.descendants # => [B, A, D]
L'ordre dans lequel ces classes sont renvoyées n'est pas spécifié.
NOTE : Défini dans active_support/core_ext/class/subclasses.rb
.
5 Extensions à String
5.1 Sécurité de la sortie
5.1.1 Motivation
Insérer des données dans des modèles HTML nécessite une attention particulière. Par exemple, vous ne pouvez pas simplement interpoler @review.title
tel quel dans une page HTML. Pour une chose, si le titre de la revue est "Flanagan & Matz rules!", la sortie ne sera pas bien formée car un esperluette doit être échappée en "&". De plus, selon l'application, cela peut constituer une grande faille de sécurité car les utilisateurs peuvent injecter du code HTML malveillant en définissant un titre de revue spécialement conçu. Consultez la section sur les attaques de type cross-site scripting dans le guide de sécurité pour plus d'informations sur les risques.
5.1.2 Chaînes de caractères sécurisées
Active Support a le concept de chaînes de caractères (html) sécurisées. Une chaîne de caractères sécurisée est marquée comme pouvant être insérée dans du HTML telle quelle. Elle est considérée comme fiable, que ce soit échappée ou non.
Par défaut, les chaînes de caractères sont considérées comme non sécurisées :
"".html_safe? # => false
Vous pouvez obtenir une chaîne de caractères sécurisée à partir d'une chaîne donnée avec la méthode html_safe
:
s = "".html_safe
s.html_safe? # => true
Il est important de comprendre que html_safe
ne réalise aucune échappement, c'est simplement une assertion :
s = "<script>...</script>".html_safe
s.html_safe? # => true
s # => "<script>...</script>"
Il est de votre responsabilité de vous assurer que l'appel à html_safe
sur une chaîne particulière est correct.
Si vous ajoutez une chaîne à une chaîne sécurisée, que ce soit en place avec concat
/<<
, ou avec +
, le résultat est une chaîne sécurisée. Les arguments non sécurisés sont échappés :
"".html_safe + "<" # => "<"
Les arguments sécurisés sont directement ajoutés :
"".html_safe + "<".html_safe # => "<"
Ces méthodes ne doivent pas être utilisées dans les vues ordinaires. Les valeurs non sécurisées sont automatiquement échappées :
<%= @review.title %> <%# correct, échappé si nécessaire %>
Pour insérer quelque chose tel quel, utilisez l'aide raw
plutôt que d'appeler html_safe
:
<%= raw @cms.current_template %> <%# insère @cms.current_template tel quel %>
ou, de manière équivalente, utilisez <%==
:
<%== @cms.current_template %> <%# insère @cms.current_template tel quel %>
L'aide raw
appelle html_safe
pour vous :
def raw(stringish)
stringish.to_s.html_safe
end
NOTE : Défini dans active_support/core_ext/string/output_safety.rb
.
5.1.3 Transformation
En règle générale, à l'exception peut-être de la concaténation comme expliqué ci-dessus, toute méthode qui peut modifier une chaîne de caractères vous donne une chaîne non sécurisée. Il s'agit de downcase
, gsub
, strip
, chomp
, underscore
, etc.
Dans le cas des transformations en place comme gsub!
, le récepteur lui-même devient non sécurisé.
INFO : Le bit de sécurité est toujours perdu, que la transformation ait effectivement changé quelque chose ou non.
5.1.4 Conversion et coercition
Appeler to_s
sur une chaîne de caractères sécurisée renvoie une chaîne de caractères sécurisée, mais la coercition avec to_str
renvoie une chaîne de caractères non sécurisée.
5.1.5 Copie
Appeler dup
ou clone
sur des chaînes de caractères sécurisées donne des chaînes de caractères sécurisées.
5.2 remove
La méthode remove
supprime toutes les occurrences du motif :
"Hello World".remove(/Hello /) # => "World"
Il existe également la version destructive String#remove!
.
NOTE : Défini dans active_support/core_ext/string/filters.rb
.
5.3 squish
La méthode squish
supprime les espaces vides en début et en fin de chaîne, et remplace les séries d'espaces vides par un seul espace :
" \n foo\n\r \t bar \n".squish # => "foo bar"
Il existe également la version destructive String#squish!
.
Notez qu'elle gère à la fois les espaces vides ASCII et Unicode.
NOTE : Défini dans active_support/core_ext/string/filters.rb
.
5.4 truncate
La méthode truncate
renvoie une copie de la chaîne de caractères tronquée après une longueur donnée :
"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."
L'ellipse peut être personnalisée avec l'option :omission
:
"Oh dear! Oh dear! I shall be late!".truncate(20, omission: '…')
# => "Oh dear! Oh …"
Notez en particulier que la troncature prend en compte la longueur de la chaîne d'omission.
Passez un :separator
pour tronquer la chaîne à une rupture naturelle :
```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..."
L'option `:separator` peut être une expression régulière :
```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."
Dans les exemples ci-dessus, "dear" est coupé en premier, mais :separator
l'empêche ensuite.
NOTE : Défini dans active_support/core_ext/string/filters.rb
.
5.5 truncate_bytes
La méthode truncate_bytes
renvoie une copie de son objet tronqué à un maximum de bytesize
octets :
"👍👍👍👍".truncate_bytes(15)
# => "👍👍👍…"
L'omission peut être personnalisée avec l'option :omission
:
"👍👍👍👍".truncate_bytes(15, omission: "🖖")
# => "👍👍🖖"
NOTE : Défini dans active_support/core_ext/string/filters.rb
.
5.6 truncate_words
La méthode truncate_words
renvoie une copie de son objet tronqué après un certain nombre de mots :
"Oh dear! Oh dear! I shall be late!".truncate_words(4)
# => "Oh dear! Oh dear!..."
L'omission peut être personnalisée avec l'option :omission
:
"Oh dear! Oh dear! I shall be late!".truncate_words(4, omission: '…')
# => "Oh dear! Oh dear!…"
Passez un :separator
pour tronquer la chaîne à une rupture naturelle :
"Oh dear! Oh dear! I shall be late!".truncate_words(3, separator: '!')
# => "Oh dear! Oh dear! I shall be late..."
L'option :separator
peut être une expression régulière :
"Oh dear! Oh dear! I shall be late!".truncate_words(4, separator: /\s/)
# => "Oh dear! Oh dear!..."
NOTE : Défini dans active_support/core_ext/string/filters.rb
.
5.7 inquiry
La méthode inquiry
convertit une chaîne de caractères en un objet StringInquirer
, rendant les comparaisons d'égalité plus jolies.
"production".inquiry.production? # => true
"active".inquiry.inactive? # => false
NOTE : Défini dans active_support/core_ext/string/inquiry.rb
.
5.8 starts_with?
et ends_with?
Active Support définit des alias à la troisième personne de String#start_with?
et String#end_with?
:
"foo".starts_with?("f") # => true
"foo".ends_with?("o") # => true
NOTE : Défini dans active_support/core_ext/string/starts_ends_with.rb
.
5.9 strip_heredoc
La méthode strip_heredoc
supprime l'indentation dans les heredocs.
Par exemple, dans
if options[:usage]
puts <<-USAGE.strip_heredoc
This command does such and such.
Supported options are:
-h This message
...
USAGE
end
l'utilisateur verra le message d'utilisation aligné contre la marge gauche.
Techniquement, elle recherche la ligne avec le moins d'indentation dans toute la chaîne, et supprime cette quantité d'espaces en début de ligne.
NOTE : Défini dans active_support/core_ext/string/strip.rb
.
5.10 indent
La méthode indent
indente les lignes de l'objet :
<<EOS.indent(2)
def some_method
some_code
end
EOS
# =>
def some_method
some_code
end
Le deuxième argument, indent_string
, spécifie quelle chaîne d'indentation utiliser. Par défaut, c'est nil
, ce qui indique à la méthode de deviner en regardant la première ligne indentée, et de revenir à un espace s'il n'y en a pas.
" foo".indent(2) # => " foo"
"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
"foo".indent(2, "\t") # => "\t\tfoo"
Bien que indent_string
soit généralement un espace ou une tabulation, il peut être n'importe quelle chaîne de caractères.
Le troisième argument, indent_empty_lines
, est un indicateur qui indique si les lignes vides doivent être indentées. Par défaut, c'est false.
"foo\n\nbar".indent(2) # => " foo\n\n bar"
"foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
La méthode indent!
effectue l'indentation sur place.
NOTE : Défini dans active_support/core_ext/string/indent.rb
.
5.11 Accès
5.11.1 at(position)
La méthode at
renvoie le caractère de la chaîne de caractères à la position position
:
"hello".at(0) # => "h"
"hello".at(4) # => "o"
"hello".at(-1) # => "o"
"hello".at(10) # => nil
NOTE : Défini dans active_support/core_ext/string/access.rb
.
5.11.2 from(position)
La méthode from
renvoie la sous-chaîne de caractères de la chaîne de caractères à partir de la position position
:
"hello".from(0) # => "hello"
"hello".from(2) # => "llo"
"hello".from(-2) # => "lo"
"hello".from(10) # => nil
NOTE : Défini dans active_support/core_ext/string/access.rb
.
5.11.3 to(position)
La méthode to
renvoie la sous-chaîne de caractères de la chaîne de caractères jusqu'à la position position
:
"hello".to(0) # => "h"
"hello".to(2) # => "hel"
"hello".to(-2) # => "hell"
"hello".to(10) # => "hello"
NOTE : Défini dans active_support/core_ext/string/access.rb
.
5.11.4 first(limit = 1)
La méthode first
renvoie une sous-chaîne de caractères contenant les limit
premiers caractères de la chaîne de caractères.
L'appel str.first(n)
est équivalent à str.to(n-1)
si n
> 0, et renvoie une chaîne vide pour n
== 0.
NOTE : Défini dans active_support/core_ext/string/access.rb
.
5.11.5 last(limit = 1)
La méthode last
renvoie une sous-chaîne de caractères contenant les limit
derniers caractères de la chaîne de caractères.
L'appel str.last(n)
est équivalent à str.from(-n)
si n
> 0, et renvoie une chaîne vide pour n
== 0.
NOTE : Défini dans active_support/core_ext/string/access.rb
.
5.12 Inflections
5.12.1 pluralize
La méthode pluralize
renvoie le pluriel de son objet :
"table".pluralize # => "tables"
"ruby".pluralize # => "rubies"
"equipment".pluralize # => "equipment"
Comme le montre l'exemple précédent, Active Support connaît certains pluriels irréguliers et des noms non dénombrables. Les règles intégrées peuvent être étendues dans config/initializers/inflections.rb
. Ce fichier est généré par défaut par la commande rails new
et contient des instructions en commentaires.
pluralize
peut également prendre un paramètre optionnel count
. Si count == 1
, la forme singulière sera renvoyée. Pour toute autre valeur de count
, la forme plurielle sera renvoyée :
"dude".pluralize(0) # => "dudes"
"dude".pluralize(1) # => "dude"
"dude".pluralize(2) # => "dudes"
Active Record utilise cette méthode pour calculer le nom de table par défaut correspondant à un modèle :
# active_record/model_schema.rb
def undecorated_table_name(model_name)
table_name = model_name.to_s.demodulize.underscore
pluralize_table_names ? table_name.pluralize : table_name
end
NOTE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.2 singularize
La méthode singularize
est l'inverse de pluralize
:
"tables".singularize # => "table"
"rubies".singularize # => "ruby"
"equipment".singularize # => "equipment"
Les associations calculent le nom de la classe associée par défaut en utilisant cette méthode :
# active_record/reflection.rb
def derive_class_name
class_name = name.to_s.camelize
class_name = class_name.singularize if collection?
class_name
end
NOTE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.3 camelize
La méthode camelize
renvoie son objet en camel case :
"product".camelize # => "Product"
"admin_user".camelize # => "AdminUser"
En règle générale, vous pouvez considérer cette méthode comme celle qui transforme les chemins en noms de classes ou de modules Ruby, où les barres obliques séparent les espaces de noms :
"backoffice/session".camelize # => "Backoffice::Session"
Par exemple, Action Pack utilise cette méthode pour charger la classe qui fournit un certain magasin de session :
# action_controller/metal/session_management.rb
def session_store=(store)
@@session_store = store.is_a?(Symbol) ?
ActionDispatch::Session.const_get(store.to_s.camelize) :
store
end
camelize
accepte un argument optionnel, qui peut être :upper
(par défaut) ou :lower
. Avec ce dernier, la première lettre devient en minuscule :
ruby
"visual_effect".camelize(:lower) # => "visualEffect"
Cela peut être pratique pour calculer des noms de méthodes dans une langue qui suit cette convention, par exemple JavaScript.
En règle générale, vous pouvez considérer camelize
comme l'inverse de underscore
, bien qu'il existe des cas où cela ne s'applique pas: "SSLError".underscore.camelize
renvoie "SslError"
. Pour prendre en charge des cas comme celui-ci, Active Support vous permet de spécifier des acronymes dans config/initializers/inflections.rb
:
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'SSL'
end
"SSLError".underscore.camelize # => "SSLError"
camelize
est un alias de camelcase
.
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.4 underscore
La méthode underscore
fait l'inverse, du camel case aux chemins:
"Product".underscore # => "product"
"AdminUser".underscore # => "admin_user"
Convertit également "::" en "/":
"Backoffice::Session".underscore # => "backoffice/session"
et comprend les chaînes qui commencent par une minuscule:
"visualEffect".underscore # => "visual_effect"
underscore
n'accepte aucun argument.
Rails utilise underscore
pour obtenir un nom en minuscules pour les classes de contrôleur:
# actionpack/lib/abstract_controller/base.rb
def controller_path
@controller_path ||= name.delete_suffix("Controller").underscore
end
Par exemple, cette valeur est celle que vous obtenez dans params[:controller]
.
En règle générale, vous pouvez considérer underscore
comme l'inverse de camelize
, bien qu'il existe des cas où cela ne s'applique pas. Par exemple, "SSLError".underscore.camelize
renvoie "SslError"
.
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.5 titleize
La méthode titleize
met en majuscule les mots dans la chaîne:
"alice in wonderland".titleize # => "Alice In Wonderland"
"fermat's enigma".titleize # => "Fermat's Enigma"
titleize
est un alias de titlecase
.
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.6 dasherize
La méthode dasherize
remplace les underscores dans la chaîne par des tirets:
"name".dasherize # => "name"
"contact_data".dasherize # => "contact-data"
Le sérialiseur XML des modèles utilise cette méthode pour transformer les noms de nœuds en tirets:
# active_model/serializers/xml.rb
def reformat_name(name)
name = name.camelize if camelize?
dasherize? ? name.dasherize : name
end
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.7 demodulize
Étant donné une chaîne avec un nom de constante qualifié, demodulize
renvoie le nom de la constante lui-même, c'est-à-dire la partie la plus à droite:
"Product".demodulize # => "Product"
"Backoffice::UsersController".demodulize # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
"::Inflections".demodulize # => "Inflections"
"".demodulize # => ""
Active Record utilise par exemple cette méthode pour calculer le nom d'une colonne de cache de compteur:
# active_record/reflection.rb
def counter_cache_column
if options[:counter_cache] == true
"#{active_record.name.demodulize.underscore.pluralize}_count"
elsif options[:counter_cache]
options[:counter_cache]
end
end
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.8 deconstantize
Étant donné une chaîne avec une expression de référence de constante qualifiée, deconstantize
supprime le segment le plus à droite, laissant généralement le nom du conteneur de la constante:
"Product".deconstantize # => ""
"Backoffice::UsersController".deconstantize # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"
Défini dans active_support/core_ext/string/inflections.rb
.
5.12.9 parameterize
La méthode parameterize
normalise la chaîne de manière à pouvoir être utilisée dans les URL conviviales.
"John Smith".parameterize # => "john-smith"
"Kurt Gödel".parameterize # => "kurt-godel"
Pour conserver la casse de la chaîne, définissez l'argument preserve_case
sur true. Par défaut, preserve_case
est défini sur false.
"John Smith".parameterize(preserve_case: true) # => "John-Smith"
"Kurt Gödel".parameterize(preserve_case: true) # => "Kurt-Godel"
Pour utiliser un séparateur personnalisé, remplacez l'argument separator
.
"John Smith".parameterize(separator: "_") # => "john_smith"
"Kurt Gödel".parameterize(separator: "_") # => "kurt_godel"
REMARQUE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.10 tableize
La méthode tableize
est underscore
suivie de pluralize
.
"Personne".tableize # => "people"
"Facture".tableize # => "invoices"
"LigneFacture".tableize # => "invoice_lines"
En règle générale, tableize
renvoie le nom de la table correspondant à un modèle donné pour les cas simples. L'implémentation réelle dans Active Record n'est pas simplement tableize
, car elle démodule également le nom de la classe et vérifie quelques options qui peuvent affecter la chaîne renvoyée.
REMARQUE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.11 classify
La méthode classify
est l'inverse de tableize
. Elle vous donne le nom de classe correspondant à un nom de table :
"people".classify # => "Personne"
"invoices".classify # => "Facture"
"invoice_lines".classify # => "LigneFacture"
La méthode comprend les noms de table qualifiés :
"highrise_production.companies".classify # => "Societe"
Notez que classify
renvoie un nom de classe sous forme de chaîne. Vous pouvez obtenir l'objet de classe réel en invoquant constantize
dessus, expliqué ensuite.
REMARQUE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.12 constantize
La méthode constantize
résout l'expression de référence constante dans son receveur :
"Integer".constantize # => Integer
module M
X = 1
end
"M::X".constantize # => 1
Si la chaîne ne correspond à aucune constante connue, ou si son contenu n'est même pas un nom de constante valide, constantize
génère une NameError
.
La résolution du nom de constante par constantize
commence toujours au niveau supérieur de Object
, même s'il n'y a pas de "::" au début.
X = :in_Object
module M
X = :in_M
X # => :in_M
"::X".constantize # => :in_Object
"X".constantize # => :in_Object (!)
end
Ainsi, en général, cela n'est pas équivalent à ce que Ruby ferait au même endroit, si une vraie constante était évaluée.
Les cas de test des mailers obtiennent le mailer testé à partir du nom de la classe de test en utilisant constantize
:
# action_mailer/test_case.rb
def determine_default_mailer(name)
name.delete_suffix("Test").constantize
rescue NameError => e
raise NonInferrableMailerError.new(name)
end
REMARQUE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.13 humanize
La méthode humanize
ajuste un nom d'attribut pour l'affichage aux utilisateurs finaux.
Plus précisément, elle effectue ces transformations :
- Applique les règles d'inflection humaine à l'argument.
- Supprime les tirets bas initiaux, le cas échéant.
- Supprime le suffixe "_id" s'il est présent.
- Remplace les tirets bas par des espaces, le cas échéant.
- Met en minuscule tous les mots sauf les acronymes.
- Met en majuscule le premier mot.
La majuscule du premier mot peut être désactivée en définissant l'option :capitalize
sur false (par défaut, true).
"name".humanize # => "Nom"
"author_id".humanize # => "Auteur"
"author_id".humanize(capitalize: false) # => "auteur"
"comments_count".humanize # => "Nombre de commentaires"
"_id".humanize # => "Id"
Si "SSL" est défini comme un acronyme :
'ssl_error'.humanize # => "Erreur SSL"
La méthode d'aide full_messages
utilise humanize
comme solution de secours pour inclure les noms d'attributs :
def full_messages
map { |attribute, message| full_message(attribute, message) }
end
def full_message
# ...
attr_name = attribute.to_s.tr('.', '_').humanize
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
# ...
end
REMARQUE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.14 foreign_key
La méthode foreign_key
donne le nom de la colonne de clé étrangère à partir d'un nom de classe. Pour ce faire, elle démodule, ajoute des tirets bas et ajoute "_id" :
"User".foreign_key # => "user_id"
"InvoiceLine".foreign_key # => "invoice_line_id"
"Admin::Session".foreign_key # => "session_id"
Passez un argument faux si vous ne voulez pas de tiret bas dans "_id":
"User".foreign_key(false) # => "userid"
Les associations utilisent cette méthode pour déduire les clés étrangères, par exemple has_one
et has_many
font cela:
# active_record/associations.rb
foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
NOTE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.15 upcase_first
La méthode upcase_first
met en majuscule la première lettre du récepteur :
"employee salary".upcase_first # => "Employee salary"
"".upcase_first # => ""
NOTE : Défini dans active_support/core_ext/string/inflections.rb
.
5.12.16 downcase_first
La méthode downcase_first
convertit la première lettre du récepteur en minuscule :
"If I had read Alice in Wonderland".downcase_first # => "if I had read Alice in Wonderland"
"".downcase_first # => ""
NOTE : Défini dans active_support/core_ext/string/inflections.rb
.
5.13 Conversions
5.13.1 to_date
, to_time
, to_datetime
Les méthodes to_date
, to_time
et to_datetime
sont essentiellement des enveloppes pratiques autour de Date._parse
:
"2010-07-27".to_date # => Tue, 27 Jul 2010
"2010-07-27 23:37:00".to_time # => 2010-07-27 23:37:00 +0200
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000
to_time
reçoit un argument facultatif :utc
ou :local
, pour indiquer dans quel fuseau horaire vous voulez l'heure :
"2010-07-27 23:42:00".to_time(:utc) # => 2010-07-27 23:42:00 UTC
"2010-07-27 23:42:00".to_time(:local) # => 2010-07-27 23:42:00 +0200
La valeur par défaut est :local
.
Veuillez vous référer à la documentation de Date._parse
pour plus de détails.
INFO : Les trois renvoient nil
pour les récepteurs vides.
NOTE : Défini dans active_support/core_ext/string/conversions.rb
.
6 Extensions à Symbol
6.1 starts_with?
et ends_with?
Active Support définit des alias à la troisième personne de Symbol#start_with?
et Symbol#end_with?
:
:foo.starts_with?("f") # => true
:foo.ends_with?("o") # => true
NOTE : Défini dans active_support/core_ext/symbol/starts_ends_with.rb
.
7 Extensions à Numeric
7.1 Bytes
Tous les nombres répondent à ces méthodes :
Elles renvoient la quantité correspondante d'octets, en utilisant un facteur de conversion de 1024 :
2.kilobytes # => 2048
3.megabytes # => 3145728
3.5.gigabytes # => 3758096384.0
-4.exabytes # => -4611686018427387904
Les formes singulières sont des alias, vous pouvez donc dire :
1.megabyte # => 1048576
NOTE : Défini dans active_support/core_ext/numeric/bytes.rb
.
7.2 Time
Les méthodes suivantes :
permettent les déclarations et les calculs de temps, comme 45.minutes + 2.hours + 4.weeks
. Leurs valeurs de retour peuvent également être ajoutées ou soustraites des objets Time.
Ces méthodes peuvent être combinées avec from_now
, ago
, etc, pour des calculs de date précis. Par exemple :
# équivalent à Time.current.advance(days: 1)
1.day.from_now
# équivalent à Time.current.advance(weeks: 2)
2.weeks.from_now
# équivalent à Time.current.advance(days: 4, weeks: 5)
(4.days + 5.weeks).from_now
ATTENTION. Pour d'autres durées, veuillez vous référer aux extensions de temps à Integer
.
NOTE : Défini dans active_support/core_ext/numeric/time.rb
.
7.3 Formatage
Permet le formatage des nombres de différentes manières.
Produire une représentation sous forme de chaîne d'un nombre en tant que numéro de téléphone :
5551234.to_fs(:phone)
# => 555-1234
1235551234.to_fs(:phone)
# => 123-555-1234
1235551234.to_fs(:phone, area_code: true)
# => (123) 555-1234
1235551234.to_fs(:phone, delimiter: " ")
# => 123 555 1234
1235551234.to_fs(:phone, area_code: true, extension: 555)
# => (123) 555-1234 x 555
1235551234.to_fs(:phone, country_code: 1)
# => +1-123-555-1234
Produire une représentation sous forme de chaîne d'un nombre en tant que devise :
1234567890.50.to_fs(:currency) # => $1,234,567,890.50
1234567890.506.to_fs(:currency) # => $1,234,567,890.51
1234567890.506.to_fs(:currency, precision: 3) # => $1,234,567,890.506
Produire une représentation sous forme de chaîne d'un nombre en pourcentage:
100.to_fs(:pourcentage)
# => 100.000%
100.to_fs(:pourcentage, precision: 0)
# => 100%
1000.to_fs(:pourcentage, delimiter: '.', separator: ',')
# => 1.000,000%
302.24398923423.to_fs(:pourcentage, precision: 5)
# => 302.24399%
Produire une représentation sous forme de chaîne d'un nombre en forme délimitée:
12345678.to_fs(:délimité) # => 12,345,678
12345678.05.to_fs(:délimité) # => 12,345,678.05
12345678.to_fs(:délimité, delimiter: ".") # => 12.345.678
12345678.to_fs(:délimité, delimiter: ",") # => 12,345,678
12345678.05.to_fs(:délimité, separator: " ") # => 12,345,678 05
Produire une représentation sous forme de chaîne d'un nombre arrondi à une précision:
111.2345.to_fs(:arrondi) # => 111.235
111.2345.to_fs(:arrondi, precision: 2) # => 111.23
13.to_fs(:arrondi, precision: 5) # => 13.00000
389.32314.to_fs(:arrondi, precision: 0) # => 389
111.2345.to_fs(:arrondi, significant: true) # => 111
Produire une représentation sous forme de chaîne d'un nombre en tant que nombre de bytes lisible par un humain:
123.to_fs(:taille_humaine) # => 123 Bytes
1234.to_fs(:taille_humaine) # => 1.21 KB
12345.to_fs(:taille_humaine) # => 12.1 KB
1234567.to_fs(:taille_humaine) # => 1.18 MB
1234567890.to_fs(:taille_humaine) # => 1.15 GB
1234567890123.to_fs(:taille_humaine) # => 1.12 TB
1234567890123456.to_fs(:taille_humaine) # => 1.1 PB
1234567890123456789.to_fs(:taille_humaine) # => 1.07 EB
Produire une représentation sous forme de chaîne d'un nombre en mots lisibles par un humain:
123.to_fs(:humain) # => "123"
1234.to_fs(:humain) # => "1.23 Thousand"
12345.to_fs(:humain) # => "12.3 Thousand"
1234567.to_fs(:humain) # => "1.23 Million"
1234567890.to_fs(:humain) # => "1.23 Billion"
1234567890123.to_fs(:humain) # => "1.23 Trillion"
1234567890123456.to_fs(:humain) # => "1.23 Quadrillion"
Défini dans active_support/core_ext/numeric/conversions.rb
.
8 Extensions à Integer
8.1 multiple_of?
La méthode multiple_of?
teste si un entier est un multiple de l'argument:
2.multiple_of?(1) # => true
1.multiple_of?(2) # => false
Défini dans active_support/core_ext/integer/multiple.rb
.
8.2 ordinal
La méthode ordinal
renvoie la chaîne de suffixe ordinal correspondant à l'entier:
1.ordinal # => "st"
2.ordinal # => "nd"
53.ordinal # => "rd"
2009.ordinal # => "th"
-21.ordinal # => "st"
-134.ordinal # => "th"
Défini dans active_support/core_ext/integer/inflections.rb
.
8.3 ordinalize
La méthode ordinalize
renvoie la chaîne ordinale correspondant à l'entier. En comparaison, notez que la méthode ordinal
renvoie seulement la chaîne de suffixe.
1.ordinalize # => "1st"
2.ordinalize # => "2nd"
53.ordinalize # => "53rd"
2009.ordinalize # => "2009th"
-21.ordinalize # => "-21st"
-134.ordinalize # => "-134th"
Défini dans active_support/core_ext/integer/inflections.rb
.
8.4 Time
Les méthodes suivantes:
permettent les déclarations et les calculs de temps, comme 4.months + 5.years
. Leurs valeurs de retour peuvent également être ajoutées ou soustraites des objets Time.
Ces méthodes peuvent être combinées avec from_now
, ago
, etc, pour des calculs de dates précis. Par exemple:
# équivalent à Time.current.advance(months: 1)
1.month.from_now
# équivalent à Time.current.advance(years: 2)
2.years.from_now
# équivalent à Time.current.advance(months: 4, years: 5)
(4.months + 5.years).from_now
ATTENTION. Pour d'autres durées, veuillez vous référer aux extensions de temps à Numeric
.
Défini dans active_support/core_ext/integer/time.rb
.
9 Extensions à BigDecimal
9.1 to_s
La méthode to_s
fournit un spécificateur par défaut de "F". Cela signifie qu'un simple appel à to_s
donnera une représentation en virgule flottante au lieu de la notation scientifique:
BigDecimal(5.00, 6).to_s # => "5.0"
La notation scientifique est toujours prise en charge:
BigDecimal(5.00, 6).to_s("e") # => "0.5E1"
10 Extensions à Enumerable
10.1 sum
La méthode sum
ajoute les éléments d'un énumérable:
ruby
[1, 2, 3].sum # => 6
(1..100).sum # => 5050
L'addition suppose seulement que les éléments répondent à +
:
[[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 # => [:a, 1, :b, 2, :c, 3]
La somme d'une collection vide est zéro par défaut, mais cela peut être personnalisé:
[].sum # => 0
[].sum(1) # => 1
Si un bloc est donné, sum
devient un itérateur qui renvoie les éléments de la collection et additionne les valeurs renvoyées:
(1..5).sum { |n| n * 2 } # => 30
[2, 4, 6, 8, 10].sum # => 30
La somme d'un récepteur vide peut également être personnalisée sous cette forme:
[].sum(1) { |n| n**3 } # => 1
Défini dans active_support/core_ext/enumerable.rb
.
10.2 index_by
La méthode index_by
génère un hash avec les éléments d'une énumération indexés par une clé.
Elle itère à travers la collection et passe chaque élément à un bloc. L'élément sera indexé par la valeur renvoyée par le bloc:
invoices.index_by(&:number)
# => {'2009-032' => <Invoice ...>, '2009-008' => <Invoice ...>, ...}
ATTENTION. Les clés devraient normalement être uniques. Si le bloc renvoie la même valeur pour différents éléments, aucune collection n'est construite pour cette clé. Le dernier élément l'emportera.
Défini dans active_support/core_ext/enumerable.rb
.
10.3 index_with
La méthode index_with
génère un hash avec les éléments d'une énumération comme clés. La valeur
est soit une valeur par défaut passée en argument, soit renvoyée par un bloc.
post = Post.new(title: "hey there", body: "what's up?")
%i( title body ).index_with { |attr_name| post.public_send(attr_name) }
# => { title: "hey there", body: "what's up?" }
WEEKDAYS.index_with(Interval.all_day)
# => { monday: [ 0, 1440 ], … }
Défini dans active_support/core_ext/enumerable.rb
.
10.4 many?
La méthode many?
est une abréviation pour collection.size > 1
:
<% if pages.many? %>
<%= pagination_links %>
<% end %>
Si un bloc optionnel est donné, many?
ne prend en compte que les éléments qui renvoient true:
@see_more = videos.many? { |video| video.category == params[:category] }
Défini dans active_support/core_ext/enumerable.rb
.
10.5 exclude?
Le prédicat exclude?
teste si un objet donné n'appartient pas à la collection. C'est la négation de include?
intégré:
to_visit << node if visited.exclude?(node)
Défini dans active_support/core_ext/enumerable.rb
.
10.6 including
La méthode including
renvoie une nouvelle énumération qui inclut les éléments passés en argument:
[ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
["David", "Rafael"].including %w[ Aaron Todd ] # => ["David", "Rafael", "Aaron", "Todd"]
Défini dans active_support/core_ext/enumerable.rb
.
10.7 excluding
La méthode excluding
renvoie une copie d'une énumération avec les éléments spécifiés
supprimés:
["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
excluding
est un alias de without
.
Défini dans active_support/core_ext/enumerable.rb
.
10.8 pluck
La méthode pluck
extrait la clé donnée de chaque élément:
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name) # => ["David", "Rafael", "Aaron"]
[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name) # => [[1, "David"], [2, "Rafael"]]
Défini dans active_support/core_ext/enumerable.rb
.
10.9 pick
La méthode pick
extrait la clé donnée du premier élément :
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name) # => "David"
[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name) # => [1, "David"]
Défini dans active_support/core_ext/enumerable.rb
.
11 Extensions pour Array
11.1 Accès
Active Support améliore l'API des tableaux pour faciliter certaines façons de les accéder. Par exemple, to
renvoie le sous-tableau des éléments jusqu'à celui à l'index passé :
%w(a b c d).to(2) # => ["a", "b", "c"]
[].to(7) # => []
De même, from
renvoie la partie à partir de l'élément à l'index passé jusqu'à la fin. Si l'index est supérieur à la longueur du tableau, il renvoie un tableau vide.
%w(a b c d).from(2) # => ["c", "d"]
%w(a b c d).from(10) # => []
[].from(0) # => []
La méthode including
renvoie un nouveau tableau qui inclut les éléments passés :
[ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
[ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
La méthode excluding
renvoie une copie du tableau en excluant les éléments spécifiés.
Il s'agit d'une optimisation de Enumerable#excluding
qui utilise Array#-
au lieu de Array#reject
pour des raisons de performance.
["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
[ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
Les méthodes second
, third
, fourth
et fifth
renvoient l'élément correspondant, tout comme second_to_last
et third_to_last
(first
et last
sont intégrés). Grâce à la sagesse sociale et à la constructivité positive partout, forty_two
est également disponible.
%w(a b c d).third # => "c"
%w(a b c d).fifth # => nil
Défini dans active_support/core_ext/array/access.rb
.
11.2 Extraction
La méthode extract!
supprime et renvoie les éléments pour lesquels le bloc renvoie une valeur vraie.
Si aucun bloc n'est donné, un énumérateur est renvoyé à la place.
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
numbers # => [0, 2, 4, 6, 8]
Défini dans active_support/core_ext/array/extract.rb
.
11.3 Extraction des options
Lorsque le dernier argument dans un appel de méthode est un hash, à l'exception peut-être d'un argument &block
, Ruby vous permet d'omettre les crochets :
User.exists?(email: params[:email])
Ce sucre syntaxique est beaucoup utilisé dans Rails pour éviter les arguments positionnels lorsque cela serait trop nombreux, offrant à la place des interfaces qui émulent les paramètres nommés. En particulier, il est très idiomatique d'utiliser un hash de fin pour les options.
Si une méthode attend un nombre variable d'arguments et utilise *
dans sa déclaration, cependant, un hash d'options se retrouve être un élément du tableau d'arguments, où il perd son rôle.
Dans ces cas, vous pouvez donner à un hash d'options un traitement distinct avec extract_options!
. Cette méthode vérifie le type du dernier élément d'un tableau. S'il s'agit d'un hash, il le supprime et le renvoie, sinon il renvoie un hash vide.
Voyons par exemple la définition de la macro du contrôleur caches_action
:
def caches_action(*actions)
return unless cache_configured?
options = actions.extract_options!
# ...
end
Cette méthode reçoit un nombre arbitraire de noms d'actions et un hachage d'options facultatif en dernier argument. Avec l'appel à extract_options!
, vous obtenez le hachage d'options et le supprimez de actions
de manière simple et explicite.
NOTE : Défini dans active_support/core_ext/array/extract_options.rb
.
11.4 Conversions
11.4.1 to_sentence
La méthode to_sentence
transforme un tableau en une chaîne de caractères contenant une phrase qui énumère ses éléments :
%w().to_sentence # => ""
%w(Earth).to_sentence # => "Earth"
%w(Earth Wind).to_sentence # => "Earth and Wind"
%w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"
Cette méthode accepte trois options :
:two_words_connector
: Ce qui est utilisé pour les tableaux de longueur 2. La valeur par défaut est " and ".:words_connector
: Ce qui est utilisé pour joindre les éléments des tableaux avec 3 éléments ou plus, sauf les deux derniers. La valeur par défaut est ", ".:last_word_connector
: Ce qui est utilisé pour joindre les derniers éléments d'un tableau avec 3 éléments ou plus. La valeur par défaut est ", and ".
Les valeurs par défaut de ces options peuvent être localisées, leurs clés sont :
Option | Clé I18n |
---|---|
:two_words_connector |
support.array.two_words_connector |
:words_connector |
support.array.words_connector |
:last_word_connector |
support.array.last_word_connector |
NOTE : Défini dans active_support/core_ext/array/conversions.rb
.
11.4.2 to_fs
La méthode to_fs
agit comme to_s
par défaut.
Si le tableau contient des éléments qui répondent à id
, cependant, le symbole :db
peut être passé en argument. C'est généralement utilisé avec des collections d'objets Active Record. Les chaînes retournées sont :
[].to_fs(:db) # => "null"
[user].to_fs(:db) # => "8456"
invoice.lines.to_fs(:db) # => "23,567,556,12"
Les entiers dans l'exemple ci-dessus sont censés provenir des appels respectifs à id
.
NOTE : Défini dans active_support/core_ext/array/conversions.rb
.
11.4.3 to_xml
La méthode to_xml
renvoie une chaîne de caractères contenant une représentation XML de son objet :
Contributor.limit(2).order(:rank).to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors type="array">
# <contributor>
# <id type="integer">4356</id>
# <name>Jeremy Kemper</name>
# <rank type="integer">1</rank>
# <url-id>jeremy-kemper</url-id>
# </contributor>
# <contributor>
# <id type="integer">4404</id>
# <name>David Heinemeier Hansson</name>
# <rank type="integer">2</rank>
# <url-id>david-heinemeier-hansson</url-id>
# </contributor>
# </contributors>
Pour ce faire, elle envoie to_xml
à chaque élément à tour de rôle et collecte les résultats sous un nœud racine. Tous les éléments doivent répondre à to_xml
, sinon une exception est levée.
Par défaut, le nom de l'élément racine est le pluriel en underscore et en tiret du nom de la classe du premier élément, à condition que le reste des éléments appartiennent à ce type (vérifié avec is_a?
) et qu'ils ne soient pas des hachages. Dans l'exemple ci-dessus, il s'agit de "contributors".
S'il y a un élément qui n'appartient pas au type du premier élément, le nœud racine devient "objects" :
[Contributor.first, Commit.first].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
# <object>
# <id type="integer">4583</id>
# <name>Aaron Batalion</name>
# <rank type="integer">53</rank>
# <url-id>aaron-batalion</url-id>
# </object>
# <object>
# <author>Joshua Peek</author>
# <authored-timestamp type="datetime">2009-09-02T16:44:36Z</authored-timestamp>
# <branch>origin/master</branch>
# <committed-timestamp type="datetime">2009-09-02T16:44:36Z</committed-timestamp>
# <committer>Joshua Peek</committer>
# <git-show nil="true"></git-show>
# <id type="integer">190316</id>
# <imported-from-svn type="boolean">false</imported-from-svn>
# <message>Kill AMo observing wrap_with_notifications since ARes was only using it</message>
# <sha1>723a47bfb3708f968821bc969a9a3fc873a3ed58</sha1>
# </object>
# </objects>
Si le récepteur est un tableau de hachages, l'élément racine est par défaut également "objects":
[{ a: 1, b: 2 }, { c: 3 }].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
# <object>
# <b type="integer">2</b>
# <a type="integer">1</a>
# </object>
# <object>
# <c type="integer">3</c>
# </object>
# </objects>
ATTENTION. Si la collection est vide, l'élément racine est par défaut "nil-classes". C'est un piège, par exemple l'élément racine de la liste des contributeurs ci-dessus ne serait pas "contributors" si la collection était vide, mais "nil-classes". Vous pouvez utiliser l'option :root
pour garantir un élément racine cohérent.
Le nom des nœuds enfants est par défaut le nom du nœud racine singulier. Dans les exemples ci-dessus, nous avons vu "contributor" et "object". L'option :children
vous permet de définir ces noms de nœuds.
Le constructeur XML par défaut est une nouvelle instance de Builder::XmlMarkup
. Vous pouvez configurer votre propre constructeur via l'option :builder
. La méthode accepte également des options telles que :dasherize
et autres, qui sont transmises au constructeur :
Contributor.limit(2).order(:rank).to_xml(skip_types: true)
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors>
# <contributor>
# <id>4356</id>
# <name>Jeremy Kemper</name>
# <rank>1</rank>
# <url-id>jeremy-kemper</url-id>
# </contributor>
# <contributor>
# <id>4404</id>
# <name>David Heinemeier Hansson</name>
# <rank>2</rank>
# <url-id>david-heinemeier-hansson</url-id>
# </contributor>
# </contributors>
NOTE : Défini dans active_support/core_ext/array/conversions.rb
.
11.5 Enveloppement
La méthode Array.wrap
enveloppe son argument dans un tableau à moins qu'il ne soit déjà un tableau (ou de type tableau).
Plus précisément :
- Si l'argument est
nil
, un tableau vide est renvoyé. - Sinon, si l'argument répond à
to_ary
, il est invoqué, et si la valeur deto_ary
n'est pasnil
, elle est renvoyée. - Sinon, un tableau avec l'argument comme unique élément est renvoyé.
Array.wrap(nil) # => []
Array.wrap([1, 2, 3]) # => [1, 2, 3]
Array.wrap(0) # => [0]
Cette méthode est similaire en but à Kernel#Array
, mais il y a quelques différences :
- Si l'argument répond à
to_ary
, la méthode est invoquée.Kernel#Array
passe àto_a
si la valeur renvoyée estnil
, maisArray.wrap
renvoie immédiatement un tableau avec l'argument comme unique élément. - Si la valeur renvoyée par
to_ary
n'est ninil
ni un objetArray
,Kernel#Array
génère une exception, tandis queArray.wrap
ne le fait pas, il renvoie simplement la valeur. - Il n'appelle pas
to_a
sur l'argument, si l'argument ne répond pas àto_ary
, il renvoie un tableau avec l'argument comme unique élément.
Le dernier point vaut particulièrement la peine d'être comparé pour certaines énumérables :
Array.wrap(foo: :bar) # => [{:foo=>:bar}]
Array(foo: :bar) # => [[:foo, :bar]]
Il existe également une expression idiomatique associée qui utilise l'opérateur splat :
[*object]
NOTE : Défini dans active_support/core_ext/array/wrap.rb
.
11.6 Duplication
La méthode Array#deep_dup
duplique elle-même et tous les objets à l'intérieur de manière récursive avec la méthode Active Support Object#deep_dup
. Elle fonctionne comme Array#map
, en envoyant la méthode deep_dup
à chaque objet à l'intérieur.
array = [1, [2, 3]]
dup = array.deep_dup
dup[1][2] = 4
array[1][2] == nil # => true
NOTE : Défini dans active_support/core_ext/object/deep_dup.rb
.
11.7 Groupement
11.7.1 in_groups_of(nombre, remplir_avec = nil)
La méthode in_groups_of
divise un tableau en groupes consécutifs d'une certaine taille. Elle renvoie un tableau avec les groupes :
[1, 2, 3].in_groups_of(2) # => [[1, 2], [3, nil]]
ou les renvoie un par un si un bloc est passé :
<% sample.in_groups_of(3) do |a, b, c| %>
<tr>
<td><%= a %></td>
<td><%= b %></td>
<td><%= c %></td>
</tr>
<% end %>
Le premier exemple montre comment in_groups_of
remplit le dernier groupe avec autant d'éléments nil
que nécessaire pour obtenir la taille demandée. Vous pouvez changer cette valeur de remplissage en utilisant le deuxième argument optionnel :
[1, 2, 3].in_groups_of(2, 0) # => [[1, 2], [3, 0]]
Et vous pouvez indiquer à la méthode de ne pas remplir le dernier groupe en passant false
:
[1, 2, 3].in_groups_of(2, false) # => [[1, 2], [3]]
En conséquence, false
ne peut pas être utilisé comme valeur de remplissage.
NOTE : Défini dans active_support/core_ext/array/grouping.rb
.
11.7.2 in_groups(nombre, remplir_avec = nil)
La méthode in_groups
divise un tableau en un certain nombre de groupes. La méthode renvoie un tableau avec les groupes :
%w(1 2 3 4 5 6 7).in_groups(3)
# => [["1", "2", "3"], ["4", "5", nil], ["6", "7", nil]]
ou les renvoie un par un si un bloc est passé :
%w(1 2 3 4 5 6 7).in_groups(3) { |group| p group }
["1", "2", "3"]
["4", "5", nil]
["6", "7", nil]
Les exemples ci-dessus montrent que in_groups
remplit certains groupes avec un élément nil
supplémentaire si nécessaire. Un groupe peut avoir au plus un de ces éléments supplémentaires, le dernier à droite s'il y en a. Et les groupes qui les ont sont toujours les derniers.
Vous pouvez changer cette valeur de remplissage en utilisant le deuxième argument optionnel :
%w(1 2 3 4 5 6 7).in_groups(3, "0")
# => [["1", "2", "3"], ["4", "5", "0"], ["6", "7", "0"]]
Et vous pouvez indiquer à la méthode de ne pas remplir les groupes plus petits en passant false
:
%w(1 2 3 4 5 6 7).in_groups(3, false)
# => [["1", "2", "3"], ["4", "5"], ["6", "7"]]
En conséquence, false
ne peut pas être utilisé comme valeur de remplissage.
NOTE : Défini dans active_support/core_ext/array/grouping.rb
.
11.7.3 split(valeur = nil)
La méthode split
divise un tableau par un séparateur et renvoie les morceaux résultants.
Si un bloc est passé, les séparateurs sont les éléments du tableau pour lesquels le bloc renvoie true :
(-5..5).to_a.split { |i| i.multiple_of?(4) }
# => [[-5], [-3, -2, -1], [1, 2, 3], [5]]
Sinon, la valeur reçue en argument, qui est par défaut nil
, est le séparateur :
[0, 1, -5, 1, 1, "foo", "bar"].split(1)
# => [[0], [-5], [], ["foo", "bar"]]
ASTUCE : Remarquez dans l'exemple précédent que les séparateurs consécutifs donnent des tableaux vides.
NOTE : Défini dans active_support/core_ext/array/grouping.rb
.
12 Extensions à Hash
12.1 Conversions
12.1.1 to_xml
La méthode to_xml
renvoie une chaîne de caractères contenant une représentation XML de son objet :
{ foo: 1, bar: 2 }.to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <hash>
# <foo type="integer">1</foo>
# <bar type="integer">2</bar>
# </hash>
Pour ce faire, la méthode boucle sur les paires et construit des nœuds qui dépendent des valeurs. Étant donné une paire clé
, valeur
:
Si
valeur
est un hash, il y a un appel récursif avecclé
en tant que:root
.Si
valeur
est un tableau, il y a un appel récursif avecclé
en tant que:root
, etclé
singulier en tant que:children
.Si
valeur
est un objet appelable, il doit s'attendre à un ou deux arguments. Selon l'arité, l'appelable est invoqué avec le hashoptions
comme premier argument avecclé
en tant que:root
, etclé
singulier en tant que deuxième argument. Sa valeur de retour devient un nouveau nœud.Si
valeur
répond àto_xml
, la méthode est invoquée avecclé
en tant que:root
.Sinon, un nœud avec
clé
en tant qu'étiquette est créé avec une représentation sous forme de chaîne de caractères devaleur
en tant que nœud de texte. Sivaleur
estnil
, un attribut "nil" défini sur "true" est ajouté. À moins que l'option:skip_types
n'existe et soit true, un attribut "type" est également ajouté selon la correspondance suivante :
XML_TYPE_NAMES = {
"Symbol" => "symbol",
"Integer" => "integer",
"BigDecimal" => "decimal",
"Float" => "float",
"TrueClass" => "boolean",
"FalseClass" => "boolean",
"Date" => "date",
"DateTime" => "datetime",
"Time" => "datetime"
}
Par défaut, le nœud racine est "hash", mais cela peut être configuré via l'option :root
.
Le constructeur XML par défaut est une nouvelle instance de Builder::XmlMarkup
. Vous pouvez configurer votre propre constructeur avec l'option :builder
. La méthode accepte également des options telles que :dasherize
et autres, qui sont transmises au constructeur.
NOTE : Défini dans active_support/core_ext/hash/conversions.rb
.
12.2 Fusion
Ruby dispose d'une méthode intégrée Hash#merge
qui fusionne deux hashes :
{ a: 1, b: 1 }.merge(a: 0, c: 2)
# => {:a=>0, :b=>1, :c=>2}
Active Support définit quelques autres façons de fusionner des hashes qui peuvent être pratiques.
12.2.1 reverse_merge
et reverse_merge!
En cas de collision, la clé dans le hash de l'argument l'emporte dans merge
. Vous pouvez prendre en charge des hashes d'options avec des valeurs par défaut de manière compacte avec cette expression :
options = { length: 30, omission: "..." }.merge(options)
Active Support définit reverse_merge
au cas où vous préférez cette notation alternative :
options = options.reverse_merge(length: 30, omission: "...")
Et une version avec un point d'exclamation reverse_merge!
qui effectue la fusion sur place :
options.reverse_merge!(length: 30, omission: "...")
ATTENTION. Prenez en compte que reverse_merge!
peut modifier le hash dans l'appelant, ce qui peut être une bonne ou une mauvaise idée.
NOTE : Défini dans active_support/core_ext/hash/reverse_merge.rb
.
12.2.2 reverse_update
La méthode reverse_update
est un alias de reverse_merge!
, expliqué ci-dessus.
ATTENTION. Notez que reverse_update
n'a pas de point d'exclamation.
NOTE : Défini dans active_support/core_ext/hash/reverse_merge.rb
.
12.2.3 deep_merge
et deep_merge!
Comme vous pouvez le voir dans l'exemple précédent, si une clé est présente dans les deux hashes, la valeur dans celui de l'argument l'emporte.
Active Support définit Hash#deep_merge
. Dans une fusion profonde, si une clé est présente dans les deux hashes et que leurs valeurs sont elles-mêmes des hashes, alors leur fusion devient la valeur dans le hash résultant :
{ a: { b: 1 } }.deep_merge(a: { c: 2 })
# => {:a=>{:b=>1, :c=>2}}
La méthode deep_merge!
effectue une fusion profonde sur place.
NOTE : Défini dans active_support/core_ext/hash/deep_merge.rb
.
12.3 Duplication profonde
La méthode Hash#deep_dup
se duplique elle-même ainsi que toutes les clés et valeurs à l'intérieur de manière récursive avec la méthode Active Support Object#deep_dup
. Elle fonctionne comme Enumerator#each_with_object
en envoyant la méthode deep_dup
à chaque paire à l'intérieur.
hash = { a: 1, b: { c: 2, d: [3, 4] } }
dup = hash.deep_dup
dup[:b][:e] = 5
dup[:b][:d] << 5
hash[:b][:e] == nil # => true
hash[:b][:d] == [3, 4] # => true
NOTE : Défini dans active_support/core_ext/object/deep_dup.rb
.
12.4 Travailler avec les clés
12.4.1 except
et except!
La méthode except
renvoie un hash avec les clés de la liste d'arguments supprimées, si elles sont présentes :
{ a: 1, b: 2 }.except(:a) # => {:b=>2}
Si le receveur répond à convert_key
, la méthode est appelée sur chacun des arguments. Cela permet à except
de fonctionner correctement avec des hashes à accès indifférent, par exemple :
{ a: 1 }.with_indifferent_access.except(:a) # => {}
{ a: 1 }.with_indifferent_access.except("a") # => {}
Il existe également la variante except!
qui supprime les clés sur place.
NOTE : Défini dans active_support/core_ext/hash/except.rb
.
12.4.2 stringify_keys
et stringify_keys!
La méthode stringify_keys
renvoie un hash dont les clés du receveur sont converties en chaînes de caractères. Elle le fait en envoyant to_s
à chaque clé :
{ nil => nil, 1 => 1, a: :a }.stringify_keys
# => {"" => nil, "1" => 1, "a" => :a}
En cas de collision de clés, la valeur sera celle qui a été insérée le plus récemment dans le hash :
{ "a" => 1, a: 2 }.stringify_keys
# Le résultat sera
# => {"a"=>2}
Cette méthode peut être utile, par exemple, pour accepter facilement à la fois des symboles et des chaînes de caractères en tant qu'options. Par exemple, ActionView::Helpers::FormHelper
définit :
def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
options = options.stringify_keys
options["type"] = "checkbox"
# ...
end
La deuxième ligne peut accéder en toute sécurité à la clé "type" et permettre à l'utilisateur de passer soit :type
, soit "type".
Il existe également la variante stringify_keys!
qui convertit les clés en chaînes de caractères sur place.
En plus de cela, on peut utiliser deep_stringify_keys
et deep_stringify_keys!
pour convertir en chaînes de caractères toutes les clés du hash donné et de tous les hashes imbriqués. Un exemple du résultat est :
{ nil => nil, 1 => 1, nested: { a: 3, 5 => 5 } }.deep_stringify_keys
# => {""=>nil, "1"=>1, "nested"=>{"a"=>3, "5"=>5}}
NOTE : Défini dans active_support/core_ext/hash/keys.rb
.
12.4.3 symbolize_keys
et symbolize_keys!
La méthode symbolize_keys
renvoie un hash dont les clés du receveur sont symbolisées, dans la mesure du possible. Elle le fait en envoyant to_sym
à chaque clé :
{ nil => nil, 1 => 1, "a" => "a" }.symbolize_keys
# => {nil=>nil, 1=>1, :a=>"a"}
ATTENTION. Notez que dans l'exemple précédent, une seule clé a été symbolisée.
En cas de collision de clés, la valeur sera celle qui a été insérée le plus récemment dans le hash :
{ "a" => 1, a: 2 }.symbolize_keys
# => {:a=>2}
Cette méthode peut être utile, par exemple, pour accepter facilement à la fois des symboles et des chaînes de caractères en tant qu'options. Par exemple, ActionText::TagHelper
définit
```ruby
def rich_text_area_tag(name, value = nil, options = {})
options = options.symbolize_keys
options[:input] ||= "trix_input_#{ActionText::TagHelper.id += 1}" # ... end ```
La troisième ligne peut accéder en toute sécurité à la clé :input
et permet à l'utilisateur de passer soit :input
soit "input".
Il existe également la variante avec point d'exclamation symbolize_keys!
qui symbolise les clés sur place.
En plus de cela, on peut utiliser deep_symbolize_keys
et deep_symbolize_keys!
pour symboliser toutes les clés du hash donné et tous les hashes imbriqués. Un exemple du résultat est :
{ nil => nil, 1 => 1, "nested" => { "a" => 3, 5 => 5 } }.deep_symbolize_keys
# => {nil=>nil, 1=>1, nested:{a:3, 5=>5}}
NOTE : Défini dans active_support/core_ext/hash/keys.rb
.
12.4.4 to_options
et to_options!
Les méthodes to_options
et to_options!
sont des alias de symbolize_keys
et symbolize_keys!
, respectivement.
NOTE : Défini dans active_support/core_ext/hash/keys.rb
.
12.4.5 assert_valid_keys
La méthode assert_valid_keys
reçoit un nombre arbitraire d'arguments et vérifie si le récepteur a une clé en dehors de cette liste. Si c'est le cas, une ArgumentError
est levée.
{ a: 1 }.assert_valid_keys(:a) # passe
{ a: 1 }.assert_valid_keys("a") # ArgumentError
Active Record n'accepte pas les options inconnues lors de la construction d'associations, par exemple. Il implémente ce contrôle via assert_valid_keys
.
NOTE : Défini dans active_support/core_ext/hash/keys.rb
.
12.5 Travailler avec les valeurs
12.5.1 deep_transform_values
et deep_transform_values!
La méthode deep_transform_values
renvoie un nouveau hash avec toutes les valeurs converties par l'opération de bloc. Cela inclut les valeurs du hash racine et de tous les hashes et tableaux imbriqués.
hash = { person: { name: 'Rob', age: '28' } }
hash.deep_transform_values { |value| value.to_s.upcase }
# => {person: {name: "ROB", age: "28"}}
Il existe également la variante avec point d'exclamation deep_transform_values!
qui convertit de manière destructive toutes les valeurs en utilisant l'opération de bloc.
NOTE : Défini dans active_support/core_ext/hash/deep_transform_values.rb
.
12.6 Découpage
La méthode slice!
remplace le hash par les seules clés données et renvoie un hash contenant les paires clé/valeur supprimées.
hash = { a: 1, b: 2 }
rest = hash.slice!(:a) # => {:b=>2}
hash # => {:a=>1}
NOTE : Défini dans active_support/core_ext/hash/slice.rb
.
12.7 Extraction
La méthode extract!
supprime et renvoie les paires clé/valeur correspondant aux clés données.
hash = { a: 1, b: 2 }
rest = hash.extract!(:a) # => {:a=>1}
hash # => {:b=>2}
La méthode extract!
renvoie la même sous-classe de Hash que le récepteur.
hash = { a: 1, b: 2 }.with_indifferent_access
rest = hash.extract!(:a).class
# => ActiveSupport::HashWithIndifferentAccess
NOTE : Défini dans active_support/core_ext/hash/slice.rb
.
12.8 Accès indifférent
La méthode with_indifferent_access
renvoie un ActiveSupport::HashWithIndifferentAccess
à partir de son récepteur :
{ a: 1 }.with_indifferent_access["a"] # => 1
NOTE : Défini dans active_support/core_ext/hash/indifferent_access.rb
.
13 Extensions à Regexp
13.1 multiline?
La méthode multiline?
indique si une expression régulière a le drapeau /m
défini, c'est-à-dire si le point correspond aux sauts de ligne.
%r{.}.multiline? # => false
%r{.}m.multiline? # => true
Regexp.new('.').multiline? # => false
Regexp.new('.', Regexp::MULTILINE).multiline? # => true
Rails utilise cette méthode à un seul endroit, également dans le code de routage. Les expressions régulières multilignes sont interdites pour les exigences de route et ce drapeau facilite l'application de cette contrainte.
def verify_regexp_requirements(requirements)
# ...
if requirement.multiline?
raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}"
end
# ...
end
Défini dans active_support/core_ext/regexp.rb
.
14 Extensions à Range
14.1 to_fs
Active Support définit Range#to_fs
comme une alternative à to_s
qui comprend un argument de format optionnel. Au moment de la rédaction de cet article, le seul format non par défaut pris en charge est :db
:
(Date.today..Date.tomorrow).to_fs
# => "2009-10-25..2009-10-26"
(Date.today..Date.tomorrow).to_fs(:db)
# => "BETWEEN '2009-10-25' AND '2009-10-26'"
Comme l'exemple le montre, le format :db
génère une clause SQL BETWEEN
. Cela est utilisé par Active Record dans son support des valeurs de plage dans les conditions.
Défini dans active_support/core_ext/range/conversions.rb
.
14.2 ===
et include?
Les méthodes Range#===
et Range#include?
indiquent si une valeur se situe entre les extrémités d'une instance donnée:
(2..3).include?(Math::E) # => true
Active Support étend ces méthodes de sorte que l'argument puisse être à son tour une autre plage. Dans ce cas, nous testons si les extrémités de la plage d'argument appartiennent elles-mêmes au receveur:
(1..10) === (3..7) # => true
(1..10) === (0..7) # => false
(1..10) === (3..11) # => false
(1...9) === (3..9) # => false
(1..10).include?(3..7) # => true
(1..10).include?(0..7) # => false
(1..10).include?(3..11) # => false
(1...9).include?(3..9) # => false
Défini dans active_support/core_ext/range/compare_range.rb
.
14.3 overlap?
La méthode Range#overlap?
indique si deux plages données ont une intersection non vide:
(1..10).overlap?(7..11) # => true
(1..10).overlap?(0..7) # => true
(1..10).overlap?(11..27) # => false
Défini dans active_support/core_ext/range/overlap.rb
.
15 Extensions à Date
15.1 Calculs
Les méthodes de calcul suivantes ont des cas particuliers en octobre 1582, car les jours 5 à 14 n'existent tout simplement pas. Ce guide ne documente pas leur comportement autour de ces jours pour des raisons de concision, mais il suffit de dire qu'ils font ce que vous attendez. C'est-à-dire que Date.new(1582, 10, 4).tomorrow
renvoie Date.new(1582, 10, 15)
et ainsi de suite. Veuillez consulter test/core_ext/date_ext_test.rb
dans la suite de tests Active Support pour connaître le comportement attendu.
15.1.1 Date.current
Active Support définit Date.current
comme étant aujourd'hui dans le fuseau horaire actuel. C'est comme Date.today
, sauf qu'il respecte le fuseau horaire de l'utilisateur, s'il est défini. Il définit également Date.yesterday
et Date.tomorrow
, ainsi que les prédicats d'instance past?
, today?
, tomorrow?
, next_day?
, yesterday?
, prev_day?
, future?
, on_weekday?
et on_weekend?
, tous relatifs à Date.current
.
Lorsque vous effectuez des comparaisons de dates en utilisant des méthodes qui respectent le fuseau horaire de l'utilisateur, assurez-vous d'utiliser Date.current
et non Date.today
. Il existe des cas où le fuseau horaire de l'utilisateur peut être dans le futur par rapport au fuseau horaire du système, que Date.today
utilise par défaut. Cela signifie que Date.today
peut être égal à Date.yesterday
.
Défini dans active_support/core_ext/date/calculations.rb
.
15.1.2 Dates nommées
15.1.2.1 beginning_of_week
, end_of_week
Les méthodes beginning_of_week
et end_of_week
renvoient les dates du début et de la fin de la semaine, respectivement. On suppose que les semaines commencent le lundi, mais cela peut être modifié en passant un argument, en définissant Date.beginning_of_week
en tant que variable locale ou config.beginning_of_week
.
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
d.beginning_of_week # => Mon, 03 May 2010
d.beginning_of_week(:sunday) # => Sun, 02 May 2010
d.end_of_week # => Sun, 09 May 2010
d.end_of_week(:sunday) # => Sat, 08 May 2010
beginning_of_week
est un alias de at_beginning_of_week
et end_of_week
est un alias de at_end_of_week
.
Défini dans active_support/core_ext/date_and_time/calculations.rb
.
15.1.2.2 monday
, sunday
Les méthodes monday
et sunday
renvoient les dates du lundi précédent et du dimanche suivant, respectivement.
ruby
date = Date.new(2010, 6, 7)
date.months_ago(3) # => Mon, 07 Mar 2010
date.months_since(3) # => Thu, 07 Sep 2010
If such a day does not exist, the last day of the corresponding month is returned:
Date.new(2012, 3, 31).months_ago(1) # => Thu, 29 Feb 2012
Date.new(2012, 1, 31).months_since(1) # => Wed, 29 Feb 2012
last_month
is short-hand for #months_ago(1)
.
15.1.2.3 weeks_ago
, weeks_since
The methods weeks_ago
and [weeks_since
][DateAndTime::Calculations#weeks_since] work analogously for weeks:
date = Date.new(2010, 6, 7)
date.weeks_ago(2) # => Mon, 24 May 2010
date.weeks_since(2) # => Mon, 21 Jun 2010
last_week
is short-hand for #weeks_ago(1)
.
15.1.2.4 days_ago
, days_since
The methods [days_ago
][DateAndTime::Calculations#days_ago] and [days_since
][DateAndTime::Calculations#days_since] work analogously for days:
date = Date.new(2010, 6, 7)
date.days_ago(5) # => Wed, 02 Jun 2010
date.days_since(5) # => Sat, 12 Jun 2010
[yesterday
][DateAndTime::Calculations#yesterday] is short-hand for #days_ago(1)
, and [tomorrow
][DateAndTime::Calculations#tomorrow] is short-hand for #days_since(1)
.
The method end_of_minute
returns a timestamp at the end of the minute (hh:mm:59):
date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.end_of_minute # => Mon Jun 07 19:55:59 +0200 2010
beginning_of_minute
is aliased to at_beginning_of_minute
.
La méthode end_of_minute
renvoie un horodatage à la fin de la minute (hh:mm:59):
date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.end_of_minute # => Lun Jun 07 19:55:59 +0200 2010
beginning_of_minute
est un alias de at_beginning_of_minute
.
beginning_of_hour
, end_of_hour
, beginning_of_minute
et end_of_minute
sont implémentés pour Time
et DateTime
mais pas pour Date
car il n'a pas de sens de demander le début ou la fin d'une heure ou d'une minute sur une instance de Date
.
Défini dans active_support/core_ext/date_time/calculations.rb
.
15.1.2.5 ago
, since
La méthode ago
reçoit un nombre de secondes en argument et renvoie un horodatage correspondant à il y a autant de secondes depuis minuit :
date = Date.current # => Ven, 11 Jun 2010
date.ago(1) # => Jeu, 10 Jun 2010 23:59:59 EDT -04:00
De même, since
avance dans le temps :
date = Date.current # => Ven, 11 Jun 2010
date.since(1) # => Ven, 11 Jun 2010 00:00:01 EDT -04:00
Défini dans active_support/core_ext/date/calculations.rb
.
16 Extensions pour DateTime
AVERTISSEMENT : DateTime
ne tient pas compte des règles relatives à l'heure d'été, de sorte que certaines de ces méthodes ont des cas particuliers lorsqu'un changement d'heure d'été est en cours. Par exemple, seconds_since_midnight
peut ne pas renvoyer la véritable quantité dans un tel jour.
16.1 Calculs
La classe DateTime
est une sous-classe de Date
, donc en chargeant active_support/core_ext/date/calculations.rb
, vous héritez de ces méthodes et de leurs alias, à l'exception qu'elles renverront toujours des datetimes.
Les méthodes suivantes sont réimplémentées afin que vous n'ayez pas besoin de charger active_support/core_ext/date/calculations.rb
pour celles-ci :
En revanche, advance
et change
sont également définis et prennent en charge plus d'options, ils sont documentés ci-dessous.
Les méthodes suivantes sont uniquement implémentées dans active_support/core_ext/date_time/calculations.rb
, car elles n'ont de sens que lorsqu'elles sont utilisées avec une instance de DateTime
:
16.1.1 Datetimes nommés
16.1.1.1 DateTime.current
Active Support définit DateTime.current
pour être similaire à Time.now.to_datetime
, à l'exception qu'il respecte le fuseau horaire de l'utilisateur, s'il est défini. Les prédicats d'instance past?
et future?
sont définis par rapport à DateTime.current
.
Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.2 Autres extensions
16.1.2.1 seconds_since_midnight
La méthode seconds_since_midnight
renvoie le nombre de secondes depuis minuit :
now = DateTime.current # => Lun, 07 Jun 2010 20:26:36 +0000
now.seconds_since_midnight # => 73596
Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.2.2 utc
La méthode utc
vous donne le même datetime dans le récepteur exprimé en UTC.
now = DateTime.current # => Lun, 07 Jun 2010 19:27:52 -0400
now.utc # => Lun, 07 Jun 2010 23:27:52 +0000
Cette méthode est également un alias de getutc
.
Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.2.3 utc?
Le prédicat utc?
indique si le récepteur a UTC comme fuseau horaire :
now = DateTime.now # => Lun, 07 Jun 2010 19:30:47 -0400
now.utc? # => false
now.utc.utc? # => true
Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.2.4 advance
La façon la plus générique de passer à un autre datetime est advance
. Cette méthode reçoit un hash avec les clés :years
, :months
, :weeks
, :days
, :hours
, :minutes
et :seconds
, et renvoie un datetime avancé autant que les clés actuelles l'indiquent.
```ruby
d = DateTime.current
=> Jeu, 05 Août 2010 11:33:31 +0000
d.advance(years: 1, months: 1, days: 1, hours: 1, minutes: 1, seconds: 1)
=> Mar, 06 Septembre 2011 12:34:32 +0000
Cette méthode calcule d'abord la date de destination en passant `:years`, `:months`, `:weeks` et `:days` à `Date#advance` documenté ci-dessus. Ensuite, elle ajuste l'heure en appelant [`since`][DateTime#since] avec le nombre de secondes à avancer. Cet ordre est important, un ordre différent donnerait des datetimes différents dans certains cas particuliers. L'exemple dans `Date#advance` s'applique, et nous pouvons l'étendre pour montrer l'importance de l'ordre par rapport aux bits de temps.
Si nous déplaçons d'abord les bits de date (qui ont également un ordre relatif de traitement, comme documenté précédemment), puis les bits de temps, nous obtenons par exemple le calcul suivant :
```ruby
d = DateTime.new(2010, 2, 28, 23, 59, 59)
# => Dim, 28 Février 2010 23:59:59 +0000
d.advance(months: 1, seconds: 1)
# => Lun, 29 Mars 2010 00:00:00 +0000
mais si nous les calculons dans l'autre sens, le résultat serait différent :
d.advance(seconds: 1).advance(months: 1)
# => Jeu, 01 Avril 2010 00:00:00 +0000
AVERTISSEMENT : Étant donné que DateTime
ne tient pas compte de l'heure d'été, vous pouvez vous retrouver à un moment qui n'existe pas sans aucun avertissement ou erreur vous le signalant.
REMARQUE : Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.3 Modification des composants
La méthode change
vous permet d'obtenir un nouveau datetime qui est identique au récepteur à l'exception des options données, qui peuvent inclure :year
, :month
, :day
, :hour
, :min
, :sec
, :offset
, :start
:
now = DateTime.current
# => Mar, 08 Juin 2010 01:56:22 +0000
now.change(year: 2011, offset: Rational(-6, 24))
# => Mer, 08 Juin 2011 01:56:22 -0600
Si les heures sont mises à zéro, les minutes et les secondes le sont aussi (sauf si elles ont des valeurs données) :
now.change(hour: 0)
# => Mar, 08 Juin 2010 00:00:00 +0000
De même, si les minutes sont mises à zéro, les secondes le sont aussi (sauf si une valeur est donnée) :
now.change(min: 0)
# => Mar, 08 Juin 2010 01:00:00 +0000
Cette méthode ne tolère pas les dates inexistantes, si le changement est invalide, une ArgumentError
est levée :
DateTime.current.change(month: 2, day: 30)
# => ArgumentError: date invalide
REMARQUE : Défini dans active_support/core_ext/date_time/calculations.rb
.
16.1.4 Durées
Les objets Duration
peuvent être ajoutés et soustraits des datetimes :
now = DateTime.current
# => Lun, 09 Août 2010 23:15:17 +0000
now + 1.year
# => Mar, 09 Août 2011 23:15:17 +0000
now - 1.week
# => Lun, 02 Août 2010 23:15:17 +0000
Ils se traduisent par des appels à since
ou advance
. Par exemple, ici nous obtenons le bon saut dans la réforme du calendrier :
DateTime.new(1582, 10, 4, 23) + 1.hour
# => Ven, 15 Octobre 1582 00:00:00 +0000
17 Extensions à Time
17.1 Calculs
Ils sont analogues. Veuillez vous référer à leur documentation ci-dessus et prendre en compte les différences suivantes :
change
accepte une option supplémentaire:usec
.Time
comprend l'heure d'été, vous obtenez donc des calculs d'heure d'été corrects comme dans l'exemple suivant :
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
# À Barcelone, le 28/03/2010 02:00 +0100 devient le 28/03/2010 03:00 +0200 en raison de l'heure d'été.
t = Time.local(2010, 3, 28, 1, 59, 59)
# => Dim Mar 28 01:59:59 +0100 2010
t.advance(seconds: 1)
# => Dim Mar 28 03:00:00 +0200 2010
- Si
since
ouago
saute à un moment qui ne peut pas être exprimé avecTime
, un objetDateTime
est renvoyé à la place.
17.1.1 Time.current
Active Support définit Time.current
pour être aujourd'hui dans le fuseau horaire actuel. C'est comme Time.now
, sauf qu'il respecte le fuseau horaire de l'utilisateur, s'il est défini. Il définit également les prédicats d'instance past?
, today?
, tomorrow?
, next_day?
, yesterday?
, prev_day?
et future?
, tous relatifs à Time.current
.
Lorsque vous effectuez des comparaisons de temps en utilisant des méthodes qui respectent le fuseau horaire de l'utilisateur, assurez-vous d'utiliser Time.current
au lieu de Time.now
. Il y a des cas où le fuseau horaire de l'utilisateur peut être dans le futur par rapport au fuseau horaire du système, que Time.now
utilise par défaut. Cela signifie que Time.now.to_date
peut être égal à Date.yesterday
.
NOTE : Défini dans active_support/core_ext/time/calculations.rb
.
17.1.2 all_day
, all_week
, all_month
, all_quarter
et all_year
La méthode all_day
renvoie une plage représentant toute la journée du moment actuel.
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_day
# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Mon, 09 Aug 2010 23:59:59 UTC +00:00
De manière analogue, all_week
, all_month
, all_quarter
et all_year
servent tous à générer des plages de temps.
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_week
# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Sun, 15 Aug 2010 23:59:59 UTC +00:00
now.all_week(:sunday)
# => Sun, 16 Sep 2012 00:00:00 UTC +00:00..Sat, 22 Sep 2012 23:59:59 UTC +00:00
now.all_month
# => Sat, 01 Aug 2010 00:00:00 UTC +00:00..Tue, 31 Aug 2010 23:59:59 UTC +00:00
now.all_quarter
# => Thu, 01 Jul 2010 00:00:00 UTC +00:00..Thu, 30 Sep 2010 23:59:59 UTC +00:00
now.all_year
# => Fri, 01 Jan 2010 00:00:00 UTC +00:00..Fri, 31 Dec 2010 23:59:59 UTC +00:00
NOTE : Défini dans active_support/core_ext/date_and_time/calculations.rb
.
17.1.3 prev_day
, next_day
prev_day
et next_day
renvoient le moment du jour précédent ou suivant :
t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_day # => 2010-05-07 00:00:00 +0900
t.next_day # => 2010-05-09 00:00:00 +0900
NOTE : Défini dans active_support/core_ext/time/calculations.rb
.
17.1.4 prev_month
, next_month
prev_month
et next_month
renvoient le moment avec le même jour dans le mois précédent ou suivant :
t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_month # => 2010-04-08 00:00:00 +0900
t.next_month # => 2010-06-08 00:00:00 +0900
Si un tel jour n'existe pas, le dernier jour du mois correspondant est renvoyé :
Time.new(2000, 5, 31).prev_month # => 2000-04-30 00:00:00 +0900
Time.new(2000, 3, 31).prev_month # => 2000-02-29 00:00:00 +0900
Time.new(2000, 5, 31).next_month # => 2000-06-30 00:00:00 +0900
Time.new(2000, 1, 31).next_month # => 2000-02-29 00:00:00 +0900
NOTE : Défini dans active_support/core_ext/time/calculations.rb
.
17.1.5 prev_year
, next_year
prev_year
et next_year
renvoient un moment avec le même jour/mois dans l'année précédente ou suivante :
t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_year # => 2009-05-08 00:00:00 +0900
t.next_year # => 2011-05-08 00:00:00 +0900
Si la date est le 29 février d'une année bissextile, vous obtenez le 28 :
t = Time.new(2000, 2, 29) # => 2000-02-29 00:00:00 +0900
t.prev_year # => 1999-02-28 00:00:00 +0900
t.next_year # => 2001-02-28 00:00:00 +0900
Défini dans active_support/core_ext/time/calculations.rb
.
17.1.6 prev_quarter
, next_quarter
prev_quarter
et next_quarter
renvoient la date avec le même jour du trimestre précédent ou suivant:
t = Time.local(2010, 5, 8) # => 2010-05-08 00:00:00 +0300
t.prev_quarter # => 2010-02-08 00:00:00 +0200
t.next_quarter # => 2010-08-08 00:00:00 +0300
Si un tel jour n'existe pas, le dernier jour du mois correspondant est renvoyé:
Time.local(2000, 7, 31).prev_quarter # => 2000-04-30 00:00:00 +0300
Time.local(2000, 5, 31).prev_quarter # => 2000-02-29 00:00:00 +0200
Time.local(2000, 10, 31).prev_quarter # => 2000-07-31 00:00:00 +0300
Time.local(2000, 11, 31).next_quarter # => 2001-03-01 00:00:00 +0200
prev_quarter
est un alias de last_quarter
.
Défini dans active_support/core_ext/date_and_time/calculations.rb
.
17.2 Constructeurs de temps
Active Support définit Time.current
comme Time.zone.now
s'il existe un fuseau horaire utilisateur défini, avec une fallback à Time.now
:
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
Time.current
# => Fri, 06 Aug 2010 17:11:58 CEST +02:00
De manière analogue à DateTime
, les prédicats past?
et future?
sont relatifs à Time.current
.
Si le temps à construire se situe en dehors de la plage supportée par Time
dans la plateforme d'exécution, les microsecondes sont ignorées et un objet DateTime
est renvoyé à la place.
17.2.1 Durées
Les objets Duration
peuvent être ajoutés et soustraits des objets temps:
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now + 1.year
# => Tue, 09 Aug 2011 23:21:11 UTC +00:00
now - 1.week
# => Mon, 02 Aug 2010 23:21:11 UTC +00:00
Ils se traduisent par des appels à since
ou advance
. Par exemple, ici nous obtenons le bon saut dans la réforme du calendrier:
Time.utc(1582, 10, 3) + 5.days
# => Mon Oct 18 00:00:00 UTC 1582
18 Extensions à File
18.1 atomic_write
Avec la méthode de classe File.atomic_write
, vous pouvez écrire dans un fichier d'une manière qui empêchera tout lecteur de voir un contenu partiellement écrit.
Le nom du fichier est passé en argument, et la méthode renvoie une poignée de fichier ouverte en écriture. Une fois que le bloc est terminé, atomic_write
ferme la poignée de fichier et termine son travail.
Par exemple, Action Pack utilise cette méthode pour écrire des fichiers de cache d'actifs comme all.css
:
File.atomic_write(joined_asset_path) do |cache|
cache.write(join_asset_file_contents(asset_paths))
end
Pour accomplir cela, atomic_write
crée un fichier temporaire. C'est le fichier sur lequel le code dans le bloc écrit réellement. À la fin, le fichier temporaire est renommé, ce qui est une opération atomique sur les systèmes POSIX. Si le fichier cible existe, atomic_write
le remplace et conserve les propriétaires et les permissions. Cependant, il existe quelques cas où atomic_write
ne peut pas modifier la propriété ou les permissions du fichier, cette erreur est capturée et ignorée en faisant confiance à l'utilisateur/système de fichiers pour s'assurer que le fichier est accessible aux processus qui en ont besoin.
En raison de l'opération chmod que atomic_write
effectue, si le fichier cible a un ACL défini dessus, cet ACL sera recalculé/modifié.
AVERTISSEMENT. Notez que vous ne pouvez pas ajouter avec atomic_write
.
Le fichier auxiliaire est écrit dans un répertoire standard pour les fichiers temporaires, mais vous pouvez passer un répertoire de votre choix en deuxième argument.
Défini dans active_support/core_ext/file/atomic.rb
.
19 Extensions à NameError
Active Support ajoute missing_name?
à NameError
, qui teste si l'exception a été levée en raison du nom passé en argument.
Le nom peut être donné sous forme de symbole ou de chaîne de caractères. Un symbole est testé par rapport au nom de constante nu, une chaîne de caractères est testée par rapport au nom de constante entièrement qualifié.
CONSEIL : Un symbole peut représenter un nom de constante entièrement qualifié comme dans :"ActiveRecord::Base"
, donc le comportement pour les symboles est défini pour plus de commodité, et non parce que cela doit être ainsi techniquement.
Par exemple, lorsque l'action d'un ArticlesController
est appelée, Rails essaie de manière optimiste d'utiliser ArticlesHelper
. Il est normal que le module d'aide n'existe pas, donc si une exception est levée pour ce nom de constante, elle doit être ignorée. Mais il se peut que articles_helper.rb
lève une NameError
en raison d'une constante inconnue réelle. Dans ce cas, elle doit être relancée. La méthode missing_name?
permet de distinguer ces deux cas :
def default_helper_module!
module_name = name.delete_suffix("Controller")
module_path = module_name.underscore
helper module_path
rescue LoadError => e
raise e unless e.is_missing? "helpers/#{module_path}_helper"
rescue NameError => e
raise e unless e.missing_name? "#{module_name}Helper"
end
NOTE : Défini dans active_support/core_ext/name_error.rb
.
20 Extensions à LoadError
Active Support ajoute is_missing?
à LoadError
.
Étant donné un nom de chemin, is_missing?
teste si l'exception a été levée en raison de ce fichier particulier (sauf peut-être pour l'extension ".rb").
Par exemple, lorsque l'action d'un ArticlesController
est appelée, Rails essaie de charger articles_helper.rb
, mais ce fichier peut ne pas exister. C'est normal, le module d'aide n'est pas obligatoire, donc Rails ignore une erreur de chargement. Mais il se peut que le module d'aide existe et nécessite à son tour une autre bibliothèque qui est manquante. Dans ce cas, Rails doit relancer l'exception. La méthode is_missing?
permet de distinguer ces deux cas :
def default_helper_module!
module_name = name.delete_suffix("Controller")
module_path = module_name.underscore
helper module_path
rescue LoadError => e
raise e unless e.is_missing? "helpers/#{module_path}_helper"
rescue NameError => e
raise e unless e.missing_name? "#{module_name}Helper"
end
NOTE : Défini dans active_support/core_ext/load_error.rb
.
21 Extensions à Pathname
21.1 existence
La méthode existence
renvoie le récepteur si le fichier nommé existe, sinon elle renvoie nil
. Elle est utile pour des idiomes comme celui-ci :
content = Pathname.new("file").existence&.read
NOTE : Défini dans active_support/core_ext/pathname/existence.rb
.
Retour d'information
Vous êtes encouragé à contribuer à l'amélioration de la qualité de ce guide.
Veuillez contribuer si vous trouvez des fautes de frappe ou des erreurs factuelles. Pour commencer, vous pouvez lire notre contribution à la documentation section.
Vous pouvez également trouver du contenu incomplet ou des informations qui ne sont pas à jour. Veuillez ajouter toute documentation manquante pour la version principale. Assurez-vous de vérifier Edge Guides d'abord pour vérifier si les problèmes ont déjà été résolus ou non sur la branche principale. Consultez les Directives des guides Ruby on Rails pour le style et les conventions.
Si pour une raison quelconque vous repérez quelque chose à corriger mais ne pouvez pas le faire vous-même, veuillez ouvrir un problème.
Et enfin, toute discussion concernant la documentation de Ruby on Rails est la bienvenue sur le Forum officiel de Ruby on Rails.