<commit_before>


Active Support コア拡張機能
==============================

Active SupportはRuby on Railsのコンポーネントであり、Ruby言語の拡張、ユーティリティ、その他横断的な作業を担っています。

Active Supportは言語レベルで基本部分を底上げして豊かなものにし、Railsアプリケーションの開発とRuby on Railsそれ自体の開発に役立てるべく作られています。

このガイドの内容:

* コア拡張機能について
* すべての拡張機能を読み込む方法
* 必要な拡張機能だけを利用する方法
* Active Supportが提供する拡張機能一覧

--------------------------------------------------------------------------------

コア拡張機能を読み込む方法
---------------------------

### 単体のActive Support

足跡をほぼ残さないようにするため、Active Supportはデフォルトでは何も読み込みません。Active Supportは細かく分割され、必要な拡張機能だけが読み込まれるようになっています。また、関連する拡張機能(場合によってはすべての拡張機能)も同時に読み込むのに便利なエントリポイントもあります。

従って、以下のようなrequire文を実行しただけでは

```ruby
require 'active_support'
```

オブジェクトは`blank?`にすら応答してくれません。この定義がどのように読み込まれるかを見てみましょう。

#### 必要な定義だけを選ぶ

`blank?`メソッドを使えるようにする最も「軽量な」方法は、そのメソッドが定義されているファイルだけを選んで読み込むことです。

本ガイドでは、コア拡張機能として定義されているすべてのメソッドについて、その定義ファイルの置き場所も示してあります。たとえば`blank?`の場合、以下のようなメモを追加してあります。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

つまり、以下のようにピンポイントでrequireを実行することができます。

```ruby
require 'active_support'
require 'active_support/core_ext/object/blank'
```

Active Supportの改訂は注意深く行われていますので、あるファイルを選んだ場合、本当に必要な依存ファイルだけが同時に読み込まれます(依存関係がある場合)。

#### コア拡張機能をグループ化して読み込む

次の段階として、`Object`に対するすべての拡張機能を単に読み込んでみましょう。経験則として、`SomeClass`というクラスがあれば、`active_support/core_ext/some_class`というパスを指定することで一度に読み込めます。

従って、(`blank?`を含む)`Object`に対するすべての拡張機能を読み込む場合には以下のようにします。

```ruby
require 'active_support'
require 'active_support/core_ext/object'
```

#### すべてのコア拡張機能を読み込む

すべてのコア拡張機能を単に読み込んでおきたいのであれば、以下のようにrequireします。

```ruby
require 'active_support'
require 'active_support/core_ext'
```

#### すべてのActive Supportを読み込む

最後に、利用可能なActive Supportをすべて読み込みたい場合は以下のようにします。

```ruby
require 'active_support/all'
```

ただし、これを実行してもActive Support全体がメモリに読み込まれるわけではないことにご注意ください。一部は`autoload`として設定されており、実際に使うまで読み込まれません。

### Ruby on RailsアプリケーションでActive Supportを使用する

Ruby on Railsアプリケーションでは、基本的にすべてのActive Supportを読み込みます。例外は`config.active_support.bare`をtrueに設定した場合です。このオプションをtrueにすると、フレームワーク自体が必要とするまでアプリケーションは拡張機能を読み込みません。また、読み込まれる拡張機能の選択は、上で解説したように、あらゆる粒度で行われます。

すべてのオブジェクトで使用できる拡張機能
-------------------------

### `blank?`と`present?`

Railsアプリケーションは以下の値を空白(blank)とみなします。

* `nil`と`false`

* 空白文字 (whitespace) だけで構成された文字列 (以下の注釈参照)

* 空欄の配列とハッシュ

* その他、`empty?`メソッドに応答するオブジェクトはすべて空白として扱われます。

INFO: 文字列を判定する述語として、Unicode対応した文字クラスである`[:space:]`が使用されています。そのため、たとえばU+2029 (段落区切り文字)は空白文字と判断されます。

WARNING: 数字については空白であるかどうかは判断されません。特に0および0.0は**空白ではありません**のでご注意ください。

たとえば、`ActionController::HttpAuthentication::Token::ControllerMethods`にある以下のメソッドでは`blank?`を使用してトークンが存在しているかどうかをチェックしています。

```ruby
def authenticate(controller, &login_procedure)
  token, options = token_and_options(controller.request)
  unless token.blank?
    login_procedure.call(token, options)
  end
end
```

`present?`メソッドは`!blank?`メソッドと同等です。以下の例は`ActionDispatch::Http::Cache::Response`から引用しました。

```ruby
def set_conditional_cache_control!
  return if self["Cache-Control"].present?
  ...
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

### `presence`

`presence`メソッドは、`present?`がtrueの場合は自身のレシーバを返し、falseの場合は`nil`を返します。このメソッドは以下のような定番の用法において便利です。

```ruby
host = config[:host].presence || 'localhost'
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

### `duplicable?`

Ruby 2.4では、メソッドや特定の数値を除くほとんどのオブジェクトが`dup`や`clone`で複製できます。Ruby 2.2や2.3では、`nil`, `false`, `true`、シンボル、`Float`/`Fixnum`/`Bignum`のインスタンスは複製できません。

Rubyにおける基本的なオブジェクトの一部はsingletonオブジェクトです。たとえば、プログラムのライフサイクルが続く間、整数の1は常に同じインスタンスを参照します。

```ruby
"foo".dup           # => "foo"
"".dup              # => ""
1.method(:+).dup    # => TypeError: allocator undefined for Method
Complex(0).dup      # => TypeError: can't copy Complex
```

Active Supportでは、複製可能かどうかをオブジェクトに問い合わせる`duplicable?`が提供されています。

```ruby
"foo".duplicable?           # => true
"".duplicable?              # => true
Rational(1).duplicable?     # => false
Complex(1).duplicable?      # => false
1.method(:+).duplicable?    # => false
```

`duplicable?`は、Rubyのバージョンに応じた`dup`にマッチします。

つまり、2.4では次のようになります。

```ruby
nil.dup                 # => nil
:my_symbol.dup          # => :my_symbol
1.dup                   # => 1

nil.duplicable?         # => true
:my_symbol.duplicable?  # => true
1.duplicable?           # => true
```

一方、2.2や2.3では次のようになります。

```ruby
nil.dup                 # => TypeError: can't dup NilClass
:my_symbol.dup          # => TypeError: can't dup Symbol
1.dup                   # => TypeError: can't dup Fixnum
nil.duplicable?         # => false
:my_symbol.duplicable?  # => false
1.duplicable?           # => false
```

デフォルトでは、`nil`、`false`、`true`、シンボル、数値、クラス、モジュール、メソッドオブジェクトを除くすべてのオブジェクトが`duplicable?` #=> trueです。

WARNING: どんなクラスでも、`dup`メソッドと`clone`メソッドを除去することでこれらのメソッドを無効にしてしまうことができます。このとき、これらのメソッドが実行されると例外が発生します。このような状態では、どんなオブジェクトについてもそれが複製可能かどうかを確認するには`rescue`を使用する以外に方法はありません。`duplicable?`メソッドは、上のハードコードされたリストに依存しますが、その代わり`rescue`よりずっと高速です。実際のユースケースでハードコードされたリストで十分であることがわかっている場合には、`duplicable?`をお使いください。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/duplicable.rb`です。

### `deep_dup`

`deep_dup`メソッドは、与えられたオブジェクトの「ディープコピー」を返します。Rubyは通常の場合、他のオブジェクトを含むオブジェクトを`dup`しても、他のオブジェクトについては複製しません。このようなコピーは「浅いコピー (shallow copy)」と呼ばれます。たとえば、以下のように文字列を含む配列があるとします。

```ruby
array     = ['string']
duplicate = array.dup

duplicate.push 'another-string'

# このオブジェクトは複製されたので、複製された方にだけ要素が追加された
array     # => ['string']
duplicate # => ['string', 'another-string']

duplicate.first.gsub!('string', 'foo')

# 1つ目の要素は複製されていないので、一方を変更するとどちらの配列も変更される
array     # => ['foo']
duplicate # => ['foo', 'another-string']
```

上で見たとおり、`Array`のインスタンスを複製して別のオブジェクトができたことにより、一方を変更しても他方は変更されないようになりました。ただし、配列は複製されましたが、配列の要素はそうではありません。`dup`メソッドはディープコピーを行わないので、配列の中にある文字列は複製後も同一オブジェクトのままです。

オブジェクトをディープコピーする必要がある場合は`deep_dup`をお使いください。例:

```ruby
array     = ['string']
duplicate = array.deep_dup

duplicate.first.gsub!('string', 'foo')

array     # => ['string']
duplicate # => ['foo']
```

オブジェクトが複製不可能な場合、`deep_dup`は単にそのオブジェクトを返します。

```ruby
number = 1
duplicate = number.deep_dup
number.object_id == duplicate.object_id   # => true
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/deep_dup.rb`です。

### `try`

`nil`でない場合にのみオブジェクトのメソッドを呼び出したい場合、最も単純な方法は条件文を追加することですが、どこか冗長になってしまいます。そこで`try`メソッドを使うという手があります。`try`は`Object#send`と似ていますが、`nil`に送信された場合には`nil`を返す点が異なります。

例:

```ruby
# tryメソッドを使用しない場合
unless @number.nil?
  @number.next
end

# tryメソッドを使用した場合
@number.try(:next)
```

`ActiveRecord::ConnectionAdapters::AbstractAdapter`から別の例として以下をご紹介します。ここでは`@logger`が`nil`になることがあります。このコードでは`try`を使用したことで余分なチェックを行わずに済んでいます。

```ruby
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`メソッドは引数の代りにブロックを与えて呼び出すこともできます。この場合オブジェクトが`nil`でない場合にのみブロックが実行されます。

```ruby
@person.try { |p| "#{p.first_name} #{p.last_name}" }
```

`try`メソッドは、`NoMethodError`を握りつぶして代わりに`nil`を返す点に注意が必要です。メソッド名の誤りを防ぎたい場合は`try!`を使います。

```ruby
@number.try(:nest)  # => nil
@number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/try.rb`です。

### `class_eval(*args, &block)`

`class_eval`メソッドを使用することで、あらゆるオブジェクトのsingletonクラスのコンテキストでコードを評価することができます。

```ruby
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: 定義ファイルの場所は`active_support/core_ext/kernel/singleton_class.rb`です。

### `acts_like?(duck)`

`acts_like?`メソッドは、一部のクラスがその他のクラスと同様に振る舞うかどうかのチェックを、ある慣例に則って実行します。`String`クラスと同じインターフェイスを提供するクラスがあり、その中で以下のメソッドを定義しておくとします。

```ruby
def acts_like_string?
end
```

このメソッドは単なる目印であり、メソッドの本体と戻り値の間には関連はありません。これにより、クライアントコードで以下のようなダックタイピングチェックを行なうことができます。

```ruby
some_klass.acts_like?(:string)
```

Railsには`Date`クラスや`Time`クラスと同様に振る舞うクラスがいくつかあり、この手法を使用できます。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/acts_like.rb`です。

### `to_param`

Railsのあらゆるオブジェクトは`to_param`メソッドに応答します。これは、オブジェクトを値として表現するものを返すということです。返された値はクエリ文字列やURLの一部で使用できます。

デフォルトでは、`to_param`メソッドは単に`to_s`メソッドを呼び出します。

```ruby
7.to_param # => "7"
```

`to_param`によって返された値を **エスケープしてはいけません** 。

```ruby
"Tom & Jerry".to_param # => "Tom & Jerry"
```

このメソッドは、Railsの多くのクラスで上書きされています。

たとえば、`nil`、`true`、`false`の場合は自分自身を返します。`Array#to_param`を実行すると、`to_param`が配列内の各要素に対して実行され、結果が"/"でjoinされます。

```ruby
[0, true, String].to_param # => "0/true/String"
```

特に、Railsのルーティングシステムはモデルに対して`to_param`メソッドを実行することで、`:id`プレースホルダの値を取得しています。`ActiveRecord::Base#to_param`はモデルの`id`を返しますが、このメソッドをモデル内で再定義することもできます。たとえば

```ruby
class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
```

以下の結果を得ます。

```ruby
user_path(@user) # => "/users/357-john-smith"
```

WARNING: コントローラ側では、`to_param`メソッドがモデル側で再定義されている可能性があることに常に注意しておく必要があります。上のようなリクエストを受信した場合、`params[:id]`の値が"357-john-smith"になるからです。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/to_param.rb`です。

### `to_query`

このメソッドは、エスケープされていない`key`を受け取ると、そのキーを`to_param`が返す値に対応させるクエリ文字列の一部を生成します。ただしハッシュは例外です(後述)。たとえば以下の場合、

```ruby
class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
```

以下の結果を得ます。

```ruby
current_user.to_query('user') # => "user=357-john-smith"
```

このメソッドは、キーと値のいずれについても、必要な箇所をすべてエスケープします。

```ruby
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"
```

従って、この結果はそのままクエリ文字列として使用できます。

配列に`to_query`メソッドを適用した場合、`to_query`を配列の各要素に適用して`key[]`をキーとして追加し、それらを"&"で連結したものを返します。

```ruby
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
```

ハッシュも`to_query`に応答しますが、異なるシグネチャを使用します。メソッドに引数が渡されない場合、このメソッド呼び出しは、一連のキー/値ペアをソート済みの形で生成し、それぞれの値に対して`to_query(key)`を呼び出します。続いて結果を"&"で連結します。

```ruby
{c: 3, b: 2, a: 1}.to_query # => "a=1&b=2&c=3"
```

`Hash#to_query`メソッドは、それらのキーに対して名前空間をオプションで与えることもできます。

```ruby
{id: 89, name: "<NAME>"}.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/to_query.rb`です。

### `with_options`

`with_options`メソッドは、連続した複数のメソッド呼び出しに対して共通して与えられるオプションを解釈するための手段を提供します。

デフォルトのオプションがハッシュで与えられると、`with_options`はブロックに対するプロキシオブジェクトを生成します。そのブロック内では、プロキシに対して呼び出されたメソッドにオプションを追加したうえで、そのメソッドをレシーバに転送します。たとえば、以下のように同じオプションを繰り返さないで済むようになります。

```ruby
class Account < ApplicationRecord
  has_many :customers, dependent: :destroy
  has_many :products,  dependent: :destroy
  has_many :invoices,  dependent: :destroy
  has_many :expenses,  dependent: :destroy
end
```

上は以下のようにできます。

```ruby
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
```

この手法を使用することで、たとえばニュースレターの読者を言語ごとに _グループ化_ することができます。読者が話す言語に応じて異なるニュースレターを送信したいとします。メール送信用のコードのどこかで、以下のような感じでロケール依存ビットをグループ化することができます。

```ruby
I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
  subject i18n.t :subject
  body    i18n.t :body, user_name: user.name
end
```

TIP: `with_options`はメソッドをレシーバに転送しているので、呼び出しをネストすることもできます。各ネスティングレベルでは、自身の呼び出しに、継承したデフォルト呼び出しをマージします。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/with_options.rb`です。

### JSON support

Active Supportが提供する`to_json`メソッドの実装は、通常`json` gemがRubyオブジェクトに対して提供している`to_json`よりも優れています。その理由は、`Hash`や`OrderedHash`、`Process::Status`などのクラスでは、正しいJSON表現を提供するために特別な処理が必要になるためです。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/json.rb`です。

### インスタンス変数

Active Supportは、インスタンス変数に簡単にアクセスするためのメソッドを多数提供しています。

#### `instance_values`

`instance_values`メソッドはハッシュを返します。インスタンス変数名から"@"を除いたものがハッシュのキーに、インスタンス変数の値がハッシュの値にマップされます。キーは文字列です。

```ruby
class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/instance_variables.rb`です。

#### `instance_variable_names`

`instance_variable_names`メソッドは配列を返します。配列のインスタンス名には"@"記号が含まれます。

```ruby
class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_variable_names # => ["@x", "@y"]
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/instance_variables.rb`です。

### 警告・例外の抑制

`silence_warnings`メソッドと`enable_warnings`メソッドは、ブロックが継続する間`$VERBOSE`の値を変更し、その後リセットします。

```ruby
silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
```

`suppress`メソッドを使用すると例外の発生を止めることもできます。このメソッドは、例外クラスを表す任意の数値を受け取ります。`suppress`は、あるブロックの実行時に例外が発生し、その例外が(`kind_of?`による判定で)いずれかの引数に一致する場合、それをキャプチャして例外を発生せずに戻ります。一致しない場合、例外はキャプチャされません。

```ruby
# ユーザーがロックされていればインクリメントは失われるが、重要ではない
suppress(ActiveRecord::StaleObjectError) do
  current_user.increment! :visits
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/kernel/reporting.rb`です。

### `in?`

述語`in?`は、あるオブジェクトが他のオブジェクトに含まれているかどうかをテストします。渡された引数が`include?`に応答しない場合は`ArgumentError`例外が発生します。

`in?`の例を示します。

```ruby
1.in?([1,2])        # => true
"lo".in?("hello")   # => true
25.in?(30..50)      # => false
1.in?(1)            # => ArgumentError
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/inclusion.rb`です。

`Module`の拡張
----------------------

### 属性

#### `alias_attribute`

モデルの属性には、リーダー (reader)、ライター (writer)、述語 (predicate) があります。上に対応する3つのメソッドを持つ、モデルの属性の別名 (alias) を一度に作成することができます。他の別名作成メソッドと同様、1つ目の引数には新しい名前、2つ目の引数には元の名前を指定します (変数に代入するときと同じ順序、と覚えておく手もあります)。

```ruby
class User < ApplicationRecord
  # emailカラムを"login"という名前でも参照したい
  # そうすることで認証のコードがわかりやすくなる
  alias_attribute :login, :email
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/aliasing.rb`です。

#### 内部属性

あるクラスで属性を定義すると、後にそのクラスのサブクラスが作成されるときに名前が衝突するリスクが生じます。これはライブラリにおいては特に重要な問題です。

Active Supportでは、`attr_internal_reader`、`attr_internal_writer`、`attr_internal_accessor`というマクロが定義されています。これらのマクロは、Rubyにビルトインされている`attr_*`と同様に振る舞いますが、内部のインスタンス変数の名前が衝突しにくいように配慮される点が異なります。

`attr_internal`マクロは`attr_internal_accessor`と同義です。

```ruby
# ライブラリ
class ThirdPartyLibrary::Crawler
  attr_internal :log_level
end

# クライアントコード
class MyCrawler < ThirdPartyLibrary::Crawler
  attr_accessor :log_level
end
```

先の例では、`:log_level`はライブラリのパブリックインターフェイスに属さず、開発用途にのみ使用されます。クライアント側のコードでは衝突の可能性について考慮せずに独自に`:log_level`をサブクラスで定義しています。ライブラリ側で`attr_internal`を使用しているおかげで衝突が生じずに済んでいます。

このとき、内部インスタンス変数の名前にはデフォルトで冒頭にアンダースコアが追加されます。上の例であれば`@_log_level`となります。この動作は`Module.attr_internal_naming_format`を使用して変更することもできます。`sprintf`と同様のフォーマット文字列を与え、冒頭に`@`を置き、それ以外の名前を置きたい場所に`%s`を置きます。デフォルト値は`"@_%s"`です。

Railsではこの内部属性を他の場所でも若干使用しています。たとえばビューでは以下のように使用しています。

```ruby
module ActionView
  class Base
    attr_internal :captures
    attr_internal :request, :layout
    attr_internal :controller, :template
  end
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attr_internal.rb`です。

#### モジュール属性

`mattr_reader`、`mattr_writer`、`mattr_accessor`という3つのマクロは、クラス用に定義される`cattr_*`マクロと同じです。実際、`cattr_*`マクロは単なる`mattr_*`マクロの別名です。[クラス属性](#class属性)も参照してください。

たとえば、これらのマクロは以下のDependenciesモジュールで使用されています。

```ruby
module ActiveSupport
  module Dependencies
    mattr_accessor :warnings_on_first_load
    mattr_accessor :history
    mattr_accessor :loaded
    mattr_accessor :mechanism
    mattr_accessor :load_paths
    mattr_accessor :load_once_paths
    mattr_accessor :autoloaded_constants
    mattr_accessor :explicitly_unloadable_constants
    mattr_accessor :constant_watch_stack
    mattr_accessor :constant_watch_stack_mutex
  end
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attribute_accessors.rb`です。

### 親

#### `parent`

`parent`メソッドは、名前がネストしたモジュールに対して実行でき、対応する定数を持つモジュールを返します。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parent # => X::Y
M.parent       # => X::Y
```

モジュールが無名またはトップレベルの場合、`parent`は`Object`を返します。

WARNING: `parent_name`は上の場合でも`nil`を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`です。

#### `parent_name`

`parent_name`メソッドは、名前がネストしたモジュールに対して実行でき、対応する定数を持つモジュールを返します。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parent_name # => "X::Y"
M.parent_name       # => "X::Y"
```

モジュールが無名またはトップレベルの場合、`parent_name`は`nil`を返します。

WARNING: `parent`は上の場合でも`Object`を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`。

#### `parents`

`parents`メソッドは、レシーバに対して`parent`を呼び出し、`Object`に到着するまでパスをさかのぼります。連鎖したモジュールは、階層の下から上の順に配列として返されます。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parents # => [X::Y, X, Object]
M.parents       # => [X::Y, X, Object]
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`です。

### 無名モジュール

モジュールは名前を持つことも、無名でいることもできます。

```ruby
module M
end
M.name # => "M"

N = Module.new
N.name # => "N"

Module.new.name # => nil
```

述語`anonymous?`を使用して、モジュールに名前があるかどうかをチェックできます。

```ruby
module M
end
M.anonymous? # => false

Module.new.anonymous? # => true
```

到達不能 (unreachable) であっても、必ずしも無名 (anonymous) になるとは限りません。

```ruby
module M
end

m = Object.send(:remove_const, :M)

m.anonymous? # => false
```

逆に無名モジュールは、定義上必ず到達不能になります。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/anonymous.rb`です。

### メソッド委譲

#### `delegate`

`delegate`マクロを使用すると、メソッドを簡単に委譲できます。

あるアプリケーションの`User`モデルにログイン情報があり、それに関連する名前などの情報は`Profile`モデルにあるとします。

```ruby
class User < ApplicationRecord
  has_one :profile
end
```

この構成では、`user.profile.name`のようにプロファイル越しにユーザー名を取得することになります。これらの属性に直接アクセスできたらもっと便利になることでしょう。

```ruby
class User < ApplicationRecord
  has_one :profile

  def name
    profile.name
  end
end
```

`delegate`を使用すればできるようになります。

```ruby
class User < ApplicationRecord
  has_one :profile

  delegate :name, to: :profile
end
```

この方法なら記述が短くて済み、意味もはっきりします。

使用するメソッドは対象クラス内でpublicである必要があります。

`delegate`マクロには複数のメソッドを指定できます。

```ruby
delegate :name, :age, :address, :twitter, to: :profile
```

`:to`オプションが文字列に変換されると、メソッドの委譲先となるオブジェクトに評価される式になります。通常は文字列またはシンボルになります。そのような式は、レシーバのコンテキストで評価されます。

```ruby
# Rails定数を委譲する
delegate :logger, to: :Rails

# レシーバのクラスに委譲する
delegate :table_name, to: :class
```

WARNING: `:prefix`オプションが`true`の場合、一般性が低下します (後述)。

委譲時に`NoMethodError`が発生して対象が`nil`の場合、例外が発生します。`:allow_nil`オプションを使用すると、例外の代りに`nil`を返すようにすることができます。

```ruby
delegate :name, to: :profile, allow_nil: true
```

`:allow_nil`を指定すると、ユーザーのプロファイルがない場合に`user.name`呼び出しは`nil`を返します。

`:prefix`オプションをtrueにすると、生成されたメソッドの名前にプレフィックスを追加します。これは、たとえばよりよい名前にしたい場合に便利です。

```ruby
delegate :street, to: :address, prefix: true
```

上の例では、`street`ではなく`address_street`が生成されます。

WARNING: この場合、生成されるメソッドの名前では、対象となるオブジェクト名とメソッド名が使用されます。`:to`オプションで指定するのはメソッド名でなければなりません。

プレフィックスをカスタマイズすることもできます。

```ruby
delegate :size, to: :attachment, prefix: :avatar
```

上の例では、マクロによって`size`の代わりに`avatar_size`が生成されます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/delegation.rb`です。

#### `delegate_missing_to`

`User`オブジェクトにないものを`Profile`にあるものにすべて委譲したいとしましょう。`delegate_missing_to`マクロを使えばこれを簡単に実装できます。

```ruby
class User < ApplicationRecord
  has_one :profile

  delegate_missing_to :profile
end
```

オブジェクト内にある呼び出し可能なもの（インスタンス変数、メソッド、定数など）なら何でも対象にできます。対象のうち、publicなメソッドだけが委譲されます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/delegation.rb`です。

### メソッドの再定義

`define_method`を使用してメソッドを再定義する必要があるが、その名前が既にあるかどうかがわからないとことがあります。有効な名前が既にあれば警告が表示されます。警告が表示されても大したことはありませんが、邪魔に思えることもあります。

`redefine_method`メソッドを使用すれば、必要に応じて既存のメソッドが削除されるので、このような警告表示を抑制できます。

（`delegate`を使っているなどの理由で）メソッド自身の置き換えを定義する必要がある場合は、`silence_redefinition_of_method`を使うこともできます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/redefine_method.rb`です。

`Class`の拡張
---------------------

### Class属性

#### `class_attribute`

`class_attribute`メソッドは、1つ以上の継承可能なクラスの属性を宣言します。そのクラス属性は、その下のどの階層でも上書き可能です。

```ruby
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
```

たとえば、`ActionMailer::Base`に以下の定義があるとします。

```ruby
class_attribute :default_params
self.default_params = {
  mime_version: "1.0",
  charset: "UTF-8",
  content_type: "text/plain",
  parts_order: [ "text/plain", "text/enriched", "text/html" ]
}.freeze
```

これらの属性はインスタンスのレベルでアクセスまたはオーバーライドできます。

```ruby
A.x = 1

a1 = A.new
a2 = A.new
a2.x = 2

a1.x # => 1 (Aが使われる)
a2.x # => 2 (a2でオーバーライドされる)
```

`:instance_writer`を`false`に設定すれば、writerインスタンスメソッドは生成されません。

```ruby
module ActiveRecord
  class Base
    class_attribute :table_name_prefix, instance_writer: false, default: "my"
  end
end
```

上のオプションは、モデルの属性設定時にマスアサインメントを防止するのに便利です。

`:instance_reader`を`false`に設定すれば、readerインスタンスメソッドは生成されません。

```ruby
class A
  class_attribute :x, instance_reader: false
end

A.new.x = 1
A.new.x # NoMethodError
```

利便性のために、`class_attribute`は、インスタンスのreaderが返すものを「二重否定」するインスタンス述語も定義されます。上の例の場合、`x?`となります。

`:instance_reader`が`false`の場合、インスタンス述語はreaderメソッドと同様に`NoMethodError`を返します。

インスタンス述語が不要な場合、`instance_predicate: false`を指定すれば定義されなくなります。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/attribute.rb`です。

#### `cattr_reader`、`cattr_writer`、`cattr_accessor`

`cattr_reader`、`cattr_writer`、`cattr_accessor`マクロは、`attr_*`と似ていますが、クラス用である点が異なります。これらのメソッドは、クラス変数を`nil`に設定し (クラス変数が既にある場合を除く)、対応するクラスメソッドを生成してアクセスできるようにします。

```ruby
class MysqlAdapter < AbstractAdapter
  # @@emulate_booleansにアクセスできるクラスメソッドを生成する
  cattr_accessor :emulate_booleans, default: true
end
```

利便性のため、このときインスタンスメソッドも生成されますが、これらは実際にはクラス属性の単なるプロキシです。従って、インスタンスからクラス属性を変更することはできますが、`class_attribute`で行われるように上書きすることはできません(上記参照)。たとえば以下の場合、

```ruby
module ActionView
  class Base
    cattr_accessor :field_error_proc, default: Proc.new { ... }
  end
end
```

ビューで`field_error_proc`にアクセスできます。

同様に、`cattr_*`にブロックを渡して属性にデフォルト値を設定することもできます。

```ruby
class MysqlAdapter < AbstractAdapter
  # @@emulate_booleansにアクセスしてデフォルト値をtrueにするクラスメソッドを生成
  cattr_accessor :emulate_booleans, default: true
end
```

`:instance_reader`オプションを`false`に設定することで、readerインスタンスメソッドが生成されないようにできます。同様に、`:instance_writer`オプションを`false`に設定することで、writerインスタンスメソッドが生成されないようにできます。`:instance_accessor`オプションを`false`に設定すれば、どちらのインスタンスメソッドも生成されません。いずれの場合も、指定できる値は`false`のみです。'nil'など他のfalse値は指定できません。

```ruby
module A
  class B
    # first_nameインスタンスreaderは生成されない
    cattr_accessor :first_name, instance_reader: false
    # last_name= インスタンスwriterは生成されない
    cattr_accessor :last_name, instance_writer: false
    # surnameインスタンスreaderもsurname= インスタンスwriterも生成されない
    cattr_accessor :surname, instance_accessor: false
  end
end
```

`:instance_accessor`を`false`に設定すると、モデルの属性設定時にマスアサインメントを防止するのに便利です。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attribute_accessors.rb`です。

### サブクラスと子孫

#### `subclasses`

`subclasses`メソッドはレシーバのサブクラスを返します。

```ruby
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]
```

返されるクラスの順序は一定ではありません。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/subclasses.rb`です。

#### `descendants`

`descendants`メソッドは、そのレシーバより下位にあるすべてのクラスを返します。

```ruby
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]
```

返されるクラスの順序は一定ではありません。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/subclasses.rb`です。

`String`の拡張
----------------------

### 安全な出力

#### 開発の動機

HTMLテンプレートにデータを挿入する方法は、きわめて慎重に設計する必要があります。たとえば、`@review.title`を何の工夫もなくそのままHTMLに式展開するようなことは絶対にすべきではありません。もしこのレビューのタイトルが仮に"Flanagan & Matz rules!"だとしたら、出力はwell-formedになりません。well-formedにするには、"&amp;amp;"のようにエスケープしなければなりません。さらに、ユーザーがレビューのタイトルに細工をして、悪意のあるHTMLをタイトルに含めれば、巨大なセキュリティホールになることすらあります。このリスクの詳細については、[セキュリティガイド](security.html#クロスサイトスクリプティング-xss)のクロスサイトスクリプティングの節を参照してください。

#### 安全な文字列

Active Supportには「(html的に) 安全な文字列」という概念があります。安全な文字列とは、HTMLにそのまま挿入しても問題がないというマークが付けられている文字列です。マーキングさえされていれば、「実際にエスケープされているかどうかにかかわらず」その文字列は信頼されます。

文字列はデフォルトでは _unsafe_ とマークされます。

```ruby
"".html_safe? # => false
```

与えられた文字列に`html_safe`メソッドを適用することで、安全な文字列を得ることができます。

```ruby
s = "".html_safe
s.html_safe? # => true
```

ここで注意しなければならないのは、`html_safe`メソッドそれ自体は何らエスケープを行なっていないということです。安全であるとマーキングしているに過ぎません。

```ruby
s = "<script>...</script>".html_safe
s.html_safe? # => true
s            # => "<script>...</script>"
```

従って、特定の文字列に対して`html_safe`メソッドを呼び出す際には、その文字列が本当に安全であることを確認する義務があります。

安全であると宣言された文字列に対し、安全でない文字列を`concat`/`<<`または`+`を使用して破壊的に追加すると、結果は安全な文字列になります。安全でない引数は追加時にエスケープされます。

```ruby
"".html_safe + "<" # => "&lt;"
```

安全な引数であれば、(エスケープなしで)直接追加されます。

```ruby
"".html_safe + "<".html_safe # => "<"
```

基本的にこれらのメソッドは、通常のビューでは使用しないでください。現在のRailsのビューでは、安全でない値は自動的にエスケープされるためです。

```erb
<%= @review.title %> <%# 必要に応じてエスケープされるので問題なし %>
```

何らかの理由で、エスケープされていない文字列を挿入したい場合は、`html_safe`を呼ぶのではなく、`raw`ヘルパーを使用するようにしてください。

```erb
<%= raw @cms.current_template %> <%# @cms.current_templateをそのまま挿入 %>
```

あるいは、`raw`と同等の`<%==`を使用します。

```erb
<%== @cms.current_template %> <%# @cms.current_templateをそのまま挿入 %>
```

`raw`ヘルパーは、内部で`html_safe`を呼び出します。

```ruby
def raw(stringish)
  stringish.to_s.html_safe
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/output_safety.rb`です。

#### 各種変換

経験上、上で説明したような連結 (concatenation) 操作を除き、どんなメソッドでも潜在的には文字列を安全でないものに変換してしまう可能性があることに常に注意を払う必要があります。そのようなメソッドには`downcase`、`gsub`、`strip`、`chomp`、`underscore`などがあります。

`gsub!`のような破壊的な変換を行なうメソッドを使用すると、レシーバ自体が安全でなくなります。

INFO: こうしたメソッドを実行すると、実際に変換が行われたかどうかにかかわらず、安全を表すビットは常にオフになります。

#### 変換と強制

安全な文字列に対して`to_s`を実行した場合は、安全な文字列が返されます。しかし、`to_str`による強制的な変換を実行した場合には安全でない文字列が返されます。

#### コピー

安全な文字列に対して`dup`または`clone`を実行した場合は、安全な文字列が生成されます。

### `remove`

`remove`メソッドを実行すると、すべての該当パターンが削除されます。

```ruby
"Hello World".remove(/Hello /) # => "World"
```

このメソッドには破壊的なバージョンの`String#remove!`もあります。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `squish`

`squish`メソッドは、冒頭と末尾のホワイトスペースを除去し、連続したホワイトスペースを1つに減らします。

```ruby
" \n  foo\n\r \t bar \n".squish # => "foo bar"
```

このメソッドには破壊的なバージョンの`String#squish!`もあります。

このメソッドでは、ASCIIとUnicodeのホワイトスペースを扱えます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `truncate`

`truncate`メソッドは、指定された`length`にまで長さを切り詰めたレシーバのコピーを返します。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."
```

`:omission`オプションを指定することで、省略文字 (…) をカスタマイズすることもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20, omission: '&hellip;')
# => "Oh dear! Oh &hellip;"
```

文字列の切り詰めでは、省略文字列の長さも加味されることに特にご注意ください。

`:separator`を指定することで、自然な区切り位置で切り詰めることができます。

```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..."
```

`:separator`オプションで正規表現を使用することもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."
```

上の例では、"dear"という文字で切り落とされそうになるところを、`:separator`によって防いでいます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `truncate_words`

`truncate_words`メソッドは、指定されたワード数から後ろをきりおとしたレシーバのコピーを返します。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4)
# => "Oh dear! Oh dear!..."
```

`:omission`オプションを指定することで、省略文字 (…) をカスタマイズすることもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4, omission: '&hellip;')
# => "Oh dear! Oh dear!&hellip;"
```

`:separator`を指定することで、自然な区切り位置で切り詰めることができます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(3, separator: '!')
# => "Oh dear! Oh dear! I shall be late..."
```

`:separator`オプションで正規表現を使用することもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4, separator: /\s/)
# => "Oh dear! Oh dear!..."
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `inquiry`

`inquiry`は、文字列を`StringInquirer`オブジェクトに変換します。このオブジェクトを使用すると、等しいかどうかをよりスマートにチェックできます。

```ruby
"production".inquiry.production? # => true
"active".inquiry.inactive?       # => false
```

### `starts_with?`と`ends_with?`

Active Supportでは、`String#start_with?`と`String#end_with?`を英語的に自然な三人称(starts、ends)にした別名も定義してあります。

```ruby
"foo".starts_with?("f") # => true
"foo".ends_with?("o")   # => true
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/starts_ends_with.rb`です。

### `strip_heredoc`

`strip_heredoc`メソッドは、ヒアドキュメントのインデントを除去します。

以下に例を示します。

```ruby
if options[:usage]
  puts <<-USAGE.strip_heredoc
    This command does such and such.

    Supported options are:
      -h         This message
      ...
  USAGE
end
```

このUSAGEメッセージは左寄せで表示されます。

技術的には、インデントが一番浅い行を探して、そのインデント分だけ行頭のホワイトスペースを全体から削除するという操作を行っています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/strip.rb`です。

### `indent`

このメソッドは、レシーバの行にインデントを与えます。

```ruby
<<EOS.indent(2)
def some_method
  some_code
end
EOS
# =>
  def some_method
    some_code
  end
```

2つめの引数`indent_string`は、インデントに使用する文字列を指定します。デフォルトは`nil`であり、この場合最初にインデントされている行のインデント文字を参照してそこからインデント文字を推測します。インデントがまったくない場合はスペース1つを使用します。

```ruby
"  foo".indent(2)        # => "    foo"
"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
"foo".indent(2, "\t")    # => "\t\tfoo"
```

`indent_string`には1文字のスペースまたはタブを使用するのが普通ですが、どんな文字でも使用できます。

3つ目の引数`indent_empty_lines`は、空行もインデントするかどうかを指定するフラグです。デフォルトはfalseです。

```ruby
"foo\n\nbar".indent(2)            # => "  foo\n\n  bar"
"foo\n\nbar".indent(2, nil, true) # => "  foo\n  \n  bar"
```

`indent!`メソッドはインデントをその場で (破壊的に) 行います。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/indent.rb`です。

### Access

#### `at(position)`

対象となる文字列のうち、`position`で指定された位置にある文字を返します。

```ruby
"hello".at(0)  # => "h"
"hello".at(4)  # => "o"
"hello".at(-1) # => "o"
"hello".at(10) # => nil
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `from(position)`

文字列のうち、`position`で指定された位置から始まる部分文字列を返します。

```ruby
"hello".from(0)  # => "hello"
"hello".from(2)  # => "llo"
"hello".from(-2) # => "lo"
"hello".from(10) # => nil
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `to(position)`

文字列のうち、`position`で指定された位置を終端とする部分文字列を返します。

```ruby
"hello".to(0)  # => "h"
"hello".to(2)  # => "hel"
"hello".to(-2) # => "hell"
"hello".to(10) # => "hello"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `first(limit = 1)`

`str.first(n)`という呼び出しは、`n` > 0 のとき`str.to(n-1)`と等価です。`n` == 0の場合は空文字列を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `last(limit = 1)`

`str.last(n)` という呼び出しは、`n` > 0 のとき`str.from(-n)`と等価です。`n` == 0 の場合は空文字列を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

### 活用形

#### `pluralize`

`pluralize`メソッドは、レシーバを「複数形」にしたものを返します。

```ruby
"table".pluralize     # => "tables"
"ruby".pluralize      # => "rubies"
"equipment".pluralize # => "equipment"
```

上の例でも示したように、Active Supportは不規則な複数形や非可算名詞についてある程度知っています。`config/initializers/inflections.rb`にあるビルトインのルールは拡張可能です。このファイルは`rails`コマンドで拡張可能であり、方法はコメントに示されています。

`pluralize`メソッドではオプションで`count`パラメータを使用できます。もし`count == 1`を指定すると単数形が返されます。`count`がそれ以外の値の場合は複数形を返します(訳注: 英語では個数がゼロや小数の場合は複数形で表されます)。

```ruby
"dude".pluralize(0) # => "dudes"
"dude".pluralize(1) # => "dude"
"dude".pluralize(2) # => "dudes"
```

Active Recordでは、モデル名に対応するデフォルトのテーブル名を求めるときにこのメソッドを使用しています。

```ruby
# active_record/model_schema.rb
def undecorated_table_name(class_name = base_class.name)
  table_name = class_name.to_s.demodulize.underscore
  pluralize_table_names ? table_name.pluralize : table_name
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `singularize`

`pluralize`と逆の動作です。

```ruby
"tables".singularize    # => "table"
"rubies".singularize    # => "ruby"
"equipment".singularize # => "equipment"
```

Railsの関連付け (association) では、関連付けられたクラスにデフォルトで対応する名前を求める時にこのメソッドが使用されます。

```ruby
# 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: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `camelize`

`camelize`メソッドは、レシーバをキャメルケース (冒頭を大文字にした単語をスペースなしで連結した語) にしたものを返します。

```ruby
"product".camelize    # => "Product"
"admin_user".camelize # => "AdminUser"
```

このメソッドは、パスをRubyのクラスに変換するときにもよく使用されます。スラッシュで区切られているパスは「::」で区切られます。

```ruby
"backoffice/session".camelize # => "Backoffice::Session"
```

たとえばAction Packでは、特定のセッションストアを提供するクラスを読み込むのにこのメソッドを使用しています。

```ruby
# 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`メソッドはオプションの引数を受け付けます。使用できるのは`:upper` (デフォルト) または`:lower`です。後者を指定すると、冒頭が小文字になります。

```ruby
"visual_effect".camelize(:lower) # => "visualEffect"
```

このメソッドは、そのような命名慣習に従っている言語 (JavaScriptなど) で使用される名前を求めるのに便利です。

INFO: `camerize`メソッドの動作は、`underscore`メソッドと逆の動作と考えるとわかりやすいでしょう。ただし完全に逆の動作ではありません。たとえば、`"SSLError".underscore.camelize`を実行した結果は`"SslError"`になり、元に戻りません。このような場合をサポートするために、Active Supportでは`config/initializers/inflections.rb`の頭字語を指定することができます。

```ruby
ActiveSupport::Inflector.inflections do |inflect|
  inflect.acronym 'SSL'
end

"SSLError".underscore.camelize # => "SSLError"
```

`camelize`は`camelcase`の別名です。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `underscore`

`underscore`メソッドは上と逆に、キャメルケースをパスに変換します。

```ruby
"Product".underscore   # => "product"
"AdminUser".underscore # => "admin_user"
```

"::"も"/"に逆変換されます。

```ruby
"Backoffice::Session".underscore # => "backoffice/session"
```

小文字で始まる文字列も扱えます。

```ruby
"visualEffect".underscore # => "visual_effect"
```

ただし`underscore`は引数を取りません。

Railsで自動的に読み込まれるクラスとモジュールは、`underscore`メソッドを使用してファイルの拡張子を除いた相対パスを推測し、指定された定数が失われている場合にそれを定義するのに役立てます。

```ruby
# active_support/dependencies.rb
def load_missing_constant(from_mod, const_name)
  ...
  qualified_name = qualified_name_for from_mod, const_name
  path_suffix = qualified_name.underscore
  ...
end
```

INFO: `underscore`メソッドの動作は、`camelize`メソッドと逆の動作と考えるとわかりやすいでしょう。ただし完全に逆の動作ではありません。たとえば、`"SSLError".underscore.camelize`を実行した結果は`"SslError"`になり、元に戻りません。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `titleize`

`titleize`メソッドは、レシーバの語の1文字目を大文字にします。

```ruby
"alice in wonderland".titleize # => "Alice <NAME>"
"fermat's enigma".titleize     # => "Fermat's Enigma"
```

`titleize`メソッドは`titlecase`の別名です。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `dasherize`

`dasherize`メソッドは、レシーバのアンダースコア文字をダッシュに置き換えます(訳注: ここで言うダッシュは実際には「ハイフンマイナス文字」(U+002D)です)。

```ruby
"name".dasherize         # => "name"
"contact_data".dasherize # => "contact-data"
```

モデルのXMLシリアライザではこのメソッドを使用してノード名をダッシュ化しています。

```ruby
# active_model/serializers/xml.rb
def reformat_name(name)
  name = name.camelize if camelize?
  dasherize? ? name.dasherize : name
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `demodulize`

`demodulize`メソッドは、フルパスの (qualified) 定数名を与えられると、パス部分を取り除いて右側の定数名だけにしたものを返します。

```ruby
"Product".demodulize                        # => "Product"
"Backoffice::UsersController".demodulize    # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
"::Inflections".demodulize                  # => "Inflections"
"".demodulize                               # => ""

```

以下のActive Recordの例では、このメソッドを使用してcounter_cacheカラムの名前を求めています。

```ruby
# 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
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `deconstantize`

`deconstantize`メソッドは、フルパスの定数を表す参照表現を与えられると、一番右の部分 (通常は定数名) を取り除きます。

```ruby
"Product".deconstantize                        # => ""
"Backoffice::UsersController".deconstantize    # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `parameterize`

`parameterize`メソッドは、レシーバを正しいURLで使用可能な形式に正規化します。

```ruby
"<NAME>".parameterize # => "john-smith"
"<NAME>".parameterize # => "kurt-godel"
```

文字列の大文字小文字が変わらないようにするには、`preserve_case`引数に`true`を指定します。`preserve_case`はデフォルトでは`false`になります。

```ruby
"<NAME>".parameterize(preserve_case: true) # => "John-Smith"
"<NAME>".parameterize(preserve_case: true) # => "Kurt-Godel"
```

独自のセパレータを使うには、`separator`引数をオーバーライドします。

```ruby
"<NAME>".parameterize(separator: "_") # => "john\_smith"
"<NAME>".parameterize(separator: "_") # => "kurt\_godel"
```

実際に得られる文字列は、`ActiveSupport::Multibyte::Chars`のインスタンスでラップされています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `tableize`

`tableize`メソッドは、`underscore`の次に`pluralize`を実行したものです。

```ruby
"Person".tableize      # => "people"
"Invoice".tableize     # => "invoices"
"InvoiceLine".tableize # => "invoice_lines"
```

単純な場合であれば、モデル名に`tableize`を使用するとモデルのテーブル名を得られます。実際のActive Recordの実装は、単に`tableize`を実行する場合よりも複雑です。Active Recordではクラス名に対して`demodulize`も行っており、返される文字列に影響する可能性のあるオプションもいくつかチェックしています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `classify`

`classify`メソッドは、`tableize`と逆の動作です。与えられたテーブル名に対応するクラス名を返します。

```ruby
"people".classify        # => "Person"
"invoices".classify      # => "Invoice"
"invoice_lines".classify # => "InvoiceLine"
```

このメソッドは、フルパスの (qualified) テーブル名も扱えます。

```ruby
"highrise_production.companies".classify # => "Company"
```

`classify`が返すクラス名は文字列であることにご注意ください。得られた文字列に対して`constantize` (後述) を実行することで本当のクラスオブジェクトを得られます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `constantize`

`constantize`メソッドは、レシーバの定数参照表現を解決し、実際のオブジェクトを返します。

```ruby
"Fixnum".constantize # => Fixnum

module M
  X = 1
end
"M::X".constantize # => 1
```

与えられた文字列を`constantize`メソッドで評価しても既知の定数とマッチしない、または指定された定数名が正しくない場合は`NameError`が発生します。

`constantize`メソッドによる定数名解決は、常にトップレベルの`Object`から開始されます。これは上位に"::"がない場合でも同じです。

```ruby
X = :in_Object
module M
  X = :in_M

  X                 # => :in_M
  "::X".constantize # => :in_Object
  "X".constantize   # => :in_Object (!)
end
```

従って、このメソッドは、同じ場所でRubyが定数を評価したときの値と必ずしも等価ではありません。

メイラー (mailer) のテストケースでは、テストするクラスの名前からテスト対象のメイラーを取得するのに`constantize`メソッドを使用します。

```ruby
# action_mailer/test_case.rb
def determine_default_mailer(name)
  name.sub(/Test$/, '').constantize
rescue NameError => e
  raise NonInferrableMailerError.new(name)
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `humanize`

`humanize`メソッドは、属性名を (英語的に) 読みやすい表記に変換します。

具体的には以下の変換を行います。

  * 引数に (英語の) 活用ルールを適用します(inflection)。
  * 冒頭にアンダースコアがある場合は削除します。
  * 末尾に"_id"がある場合は削除します。
  * アンダースコアが他にもある場合はスペースに置き換えます。
  * 略語を除いてすべての単語を小文字にします(downcase)。
  * 最初の単語だけ冒頭の文字を大文字にします(capitalize)。

`:capitalize`オプションをfalseにすると、冒頭の文字は大文字にされません(デフォルトはtrue)。

```ruby
"name".humanize                         # => "Name"
"author_id".humanize                    # => "Author"
"author_id".humanize(capitalize: false) # => "author"
"comments_count".humanize               # => "Comments count"
"_id".humanize                          # => "Id"
```

"SSL"が頭字語と定義されている場合は以下のようにエラーになります。

```ruby
'ssl_error'.humanize # => "SSL error"
```

ヘルパーメソッド`full_messages`では、属性名をメッセージに含めるときに`humanize`を使用しています。


```ruby
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
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `foreign_key`
<commit_msg>Fix description of String#humanize with acronym<commit_after>


Active Support コア拡張機能
==============================

Active SupportはRuby on Railsのコンポーネントであり、Ruby言語の拡張、ユーティリティ、その他横断的な作業を担っています。

Active Supportは言語レベルで基本部分を底上げして豊かなものにし、Railsアプリケーションの開発とRuby on Railsそれ自体の開発に役立てるべく作られています。

このガイドの内容:

* コア拡張機能について
* すべての拡張機能を読み込む方法
* 必要な拡張機能だけを利用する方法
* Active Supportが提供する拡張機能一覧

--------------------------------------------------------------------------------

コア拡張機能を読み込む方法
---------------------------

### 単体のActive Support

足跡をほぼ残さないようにするため、Active Supportはデフォルトでは何も読み込みません。Active Supportは細かく分割され、必要な拡張機能だけが読み込まれるようになっています。また、関連する拡張機能(場合によってはすべての拡張機能)も同時に読み込むのに便利なエントリポイントもあります。

従って、以下のようなrequire文を実行しただけでは

```ruby
require 'active_support'
```

オブジェクトは`blank?`にすら応答してくれません。この定義がどのように読み込まれるかを見てみましょう。

#### 必要な定義だけを選ぶ

`blank?`メソッドを使えるようにする最も「軽量な」方法は、そのメソッドが定義されているファイルだけを選んで読み込むことです。

本ガイドでは、コア拡張機能として定義されているすべてのメソッドについて、その定義ファイルの置き場所も示してあります。たとえば`blank?`の場合、以下のようなメモを追加してあります。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

つまり、以下のようにピンポイントでrequireを実行することができます。

```ruby
require 'active_support'
require 'active_support/core_ext/object/blank'
```

Active Supportの改訂は注意深く行われていますので、あるファイルを選んだ場合、本当に必要な依存ファイルだけが同時に読み込まれます(依存関係がある場合)。

#### コア拡張機能をグループ化して読み込む

次の段階として、`Object`に対するすべての拡張機能を単に読み込んでみましょう。経験則として、`SomeClass`というクラスがあれば、`active_support/core_ext/some_class`というパスを指定することで一度に読み込めます。

従って、(`blank?`を含む)`Object`に対するすべての拡張機能を読み込む場合には以下のようにします。

```ruby
require 'active_support'
require 'active_support/core_ext/object'
```

#### すべてのコア拡張機能を読み込む

すべてのコア拡張機能を単に読み込んでおきたいのであれば、以下のようにrequireします。

```ruby
require 'active_support'
require 'active_support/core_ext'
```

#### すべてのActive Supportを読み込む

最後に、利用可能なActive Supportをすべて読み込みたい場合は以下のようにします。

```ruby
require 'active_support/all'
```

ただし、これを実行してもActive Support全体がメモリに読み込まれるわけではないことにご注意ください。一部は`autoload`として設定されており、実際に使うまで読み込まれません。

### Ruby on RailsアプリケーションでActive Supportを使用する

Ruby on Railsアプリケーションでは、基本的にすべてのActive Supportを読み込みます。例外は`config.active_support.bare`をtrueに設定した場合です。このオプションをtrueにすると、フレームワーク自体が必要とするまでアプリケーションは拡張機能を読み込みません。また、読み込まれる拡張機能の選択は、上で解説したように、あらゆる粒度で行われます。

すべてのオブジェクトで使用できる拡張機能
-------------------------

### `blank?`と`present?`

Railsアプリケーションは以下の値を空白(blank)とみなします。

* `nil`と`false`

* 空白文字 (whitespace) だけで構成された文字列 (以下の注釈参照)

* 空欄の配列とハッシュ

* その他、`empty?`メソッドに応答するオブジェクトはすべて空白として扱われます。

INFO: 文字列を判定する述語として、Unicode対応した文字クラスである`[:space:]`が使用されています。そのため、たとえばU+2029 (段落区切り文字)は空白文字と判断されます。

WARNING: 数字については空白であるかどうかは判断されません。特に0および0.0は**空白ではありません**のでご注意ください。

たとえば、`ActionController::HttpAuthentication::Token::ControllerMethods`にある以下のメソッドでは`blank?`を使用してトークンが存在しているかどうかをチェックしています。

```ruby
def authenticate(controller, &login_procedure)
  token, options = token_and_options(controller.request)
  unless token.blank?
    login_procedure.call(token, options)
  end
end
```

`present?`メソッドは`!blank?`メソッドと同等です。以下の例は`ActionDispatch::Http::Cache::Response`から引用しました。

```ruby
def set_conditional_cache_control!
  return if self["Cache-Control"].present?
  ...
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

### `presence`

`presence`メソッドは、`present?`がtrueの場合は自身のレシーバを返し、falseの場合は`nil`を返します。このメソッドは以下のような定番の用法において便利です。

```ruby
host = config[:host].presence || 'localhost'
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/blank.rb`です。

### `duplicable?`

Ruby 2.4では、メソッドや特定の数値を除くほとんどのオブジェクトが`dup`や`clone`で複製できます。Ruby 2.2や2.3では、`nil`, `false`, `true`、シンボル、`Float`/`Fixnum`/`Bignum`のインスタンスは複製できません。

Rubyにおける基本的なオブジェクトの一部はsingletonオブジェクトです。たとえば、プログラムのライフサイクルが続く間、整数の1は常に同じインスタンスを参照します。

```ruby
"foo".dup           # => "foo"
"".dup              # => ""
1.method(:+).dup    # => TypeError: allocator undefined for Method
Complex(0).dup      # => TypeError: can't copy Complex
```

Active Supportでは、複製可能かどうかをオブジェクトに問い合わせる`duplicable?`が提供されています。

```ruby
"foo".duplicable?           # => true
"".duplicable?              # => true
Rational(1).duplicable?     # => false
Complex(1).duplicable?      # => false
1.method(:+).duplicable?    # => false
```

`duplicable?`は、Rubyのバージョンに応じた`dup`にマッチします。

つまり、2.4では次のようになります。

```ruby
nil.dup                 # => nil
:my_symbol.dup          # => :my_symbol
1.dup                   # => 1

nil.duplicable?         # => true
:my_symbol.duplicable?  # => true
1.duplicable?           # => true
```

一方、2.2や2.3では次のようになります。

```ruby
nil.dup                 # => TypeError: can't dup NilClass
:my_symbol.dup          # => TypeError: can't dup Symbol
1.dup                   # => TypeError: can't dup Fixnum
nil.duplicable?         # => false
:my_symbol.duplicable?  # => false
1.duplicable?           # => false
```

デフォルトでは、`nil`、`false`、`true`、シンボル、数値、クラス、モジュール、メソッドオブジェクトを除くすべてのオブジェクトが`duplicable?` #=> trueです。

WARNING: どんなクラスでも、`dup`メソッドと`clone`メソッドを除去することでこれらのメソッドを無効にしてしまうことができます。このとき、これらのメソッドが実行されると例外が発生します。このような状態では、どんなオブジェクトについてもそれが複製可能かどうかを確認するには`rescue`を使用する以外に方法はありません。`duplicable?`メソッドは、上のハードコードされたリストに依存しますが、その代わり`rescue`よりずっと高速です。実際のユースケースでハードコードされたリストで十分であることがわかっている場合には、`duplicable?`をお使いください。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/duplicable.rb`です。

### `deep_dup`

`deep_dup`メソッドは、与えられたオブジェクトの「ディープコピー」を返します。Rubyは通常の場合、他のオブジェクトを含むオブジェクトを`dup`しても、他のオブジェクトについては複製しません。このようなコピーは「浅いコピー (shallow copy)」と呼ばれます。たとえば、以下のように文字列を含む配列があるとします。

```ruby
array     = ['string']
duplicate = array.dup

duplicate.push 'another-string'

# このオブジェクトは複製されたので、複製された方にだけ要素が追加された
array     # => ['string']
duplicate # => ['string', 'another-string']

duplicate.first.gsub!('string', 'foo')

# 1つ目の要素は複製されていないので、一方を変更するとどちらの配列も変更される
array     # => ['foo']
duplicate # => ['foo', 'another-string']
```

上で見たとおり、`Array`のインスタンスを複製して別のオブジェクトができたことにより、一方を変更しても他方は変更されないようになりました。ただし、配列は複製されましたが、配列の要素はそうではありません。`dup`メソッドはディープコピーを行わないので、配列の中にある文字列は複製後も同一オブジェクトのままです。

オブジェクトをディープコピーする必要がある場合は`deep_dup`をお使いください。例:

```ruby
array     = ['string']
duplicate = array.deep_dup

duplicate.first.gsub!('string', 'foo')

array     # => ['string']
duplicate # => ['foo']
```

オブジェクトが複製不可能な場合、`deep_dup`は単にそのオブジェクトを返します。

```ruby
number = 1
duplicate = number.deep_dup
number.object_id == duplicate.object_id   # => true
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/deep_dup.rb`です。

### `try`

`nil`でない場合にのみオブジェクトのメソッドを呼び出したい場合、最も単純な方法は条件文を追加することですが、どこか冗長になってしまいます。そこで`try`メソッドを使うという手があります。`try`は`Object#send`と似ていますが、`nil`に送信された場合には`nil`を返す点が異なります。

例:

```ruby
# tryメソッドを使用しない場合
unless @number.nil?
  @number.next
end

# tryメソッドを使用した場合
@number.try(:next)
```

`ActiveRecord::ConnectionAdapters::AbstractAdapter`から別の例として以下をご紹介します。ここでは`@logger`が`nil`になることがあります。このコードでは`try`を使用したことで余分なチェックを行わずに済んでいます。

```ruby
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`メソッドは引数の代りにブロックを与えて呼び出すこともできます。この場合オブジェクトが`nil`でない場合にのみブロックが実行されます。

```ruby
@person.try { |p| "#{p.first_name} #{p.last_name}" }
```

`try`メソッドは、`NoMethodError`を握りつぶして代わりに`nil`を返す点に注意が必要です。メソッド名の誤りを防ぎたい場合は`try!`を使います。

```ruby
@number.try(:nest)  # => nil
@number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/try.rb`です。

### `class_eval(*args, &block)`

`class_eval`メソッドを使用することで、あらゆるオブジェクトのsingletonクラスのコンテキストでコードを評価することができます。

```ruby
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: 定義ファイルの場所は`active_support/core_ext/kernel/singleton_class.rb`です。

### `acts_like?(duck)`

`acts_like?`メソッドは、一部のクラスがその他のクラスと同様に振る舞うかどうかのチェックを、ある慣例に則って実行します。`String`クラスと同じインターフェイスを提供するクラスがあり、その中で以下のメソッドを定義しておくとします。

```ruby
def acts_like_string?
end
```

このメソッドは単なる目印であり、メソッドの本体と戻り値の間には関連はありません。これにより、クライアントコードで以下のようなダックタイピングチェックを行なうことができます。

```ruby
some_klass.acts_like?(:string)
```

Railsには`Date`クラスや`Time`クラスと同様に振る舞うクラスがいくつかあり、この手法を使用できます。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/acts_like.rb`です。

### `to_param`

Railsのあらゆるオブジェクトは`to_param`メソッドに応答します。これは、オブジェクトを値として表現するものを返すということです。返された値はクエリ文字列やURLの一部で使用できます。

デフォルトでは、`to_param`メソッドは単に`to_s`メソッドを呼び出します。

```ruby
7.to_param # => "7"
```

`to_param`によって返された値を **エスケープしてはいけません** 。

```ruby
"<NAME>".to_param # => "<NAME>"
```

このメソッドは、Railsの多くのクラスで上書きされています。

たとえば、`nil`、`true`、`false`の場合は自分自身を返します。`Array#to_param`を実行すると、`to_param`が配列内の各要素に対して実行され、結果が"/"でjoinされます。

```ruby
[0, true, String].to_param # => "0/true/String"
```

特に、Railsのルーティングシステムはモデルに対して`to_param`メソッドを実行することで、`:id`プレースホルダの値を取得しています。`ActiveRecord::Base#to_param`はモデルの`id`を返しますが、このメソッドをモデル内で再定義することもできます。たとえば

```ruby
class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
```

以下の結果を得ます。

```ruby
user_path(@user) # => "/users/357-john-smith"
```

WARNING: コントローラ側では、`to_param`メソッドがモデル側で再定義されている可能性があることに常に注意しておく必要があります。上のようなリクエストを受信した場合、`params[:id]`の値が"357-john-smith"になるからです。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/to_param.rb`です。

### `to_query`

このメソッドは、エスケープされていない`key`を受け取ると、そのキーを`to_param`が返す値に対応させるクエリ文字列の一部を生成します。ただしハッシュは例外です(後述)。たとえば以下の場合、

```ruby
class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
```

以下の結果を得ます。

```ruby
current_user.to_query('user') # => "user=357-john-smith"
```

このメソッドは、キーと値のいずれについても、必要な箇所をすべてエスケープします。

```ruby
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"
```

従って、この結果はそのままクエリ文字列として使用できます。

配列に`to_query`メソッドを適用した場合、`to_query`を配列の各要素に適用して`key[]`をキーとして追加し、それらを"&"で連結したものを返します。

```ruby
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
```

ハッシュも`to_query`に応答しますが、異なるシグネチャを使用します。メソッドに引数が渡されない場合、このメソッド呼び出しは、一連のキー/値ペアをソート済みの形で生成し、それぞれの値に対して`to_query(key)`を呼び出します。続いて結果を"&"で連結します。

```ruby
{c: 3, b: 2, a: 1}.to_query # => "a=1&b=2&c=3"
```

`Hash#to_query`メソッドは、それらのキーに対して名前空間をオプションで与えることもできます。

```ruby
{id: 89, name: "<NAME>"}.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/to_query.rb`です。

### `with_options`

`with_options`メソッドは、連続した複数のメソッド呼び出しに対して共通して与えられるオプションを解釈するための手段を提供します。

デフォルトのオプションがハッシュで与えられると、`with_options`はブロックに対するプロキシオブジェクトを生成します。そのブロック内では、プロキシに対して呼び出されたメソッドにオプションを追加したうえで、そのメソッドをレシーバに転送します。たとえば、以下のように同じオプションを繰り返さないで済むようになります。

```ruby
class Account < ApplicationRecord
  has_many :customers, dependent: :destroy
  has_many :products,  dependent: :destroy
  has_many :invoices,  dependent: :destroy
  has_many :expenses,  dependent: :destroy
end
```

上は以下のようにできます。

```ruby
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
```

この手法を使用することで、たとえばニュースレターの読者を言語ごとに _グループ化_ することができます。読者が話す言語に応じて異なるニュースレターを送信したいとします。メール送信用のコードのどこかで、以下のような感じでロケール依存ビットをグループ化することができます。

```ruby
I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
  subject i18n.t :subject
  body    i18n.t :body, user_name: user.name
end
```

TIP: `with_options`はメソッドをレシーバに転送しているので、呼び出しをネストすることもできます。各ネスティングレベルでは、自身の呼び出しに、継承したデフォルト呼び出しをマージします。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/with_options.rb`です。

### JSON support

Active Supportが提供する`to_json`メソッドの実装は、通常`json` gemがRubyオブジェクトに対して提供している`to_json`よりも優れています。その理由は、`Hash`や`OrderedHash`、`Process::Status`などのクラスでは、正しいJSON表現を提供するために特別な処理が必要になるためです。

NOTE: 定義ファイルの場所は`active_support/core_ext/object/json.rb`です。

### インスタンス変数

Active Supportは、インスタンス変数に簡単にアクセスするためのメソッドを多数提供しています。

#### `instance_values`

`instance_values`メソッドはハッシュを返します。インスタンス変数名から"@"を除いたものがハッシュのキーに、インスタンス変数の値がハッシュの値にマップされます。キーは文字列です。

```ruby
class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/instance_variables.rb`です。

#### `instance_variable_names`

`instance_variable_names`メソッドは配列を返します。配列のインスタンス名には"@"記号が含まれます。

```ruby
class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_variable_names # => ["@x", "@y"]
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/instance_variables.rb`です。

### 警告・例外の抑制

`silence_warnings`メソッドと`enable_warnings`メソッドは、ブロックが継続する間`$VERBOSE`の値を変更し、その後リセットします。

```ruby
silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
```

`suppress`メソッドを使用すると例外の発生を止めることもできます。このメソッドは、例外クラスを表す任意の数値を受け取ります。`suppress`は、あるブロックの実行時に例外が発生し、その例外が(`kind_of?`による判定で)いずれかの引数に一致する場合、それをキャプチャして例外を発生せずに戻ります。一致しない場合、例外はキャプチャされません。

```ruby
# ユーザーがロックされていればインクリメントは失われるが、重要ではない
suppress(ActiveRecord::StaleObjectError) do
  current_user.increment! :visits
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/kernel/reporting.rb`です。

### `in?`

述語`in?`は、あるオブジェクトが他のオブジェクトに含まれているかどうかをテストします。渡された引数が`include?`に応答しない場合は`ArgumentError`例外が発生します。

`in?`の例を示します。

```ruby
1.in?([1,2])        # => true
"lo".in?("hello")   # => true
25.in?(30..50)      # => false
1.in?(1)            # => ArgumentError
```

NOTE: 定義ファイルの場所は`active_support/core_ext/object/inclusion.rb`です。

`Module`の拡張
----------------------

### 属性

#### `alias_attribute`

モデルの属性には、リーダー (reader)、ライター (writer)、述語 (predicate) があります。上に対応する3つのメソッドを持つ、モデルの属性の別名 (alias) を一度に作成することができます。他の別名作成メソッドと同様、1つ目の引数には新しい名前、2つ目の引数には元の名前を指定します (変数に代入するときと同じ順序、と覚えておく手もあります)。

```ruby
class User < ApplicationRecord
  # emailカラムを"login"という名前でも参照したい
  # そうすることで認証のコードがわかりやすくなる
  alias_attribute :login, :email
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/aliasing.rb`です。

#### 内部属性

あるクラスで属性を定義すると、後にそのクラスのサブクラスが作成されるときに名前が衝突するリスクが生じます。これはライブラリにおいては特に重要な問題です。

Active Supportでは、`attr_internal_reader`、`attr_internal_writer`、`attr_internal_accessor`というマクロが定義されています。これらのマクロは、Rubyにビルトインされている`attr_*`と同様に振る舞いますが、内部のインスタンス変数の名前が衝突しにくいように配慮される点が異なります。

`attr_internal`マクロは`attr_internal_accessor`と同義です。

```ruby
# ライブラリ
class ThirdPartyLibrary::Crawler
  attr_internal :log_level
end

# クライアントコード
class MyCrawler < ThirdPartyLibrary::Crawler
  attr_accessor :log_level
end
```

先の例では、`:log_level`はライブラリのパブリックインターフェイスに属さず、開発用途にのみ使用されます。クライアント側のコードでは衝突の可能性について考慮せずに独自に`:log_level`をサブクラスで定義しています。ライブラリ側で`attr_internal`を使用しているおかげで衝突が生じずに済んでいます。

このとき、内部インスタンス変数の名前にはデフォルトで冒頭にアンダースコアが追加されます。上の例であれば`@_log_level`となります。この動作は`Module.attr_internal_naming_format`を使用して変更することもできます。`sprintf`と同様のフォーマット文字列を与え、冒頭に`@`を置き、それ以外の名前を置きたい場所に`%s`を置きます。デフォルト値は`"@_%s"`です。

Railsではこの内部属性を他の場所でも若干使用しています。たとえばビューでは以下のように使用しています。

```ruby
module ActionView
  class Base
    attr_internal :captures
    attr_internal :request, :layout
    attr_internal :controller, :template
  end
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attr_internal.rb`です。

#### モジュール属性

`mattr_reader`、`mattr_writer`、`mattr_accessor`という3つのマクロは、クラス用に定義される`cattr_*`マクロと同じです。実際、`cattr_*`マクロは単なる`mattr_*`マクロの別名です。[クラス属性](#class属性)も参照してください。

たとえば、これらのマクロは以下のDependenciesモジュールで使用されています。

```ruby
module ActiveSupport
  module Dependencies
    mattr_accessor :warnings_on_first_load
    mattr_accessor :history
    mattr_accessor :loaded
    mattr_accessor :mechanism
    mattr_accessor :load_paths
    mattr_accessor :load_once_paths
    mattr_accessor :autoloaded_constants
    mattr_accessor :explicitly_unloadable_constants
    mattr_accessor :constant_watch_stack
    mattr_accessor :constant_watch_stack_mutex
  end
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attribute_accessors.rb`です。

### 親

#### `parent`

`parent`メソッドは、名前がネストしたモジュールに対して実行でき、対応する定数を持つモジュールを返します。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parent # => X::Y
M.parent       # => X::Y
```

モジュールが無名またはトップレベルの場合、`parent`は`Object`を返します。

WARNING: `parent_name`は上の場合でも`nil`を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`です。

#### `parent_name`

`parent_name`メソッドは、名前がネストしたモジュールに対して実行でき、対応する定数を持つモジュールを返します。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parent_name # => "X::Y"
M.parent_name       # => "X::Y"
```

モジュールが無名またはトップレベルの場合、`parent_name`は`nil`を返します。

WARNING: `parent`は上の場合でも`Object`を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`。

#### `parents`

`parents`メソッドは、レシーバに対して`parent`を呼び出し、`Object`に到着するまでパスをさかのぼります。連鎖したモジュールは、階層の下から上の順に配列として返されます。

```ruby
module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.parents # => [X::Y, X, Object]
M.parents       # => [X::Y, X, Object]
```

NOTE: 定義ファイルの場所は`active_support/core_ext/module/introspection.rb`です。

### 無名モジュール

モジュールは名前を持つことも、無名でいることもできます。

```ruby
module M
end
M.name # => "M"

N = Module.new
N.name # => "N"

Module.new.name # => nil
```

述語`anonymous?`を使用して、モジュールに名前があるかどうかをチェックできます。

```ruby
module M
end
M.anonymous? # => false

Module.new.anonymous? # => true
```

到達不能 (unreachable) であっても、必ずしも無名 (anonymous) になるとは限りません。

```ruby
module M
end

m = Object.send(:remove_const, :M)

m.anonymous? # => false
```

逆に無名モジュールは、定義上必ず到達不能になります。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/anonymous.rb`です。

### メソッド委譲

#### `delegate`

`delegate`マクロを使用すると、メソッドを簡単に委譲できます。

あるアプリケーションの`User`モデルにログイン情報があり、それに関連する名前などの情報は`Profile`モデルにあるとします。

```ruby
class User < ApplicationRecord
  has_one :profile
end
```

この構成では、`user.profile.name`のようにプロファイル越しにユーザー名を取得することになります。これらの属性に直接アクセスできたらもっと便利になることでしょう。

```ruby
class User < ApplicationRecord
  has_one :profile

  def name
    profile.name
  end
end
```

`delegate`を使用すればできるようになります。

```ruby
class User < ApplicationRecord
  has_one :profile

  delegate :name, to: :profile
end
```

この方法なら記述が短くて済み、意味もはっきりします。

使用するメソッドは対象クラス内でpublicである必要があります。

`delegate`マクロには複数のメソッドを指定できます。

```ruby
delegate :name, :age, :address, :twitter, to: :profile
```

`:to`オプションが文字列に変換されると、メソッドの委譲先となるオブジェクトに評価される式になります。通常は文字列またはシンボルになります。そのような式は、レシーバのコンテキストで評価されます。

```ruby
# Rails定数を委譲する
delegate :logger, to: :Rails

# レシーバのクラスに委譲する
delegate :table_name, to: :class
```

WARNING: `:prefix`オプションが`true`の場合、一般性が低下します (後述)。

委譲時に`NoMethodError`が発生して対象が`nil`の場合、例外が発生します。`:allow_nil`オプションを使用すると、例外の代りに`nil`を返すようにすることができます。

```ruby
delegate :name, to: :profile, allow_nil: true
```

`:allow_nil`を指定すると、ユーザーのプロファイルがない場合に`user.name`呼び出しは`nil`を返します。

`:prefix`オプションをtrueにすると、生成されたメソッドの名前にプレフィックスを追加します。これは、たとえばよりよい名前にしたい場合に便利です。

```ruby
delegate :street, to: :address, prefix: true
```

上の例では、`street`ではなく`address_street`が生成されます。

WARNING: この場合、生成されるメソッドの名前では、対象となるオブジェクト名とメソッド名が使用されます。`:to`オプションで指定するのはメソッド名でなければなりません。

プレフィックスをカスタマイズすることもできます。

```ruby
delegate :size, to: :attachment, prefix: :avatar
```

上の例では、マクロによって`size`の代わりに`avatar_size`が生成されます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/delegation.rb`です。

#### `delegate_missing_to`

`User`オブジェクトにないものを`Profile`にあるものにすべて委譲したいとしましょう。`delegate_missing_to`マクロを使えばこれを簡単に実装できます。

```ruby
class User < ApplicationRecord
  has_one :profile

  delegate_missing_to :profile
end
```

オブジェクト内にある呼び出し可能なもの（インスタンス変数、メソッド、定数など）なら何でも対象にできます。対象のうち、publicなメソッドだけが委譲されます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/delegation.rb`です。

### メソッドの再定義

`define_method`を使用してメソッドを再定義する必要があるが、その名前が既にあるかどうかがわからないとことがあります。有効な名前が既にあれば警告が表示されます。警告が表示されても大したことはありませんが、邪魔に思えることもあります。

`redefine_method`メソッドを使用すれば、必要に応じて既存のメソッドが削除されるので、このような警告表示を抑制できます。

（`delegate`を使っているなどの理由で）メソッド自身の置き換えを定義する必要がある場合は、`silence_redefinition_of_method`を使うこともできます。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/redefine_method.rb`です。

`Class`の拡張
---------------------

### Class属性

#### `class_attribute`

`class_attribute`メソッドは、1つ以上の継承可能なクラスの属性を宣言します。そのクラス属性は、その下のどの階層でも上書き可能です。

```ruby
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
```

たとえば、`ActionMailer::Base`に以下の定義があるとします。

```ruby
class_attribute :default_params
self.default_params = {
  mime_version: "1.0",
  charset: "UTF-8",
  content_type: "text/plain",
  parts_order: [ "text/plain", "text/enriched", "text/html" ]
}.freeze
```

これらの属性はインスタンスのレベルでアクセスまたはオーバーライドできます。

```ruby
A.x = 1

a1 = A.new
a2 = A.new
a2.x = 2

a1.x # => 1 (Aが使われる)
a2.x # => 2 (a2でオーバーライドされる)
```

`:instance_writer`を`false`に設定すれば、writerインスタンスメソッドは生成されません。

```ruby
module ActiveRecord
  class Base
    class_attribute :table_name_prefix, instance_writer: false, default: "my"
  end
end
```

上のオプションは、モデルの属性設定時にマスアサインメントを防止するのに便利です。

`:instance_reader`を`false`に設定すれば、readerインスタンスメソッドは生成されません。

```ruby
class A
  class_attribute :x, instance_reader: false
end

A.new.x = 1
A.new.x # NoMethodError
```

利便性のために、`class_attribute`は、インスタンスのreaderが返すものを「二重否定」するインスタンス述語も定義されます。上の例の場合、`x?`となります。

`:instance_reader`が`false`の場合、インスタンス述語はreaderメソッドと同様に`NoMethodError`を返します。

インスタンス述語が不要な場合、`instance_predicate: false`を指定すれば定義されなくなります。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/attribute.rb`です。

#### `cattr_reader`、`cattr_writer`、`cattr_accessor`

`cattr_reader`、`cattr_writer`、`cattr_accessor`マクロは、`attr_*`と似ていますが、クラス用である点が異なります。これらのメソッドは、クラス変数を`nil`に設定し (クラス変数が既にある場合を除く)、対応するクラスメソッドを生成してアクセスできるようにします。

```ruby
class MysqlAdapter < AbstractAdapter
  # @@emulate_booleansにアクセスできるクラスメソッドを生成する
  cattr_accessor :emulate_booleans, default: true
end
```

利便性のため、このときインスタンスメソッドも生成されますが、これらは実際にはクラス属性の単なるプロキシです。従って、インスタンスからクラス属性を変更することはできますが、`class_attribute`で行われるように上書きすることはできません(上記参照)。たとえば以下の場合、

```ruby
module ActionView
  class Base
    cattr_accessor :field_error_proc, default: Proc.new { ... }
  end
end
```

ビューで`field_error_proc`にアクセスできます。

同様に、`cattr_*`にブロックを渡して属性にデフォルト値を設定することもできます。

```ruby
class MysqlAdapter < AbstractAdapter
  # @@emulate_booleansにアクセスしてデフォルト値をtrueにするクラスメソッドを生成
  cattr_accessor :emulate_booleans, default: true
end
```

`:instance_reader`オプションを`false`に設定することで、readerインスタンスメソッドが生成されないようにできます。同様に、`:instance_writer`オプションを`false`に設定することで、writerインスタンスメソッドが生成されないようにできます。`:instance_accessor`オプションを`false`に設定すれば、どちらのインスタンスメソッドも生成されません。いずれの場合も、指定できる値は`false`のみです。'nil'など他のfalse値は指定できません。

```ruby
module A
  class B
    # first_nameインスタンスreaderは生成されない
    cattr_accessor :first_name, instance_reader: false
    # last_name= インスタンスwriterは生成されない
    cattr_accessor :last_name, instance_writer: false
    # surnameインスタンスreaderもsurname= インスタンスwriterも生成されない
    cattr_accessor :surname, instance_accessor: false
  end
end
```

`:instance_accessor`を`false`に設定すると、モデルの属性設定時にマスアサインメントを防止するのに便利です。

NOTE: 定義ファイルの場所は`active_support/core_ext/module/attribute_accessors.rb`です。

### サブクラスと子孫

#### `subclasses`

`subclasses`メソッドはレシーバのサブクラスを返します。

```ruby
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]
```

返されるクラスの順序は一定ではありません。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/subclasses.rb`です。

#### `descendants`

`descendants`メソッドは、そのレシーバより下位にあるすべてのクラスを返します。

```ruby
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]
```

返されるクラスの順序は一定ではありません。

NOTE: 定義ファイルの場所は`active_support/core_ext/class/subclasses.rb`です。

`String`の拡張
----------------------

### 安全な出力

#### 開発の動機

HTMLテンプレートにデータを挿入する方法は、きわめて慎重に設計する必要があります。たとえば、`@review.title`を何の工夫もなくそのままHTMLに式展開するようなことは絶対にすべきではありません。もしこのレビューのタイトルが仮に"Flanagan & Matz rules!"だとしたら、出力はwell-formedになりません。well-formedにするには、"&amp;amp;"のようにエスケープしなければなりません。さらに、ユーザーがレビューのタイトルに細工をして、悪意のあるHTMLをタイトルに含めれば、巨大なセキュリティホールになることすらあります。このリスクの詳細については、[セキュリティガイド](security.html#クロスサイトスクリプティング-xss)のクロスサイトスクリプティングの節を参照してください。

#### 安全な文字列

Active Supportには「(html的に) 安全な文字列」という概念があります。安全な文字列とは、HTMLにそのまま挿入しても問題がないというマークが付けられている文字列です。マーキングさえされていれば、「実際にエスケープされているかどうかにかかわらず」その文字列は信頼されます。

文字列はデフォルトでは _unsafe_ とマークされます。

```ruby
"".html_safe? # => false
```

与えられた文字列に`html_safe`メソッドを適用することで、安全な文字列を得ることができます。

```ruby
s = "".html_safe
s.html_safe? # => true
```

ここで注意しなければならないのは、`html_safe`メソッドそれ自体は何らエスケープを行なっていないということです。安全であるとマーキングしているに過ぎません。

```ruby
s = "<script>...</script>".html_safe
s.html_safe? # => true
s            # => "<script>...</script>"
```

従って、特定の文字列に対して`html_safe`メソッドを呼び出す際には、その文字列が本当に安全であることを確認する義務があります。

安全であると宣言された文字列に対し、安全でない文字列を`concat`/`<<`または`+`を使用して破壊的に追加すると、結果は安全な文字列になります。安全でない引数は追加時にエスケープされます。

```ruby
"".html_safe + "<" # => "&lt;"
```

安全な引数であれば、(エスケープなしで)直接追加されます。

```ruby
"".html_safe + "<".html_safe # => "<"
```

基本的にこれらのメソッドは、通常のビューでは使用しないでください。現在のRailsのビューでは、安全でない値は自動的にエスケープされるためです。

```erb
<%= @review.title %> <%# 必要に応じてエスケープされるので問題なし %>
```

何らかの理由で、エスケープされていない文字列を挿入したい場合は、`html_safe`を呼ぶのではなく、`raw`ヘルパーを使用するようにしてください。

```erb
<%= raw @cms.current_template %> <%# @cms.current_templateをそのまま挿入 %>
```

あるいは、`raw`と同等の`<%==`を使用します。

```erb
<%== @cms.current_template %> <%# @cms.current_templateをそのまま挿入 %>
```

`raw`ヘルパーは、内部で`html_safe`を呼び出します。

```ruby
def raw(stringish)
  stringish.to_s.html_safe
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/output_safety.rb`です。

#### 各種変換

経験上、上で説明したような連結 (concatenation) 操作を除き、どんなメソッドでも潜在的には文字列を安全でないものに変換してしまう可能性があることに常に注意を払う必要があります。そのようなメソッドには`downcase`、`gsub`、`strip`、`chomp`、`underscore`などがあります。

`gsub!`のような破壊的な変換を行なうメソッドを使用すると、レシーバ自体が安全でなくなります。

INFO: こうしたメソッドを実行すると、実際に変換が行われたかどうかにかかわらず、安全を表すビットは常にオフになります。

#### 変換と強制

安全な文字列に対して`to_s`を実行した場合は、安全な文字列が返されます。しかし、`to_str`による強制的な変換を実行した場合には安全でない文字列が返されます。

#### コピー

安全な文字列に対して`dup`または`clone`を実行した場合は、安全な文字列が生成されます。

### `remove`

`remove`メソッドを実行すると、すべての該当パターンが削除されます。

```ruby
"Hello World".remove(/Hello /) # => "World"
```

このメソッドには破壊的なバージョンの`String#remove!`もあります。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `squish`

`squish`メソッドは、冒頭と末尾のホワイトスペースを除去し、連続したホワイトスペースを1つに減らします。

```ruby
" \n  foo\n\r \t bar \n".squish # => "foo bar"
```

このメソッドには破壊的なバージョンの`String#squish!`もあります。

このメソッドでは、ASCIIとUnicodeのホワイトスペースを扱えます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `truncate`

`truncate`メソッドは、指定された`length`にまで長さを切り詰めたレシーバのコピーを返します。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."
```

`:omission`オプションを指定することで、省略文字 (…) をカスタマイズすることもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20, omission: '&hellip;')
# => "Oh dear! Oh &hellip;"
```

文字列の切り詰めでは、省略文字列の長さも加味されることに特にご注意ください。

`:separator`を指定することで、自然な区切り位置で切り詰めることができます。

```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..."
```

`:separator`オプションで正規表現を使用することもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."
```

上の例では、"dear"という文字で切り落とされそうになるところを、`:separator`によって防いでいます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `truncate_words`

`truncate_words`メソッドは、指定されたワード数から後ろをきりおとしたレシーバのコピーを返します。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4)
# => "Oh dear! Oh dear!..."
```

`:omission`オプションを指定することで、省略文字 (…) をカスタマイズすることもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4, omission: '&hellip;')
# => "Oh dear! Oh dear!&hellip;"
```

`:separator`を指定することで、自然な区切り位置で切り詰めることができます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(3, separator: '!')
# => "Oh dear! Oh dear! I shall be late..."
```

`:separator`オプションで正規表現を使用することもできます。

```ruby
"Oh dear! Oh dear! I shall be late!".truncate_words(4, separator: /\s/)
# => "Oh dear! Oh dear!..."
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/filters.rb`です。

### `inquiry`

`inquiry`は、文字列を`StringInquirer`オブジェクトに変換します。このオブジェクトを使用すると、等しいかどうかをよりスマートにチェックできます。

```ruby
"production".inquiry.production? # => true
"active".inquiry.inactive?       # => false
```

### `starts_with?`と`ends_with?`

Active Supportでは、`String#start_with?`と`String#end_with?`を英語的に自然な三人称(starts、ends)にした別名も定義してあります。

```ruby
"foo".starts_with?("f") # => true
"foo".ends_with?("o")   # => true
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/starts_ends_with.rb`です。

### `strip_heredoc`

`strip_heredoc`メソッドは、ヒアドキュメントのインデントを除去します。

以下に例を示します。

```ruby
if options[:usage]
  puts <<-USAGE.strip_heredoc
    This command does such and such.

    Supported options are:
      -h         This message
      ...
  USAGE
end
```

このUSAGEメッセージは左寄せで表示されます。

技術的には、インデントが一番浅い行を探して、そのインデント分だけ行頭のホワイトスペースを全体から削除するという操作を行っています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/strip.rb`です。

### `indent`

このメソッドは、レシーバの行にインデントを与えます。

```ruby
<<EOS.indent(2)
def some_method
  some_code
end
EOS
# =>
  def some_method
    some_code
  end
```

2つめの引数`indent_string`は、インデントに使用する文字列を指定します。デフォルトは`nil`であり、この場合最初にインデントされている行のインデント文字を参照してそこからインデント文字を推測します。インデントがまったくない場合はスペース1つを使用します。

```ruby
"  foo".indent(2)        # => "    foo"
"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
"foo".indent(2, "\t")    # => "\t\tfoo"
```

`indent_string`には1文字のスペースまたはタブを使用するのが普通ですが、どんな文字でも使用できます。

3つ目の引数`indent_empty_lines`は、空行もインデントするかどうかを指定するフラグです。デフォルトはfalseです。

```ruby
"foo\n\nbar".indent(2)            # => "  foo\n\n  bar"
"foo\n\nbar".indent(2, nil, true) # => "  foo\n  \n  bar"
```

`indent!`メソッドはインデントをその場で (破壊的に) 行います。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/indent.rb`です。

### Access

#### `at(position)`

対象となる文字列のうち、`position`で指定された位置にある文字を返します。

```ruby
"hello".at(0)  # => "h"
"hello".at(4)  # => "o"
"hello".at(-1) # => "o"
"hello".at(10) # => nil
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `from(position)`

文字列のうち、`position`で指定された位置から始まる部分文字列を返します。

```ruby
"hello".from(0)  # => "hello"
"hello".from(2)  # => "llo"
"hello".from(-2) # => "lo"
"hello".from(10) # => nil
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `to(position)`

文字列のうち、`position`で指定された位置を終端とする部分文字列を返します。

```ruby
"hello".to(0)  # => "h"
"hello".to(2)  # => "hel"
"hello".to(-2) # => "hell"
"hello".to(10) # => "hello"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `first(limit = 1)`

`str.first(n)`という呼び出しは、`n` > 0 のとき`str.to(n-1)`と等価です。`n` == 0の場合は空文字列を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

#### `last(limit = 1)`

`str.last(n)` という呼び出しは、`n` > 0 のとき`str.from(-n)`と等価です。`n` == 0 の場合は空文字列を返します。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/access.rb`です。

### 活用形

#### `pluralize`

`pluralize`メソッドは、レシーバを「複数形」にしたものを返します。

```ruby
"table".pluralize     # => "tables"
"ruby".pluralize      # => "rubies"
"equipment".pluralize # => "equipment"
```

上の例でも示したように、Active Supportは不規則な複数形や非可算名詞についてある程度知っています。`config/initializers/inflections.rb`にあるビルトインのルールは拡張可能です。このファイルは`rails`コマンドで拡張可能であり、方法はコメントに示されています。

`pluralize`メソッドではオプションで`count`パラメータを使用できます。もし`count == 1`を指定すると単数形が返されます。`count`がそれ以外の値の場合は複数形を返します(訳注: 英語では個数がゼロや小数の場合は複数形で表されます)。

```ruby
"dude".pluralize(0) # => "dudes"
"dude".pluralize(1) # => "dude"
"dude".pluralize(2) # => "dudes"
```

Active Recordでは、モデル名に対応するデフォルトのテーブル名を求めるときにこのメソッドを使用しています。

```ruby
# active_record/model_schema.rb
def undecorated_table_name(class_name = base_class.name)
  table_name = class_name.to_s.demodulize.underscore
  pluralize_table_names ? table_name.pluralize : table_name
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `singularize`

`pluralize`と逆の動作です。

```ruby
"tables".singularize    # => "table"
"rubies".singularize    # => "ruby"
"equipment".singularize # => "equipment"
```

Railsの関連付け (association) では、関連付けられたクラスにデフォルトで対応する名前を求める時にこのメソッドが使用されます。

```ruby
# 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: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `camelize`

`camelize`メソッドは、レシーバをキャメルケース (冒頭を大文字にした単語をスペースなしで連結した語) にしたものを返します。

```ruby
"product".camelize    # => "Product"
"admin_user".camelize # => "AdminUser"
```

このメソッドは、パスをRubyのクラスに変換するときにもよく使用されます。スラッシュで区切られているパスは「::」で区切られます。

```ruby
"backoffice/session".camelize # => "Backoffice::Session"
```

たとえばAction Packでは、特定のセッションストアを提供するクラスを読み込むのにこのメソッドを使用しています。

```ruby
# 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`メソッドはオプションの引数を受け付けます。使用できるのは`:upper` (デフォルト) または`:lower`です。後者を指定すると、冒頭が小文字になります。

```ruby
"visual_effect".camelize(:lower) # => "visualEffect"
```

このメソッドは、そのような命名慣習に従っている言語 (JavaScriptなど) で使用される名前を求めるのに便利です。

INFO: `camerize`メソッドの動作は、`underscore`メソッドと逆の動作と考えるとわかりやすいでしょう。ただし完全に逆の動作ではありません。たとえば、`"SSLError".underscore.camelize`を実行した結果は`"SslError"`になり、元に戻りません。このような場合をサポートするために、Active Supportでは`config/initializers/inflections.rb`の頭字語を指定することができます。

```ruby
ActiveSupport::Inflector.inflections do |inflect|
  inflect.acronym 'SSL'
end

"SSLError".underscore.camelize # => "SSLError"
```

`camelize`は`camelcase`の別名です。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `underscore`

`underscore`メソッドは上と逆に、キャメルケースをパスに変換します。

```ruby
"Product".underscore   # => "product"
"AdminUser".underscore # => "admin_user"
```

"::"も"/"に逆変換されます。

```ruby
"Backoffice::Session".underscore # => "backoffice/session"
```

小文字で始まる文字列も扱えます。

```ruby
"visualEffect".underscore # => "visual_effect"
```

ただし`underscore`は引数を取りません。

Railsで自動的に読み込まれるクラスとモジュールは、`underscore`メソッドを使用してファイルの拡張子を除いた相対パスを推測し、指定された定数が失われている場合にそれを定義するのに役立てます。

```ruby
# active_support/dependencies.rb
def load_missing_constant(from_mod, const_name)
  ...
  qualified_name = qualified_name_for from_mod, const_name
  path_suffix = qualified_name.underscore
  ...
end
```

INFO: `underscore`メソッドの動作は、`camelize`メソッドと逆の動作と考えるとわかりやすいでしょう。ただし完全に逆の動作ではありません。たとえば、`"SSLError".underscore.camelize`を実行した結果は`"SslError"`になり、元に戻りません。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `titleize`

`titleize`メソッドは、レシーバの語の1文字目を大文字にします。

```ruby
"alice in wonderland".titleize # => "Alice In Wonderland"
"fermat's enigma".titleize     # => "Fermat's Enigma"
```

`titleize`メソッドは`titlecase`の別名です。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `dasherize`

`dasherize`メソッドは、レシーバのアンダースコア文字をダッシュに置き換えます(訳注: ここで言うダッシュは実際には「ハイフンマイナス文字」(U+002D)です)。

```ruby
"name".dasherize         # => "name"
"contact_data".dasherize # => "contact-data"
```

モデルのXMLシリアライザではこのメソッドを使用してノード名をダッシュ化しています。

```ruby
# active_model/serializers/xml.rb
def reformat_name(name)
  name = name.camelize if camelize?
  dasherize? ? name.dasherize : name
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `demodulize`

`demodulize`メソッドは、フルパスの (qualified) 定数名を与えられると、パス部分を取り除いて右側の定数名だけにしたものを返します。

```ruby
"Product".demodulize                        # => "Product"
"Backoffice::UsersController".demodulize    # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
"::Inflections".demodulize                  # => "Inflections"
"".demodulize                               # => ""

```

以下のActive Recordの例では、このメソッドを使用してcounter_cacheカラムの名前を求めています。

```ruby
# 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
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `deconstantize`

`deconstantize`メソッドは、フルパスの定数を表す参照表現を与えられると、一番右の部分 (通常は定数名) を取り除きます。

```ruby
"Product".deconstantize                        # => ""
"Backoffice::UsersController".deconstantize    # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `parameterize`

`parameterize`メソッドは、レシーバを正しいURLで使用可能な形式に正規化します。

```ruby
"<NAME>".parameterize # => "john-smith"
"<NAME>".parameterize # => "kurt-godel"
```

文字列の大文字小文字が変わらないようにするには、`preserve_case`引数に`true`を指定します。`preserve_case`はデフォルトでは`false`になります。

```ruby
"<NAME>".parameterize(preserve_case: true) # => "John-Smith"
"<NAME>".parameterize(preserve_case: true) # => "Kurt-Godel"
```

独自のセパレータを使うには、`separator`引数をオーバーライドします。

```ruby
"<NAME>".parameterize(separator: "_") # => "john\_smith"
"<NAME>".parameterize(separator: "_") # => "kurt\_godel"
```

実際に得られる文字列は、`ActiveSupport::Multibyte::Chars`のインスタンスでラップされています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `tableize`

`tableize`メソッドは、`underscore`の次に`pluralize`を実行したものです。

```ruby
"Person".tableize      # => "people"
"Invoice".tableize     # => "invoices"
"InvoiceLine".tableize # => "invoice_lines"
```

単純な場合であれば、モデル名に`tableize`を使用するとモデルのテーブル名を得られます。実際のActive Recordの実装は、単に`tableize`を実行する場合よりも複雑です。Active Recordではクラス名に対して`demodulize`も行っており、返される文字列に影響する可能性のあるオプションもいくつかチェックしています。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `classify`

`classify`メソッドは、`tableize`と逆の動作です。与えられたテーブル名に対応するクラス名を返します。

```ruby
"people".classify        # => "Person"
"invoices".classify      # => "Invoice"
"invoice_lines".classify # => "InvoiceLine"
```

このメソッドは、フルパスの (qualified) テーブル名も扱えます。

```ruby
"highrise_production.companies".classify # => "Company"
```

`classify`が返すクラス名は文字列であることにご注意ください。得られた文字列に対して`constantize` (後述) を実行することで本当のクラスオブジェクトを得られます。

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `constantize`

`constantize`メソッドは、レシーバの定数参照表現を解決し、実際のオブジェクトを返します。

```ruby
"Fixnum".constantize # => Fixnum

module M
  X = 1
end
"M::X".constantize # => 1
```

与えられた文字列を`constantize`メソッドで評価しても既知の定数とマッチしない、または指定された定数名が正しくない場合は`NameError`が発生します。

`constantize`メソッドによる定数名解決は、常にトップレベルの`Object`から開始されます。これは上位に"::"がない場合でも同じです。

```ruby
X = :in_Object
module M
  X = :in_M

  X                 # => :in_M
  "::X".constantize # => :in_Object
  "X".constantize   # => :in_Object (!)
end
```

従って、このメソッドは、同じ場所でRubyが定数を評価したときの値と必ずしも等価ではありません。

メイラー (mailer) のテストケースでは、テストするクラスの名前からテスト対象のメイラーを取得するのに`constantize`メソッドを使用します。

```ruby
# action_mailer/test_case.rb
def determine_default_mailer(name)
  name.sub(/Test$/, '').constantize
rescue NameError => e
  raise NonInferrableMailerError.new(name)
end
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `humanize`

`humanize`メソッドは、属性名を (英語的に) 読みやすい表記に変換します。

具体的には以下の変換を行います。

  * 引数に (英語の) 活用ルールを適用します(inflection)。
  * 冒頭にアンダースコアがある場合は削除します。
  * 末尾に"_id"がある場合は削除します。
  * アンダースコアが他にもある場合はスペースに置き換えます。
  * 略語を除いてすべての単語を小文字にします(downcase)。
  * 最初の単語だけ冒頭の文字を大文字にします(capitalize)。

`:capitalize`オプションをfalseにすると、冒頭の文字は大文字にされません(デフォルトはtrue)。

```ruby
"name".humanize                         # => "Name"
"author_id".humanize                    # => "Author"
"author_id".humanize(capitalize: false) # => "author"
"comments_count".humanize               # => "Comments count"
"_id".humanize                          # => "Id"
```

"SSL"が頭字語と定義されている場合は以下のようになります。

```ruby
'ssl_error'.humanize # => "SSL error"
```

ヘルパーメソッド`full_messages`では、属性名をメッセージに含めるときに`humanize`を使用しています。


```ruby
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
```

NOTE: 定義ファイルの場所は`active_support/core_ext/string/inflections.rb`です。

#### `foreign_key`

{'fraction_non_alphanumeric': 0.15291758165039793, 'fraction_numerical': 0.004569629733057463, 'mean_word_length': 6.787091034891766, 'pattern_counts': {'":': 8, '<': 96, '<?xml version=': 0, '>': 382, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6339495', 'n_tokens_mistral': 49041, 'n_tokens_neox': 45343, 'n_words': 3760}