class Array - activesupport-4.2.3 Documentation

# class Array

### Public Class Methods

wrap(object) click to toggle source

Wraps its argument in an array unless it is already an array (or array-like).

Specifically:

- If the argument is `nil` an empty list is returned.

- Otherwise, if the argument responds to `to_ary` it is invoked, and its result returned.

- Otherwise, returns an array with the argument as its single element.

      Array.wrap(nil)       # => []
      Array.wrap([1, 2, 3]) # => [1, 2, 3]
      Array.wrap(0)         # => [0]

This method is similar in purpose to `Kernel#Array`, but there are some differences:

- If the argument responds to `to_ary` the method is invoked. `Kernel#Array` moves on to try `to_a` if the returned value is `nil`, but `Array.wrap` returns `nil` right away.

- If the returned value from `to_ary` is neither `nil` nor an `Array` object, `Kernel#Array` raises an exception, while `Array.wrap` does not, it just returns the value.

- It does not call `to_a` on the argument, but returns an empty array if argument is `nil`.

The second point is easily explained with some enumerables:

    Array(foo: :bar)      # => [[:foo, :bar]]
    Array.wrap(foo: :bar) # => [{:foo=>:bar}]

There's also a related idiom that uses the splat operator:

    [*object]

which returns `[]` for `nil`, but calls to `Array(object)` otherwise.

The differences with `Kernel#Array` explained above apply to the rest of `object`s.

    # File lib/active_support/core_ext/array/wrap.rb, line 36
    def self.wrap(object)
      if object.nil?
        []
      elsif object.respond_to?(:to_ary)
        object.to_ary || [object]
      else
        [object]
      end
    end

### Public Instance Methods

deep_dup() click to toggle source

Returns a deep copy of array.

    array = [1, [2, 3]]
    dup   = array.deep_dup
    dup[1][2] = 4

    array[1][2] # => nil
    dup[1][2]   # => 4

    # File lib/active_support/core_ext/object/deep_dup.rb, line 27
    def deep_dup
      map { |it| it.deep_dup }
    end

extract_options!() click to toggle source

Extracts options from a set of arguments. Removes and returns the last element in the array if it's a hash, otherwise returns a blank hash.

    def options(*args)
      args.extract_options!
    end

    options(1, 2)        # => {}
    options(1, 2, a: :b) # => {:a=>:b}

    # File lib/active_support/core_ext/array/extract_options.rb, line 22
    def extract_options!
      if last.is_a?(Hash) && last.extractable_options?
        pop
      else
        {}
      end
    end

fifth() click to toggle source

Equal to `self[4]`.

    %w( a b c d e ).fifth # => "e"

    # File lib/active_support/core_ext/array/access.rb, line 54
    def fifth
      self[4]
    end

forty_two() click to toggle source

Equal to `self[41]`. Also known as accessing “the reddit”.

    (1..42).to_a.forty_two # => 42

    # File lib/active_support/core_ext/array/access.rb, line 61
    def forty_two
      self[41]
    end

fourth() click to toggle source

Equal to `self[3]`.

    %w( a b c d e ).fourth # => "d"

    # File lib/active_support/core_ext/array/access.rb, line 47
    def fourth
      self[3]
    end

from(position) click to toggle source

Returns the tail of the array from `position`.

    %w( a b c d ).from(0)  # => ["a", "b", "c", "d"]
    %w( a b c d ).from(2)  # => ["c", "d"]
    %w( a b c d ).from(10) # => []
    %w().from(0)           # => []
    %w( a b c d ).from(-2) # => ["c", "d"]
    %w( a b c ).from(-10)  # => []

    # File lib/active_support/core_ext/array/access.rb, line 10
    def from(position)
      self[position, length] || []
    end

in_groups(number, fill_with = nil) { |g| ... } click to toggle source

Splits or iterates over the array in `number` of groups, padding any remaining slots with `fill_with` unless it is `false`.

    %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
    ["1", "2", "3", "4"]
    ["5", "6", "7", nil]
    ["8", "9", "10", nil]

    %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, '&nbsp;') {|group| p group}
    ["1", "2", "3", "4"]
    ["5", "6", "7", "&nbsp;"]
    ["8", "9", "10", "&nbsp;"]

    %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
    ["1", "2", "3"]
    ["4", "5"]
    ["6", "7"]

    # File lib/active_support/core_ext/array/grouping.rb, line 60
    def in_groups(number, fill_with = nil)
      # size.div number gives minor group size;
      # size % number gives how many objects need extra accommodation;
      # each group hold either division or division + 1 items.
      division = size.div number
      modulo = size % number

      # create a new array avoiding dup
      groups = []
      start = 0

      number.times do |index|
        length = division + (modulo > 0 && modulo > index ? 1 : 0)
        groups << last_group = slice(start, length)
        last_group << fill_with if fill_with != false &&
          modulo > 0 && length == division
        start += length
      end

      if block_given?
        groups.each { |g| yield(g) }
      else
        groups
      end
    end

in_groups_of(number, fill_with = nil) { |slice| ... } click to toggle source

Splits or iterates over the array in groups of size `number`, padding any remaining slots with `fill_with` unless it is `false`.

    %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
    ["1", "2", "3"]
    ["4", "5", "6"]
    ["7", "8", "9"]
    ["10", nil, nil]

    %w(1 2 3 4 5).in_groups_of(2, '&nbsp;') {|group| p group}
    ["1", "2"]
    ["3", "4"]
    ["5", "&nbsp;"]

    %w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
    ["1", "2"]
    ["3", "4"]
    ["5"]

    # File lib/active_support/core_ext/array/grouping.rb, line 20
    def in_groups_of(number, fill_with = nil)
      if number.to_i <= 0
        raise ArgumentError,
          "Group size must be a positive integer, was #{number.inspect}"
      end

      if fill_with == false
        collection = self
      else
        # size % number gives how many extra we have;
        # subtracting from number gives how many to add;
        # modulo number ensures we don't add group of just fill.
        padding = (number - size % number) % number
        collection = dup.concat(Array.new(padding, fill_with))
      end

      if block_given?
        collection.each_slice(number) { |slice| yield(slice) }
      else
        collection.each_slice(number).to_a
      end
    end

second() click to toggle source

Equal to `self[1]`.

    %w( a b c d e ).second # => "b"

    # File lib/active_support/core_ext/array/access.rb, line 33
    def second
      self[1]
    end

split(value = nil) { |element| ... } click to toggle source

Divides the array into one or more subarrays based on a delimiting `value` or the result of an optional block.

    [1, 2, 3, 4, 5].split(3)              # => [[1, 2], [4, 5]]
    (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]

    # File lib/active_support/core_ext/array/grouping.rb, line 91
    def split(value = nil)
      if block_given?
        inject([[]]) do |results, element|
          if yield(element)
            results << []
          else
            results.last << element
          end

          results
        end
      else
        results, arr = [[]], self.dup
        until arr.empty?
          if (idx = arr.index(value))
            results.last.concat(arr.shift(idx))
            arr.shift
            results << []
          else
            results.last.concat(arr.shift(arr.size))
          end
        end
        results
      end
    end

third() click to toggle source

Equal to `self[2]`.

    %w( a b c d e ).third # => "c"

    # File lib/active_support/core_ext/array/access.rb, line 40
    def third
      self[2]
    end

to(position) click to toggle source

Returns the beginning of the array up to `position`.

    %w( a b c d ).to(0)  # => ["a"]
    %w( a b c d ).to(2)  # => ["a", "b", "c"]
    %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
    %w().to(0)           # => []
    %w( a b c d ).to(-2) # => ["a", "b", "c"]
    %w( a b c ).to(-10)  # => []

    # File lib/active_support/core_ext/array/access.rb, line 22
    def to(position)
      if position >= 0
        first position + 1
      else
        self[0..position]
      end
    end

to_default_s(format = :default)
Alias for: to_s
to_formatted_s(format = :default) click to toggle source

Extends `Array#to_s` to convert a collection of elements into a comma separated id list if `:db` argument is given as the format.

    Blog.all.to_formatted_s(:db) # => "1,2,3"

    # File lib/active_support/core_ext/array/conversions.rb, line 89
    def to_formatted_s(format = :default)
      case format
      when :db
        if empty?
          'null'
        else
          collect { |element| element.id }.join(',')
        end
      else
        to_default_s
      end
    end

Also aliased as: to_s
to_param() click to toggle source

Calls `to_param` on all its elements and joins the result with slashes. This is used by `url_for` in Action Pack.

    # File lib/active_support/core_ext/object/to_query.rb, line 40
    def to_param
      collect { |e| e.to_param }.join '/'
    end

to_query(key) click to toggle source

Converts an array into a string suitable for use as a URL query string, using the given `key` as the param name.

    ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"

    # File lib/active_support/core_ext/object/to_query.rb, line 48
    def to_query(key)
      prefix = "#{key}[]"

      if empty?
        nil.to_query(prefix)
      else
        collect { |value| value.to_query(prefix) }.join '&'
      end
    end

to_s(format = :default)
Also aliased as: to_default_s
Alias for: to_formatted_s
to_sentence(options = {}) click to toggle source

Converts the array to a comma-separated sentence where the last element is joined by the connector word.

You can pass the following options to change the default behavior. If you pass an option key that doesn't exist in the list below, it will raise an `ArgumentError`.

#### Options¶ ↑

- `:words_connector` - The sign or word used to join the elements in arrays with two or more elements (default: “, ”).

- `:two_words_connector` - The sign or word used to join the elements in arrays with two elements (default: “ and ”).

- `:last_word_connector` - The sign or word used to join the last element in arrays with three or more elements (default: “, and ”).

- `:locale` - If `i18n` is available, you can set a locale and use the connector options defined on the 'support.array' namespace in the corresponding dictionary file.

#### Examples¶ ↑

    [].to_sentence                      # => ""
    ['one'].to_sentence                 # => "one"
    ['one', 'two'].to_sentence          # => "one and two"
    ['one', 'two', 'three'].to_sentence # => "one, two, and three"

    ['one', 'two'].to_sentence(passing: 'invalid option')
    # => ArgumentError: Unknown key :passing

    ['one', 'two'].to_sentence(two_words_connector: '-')
    # => "one-two"

    ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
    # => "one or two or at least three"

Using `:locale` option:

    # Given this locale dictionary:
    #
    #   es:
    #     support:
    #       array:
    #         words_connector: " o "
    #         two_words_connector: " y "
    #         last_word_connector: " o al menos "

    ['uno', 'dos'].to_sentence(locale: :es)
    # => "uno y dos"

    ['uno', 'dos', 'tres'].to_sentence(locale: :es)
    # => "uno o dos o al menos tres"

    # File lib/active_support/core_ext/array/conversions.rb, line 59
    def to_sentence(options = {})
      options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)

      default_connectors = {
        :words_connector     => ', ',
        :two_words_connector => ' and ',
        :last_word_connector => ', and '
      }
      if defined?(I18n)
        i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
        default_connectors.merge!(i18n_connectors)
      end
      options = default_connectors.merge!(options)

      case length
      when 0
        ''
      when 1
        self[0].to_s.dup
      when 2
        "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
      else
        "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
      end
    end

to_xml(options = {}) { |builder| ... } click to toggle source

Returns a string that represents the array in XML by invoking `to_xml` on each element. Active Record collections delegate their representation in XML to this method.

All elements are expected to respond to `to_xml`, if any of them does not then an exception is raised.

The root node reflects the class name of the first element in plural if all elements belong to the same type and that's not Hash:

    customer.projects.to_xml

    <?xml version="1.0" encoding="UTF-8"?>
    <projects type="array">
      <project>
        <amount type="decimal">20000.0</amount>
        <customer-id type="integer">1567</customer-id>
        <deal-date type="date">2008-04-09</deal-date>
        ...
      </project>
      <project>
        <amount type="decimal">57230.0</amount>
        <customer-id type="integer">1567</customer-id>
        <deal-date type="date">2008-04-15</deal-date>
        ...
      </project>
    </projects>

Otherwise the root element is “objects”:

    [{ foo: 1, bar: 2}, { baz: 3}].to_xml

    <?xml version="1.0" encoding="UTF-8"?>
    <objects type="array">
      <object>
        <bar type="integer">2</bar>
        <foo type="integer">1</foo>
      </object>
      <object>
        <baz type="integer">3</baz>
      </object>
    </objects>

If the collection is empty the root element is “nil-classes” by default:

    [].to_xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nil-classes type="array"/>

To ensure a meaningful root element use the `:root` option:

    customer_with_no_projects.projects.to_xml(root: 'projects')

    <?xml version="1.0" encoding="UTF-8"?>
    <projects type="array"/>

By default name of the node for the children of root is `root.singularize`. You can change it with the `:children` option.

The `options` hash is passed downwards:

    Message.all.to_xml(skip_types: true)

    <?xml version="1.0" encoding="UTF-8"?>
    <messages>
      <message>
        <created-at>2008-03-07T09:58:18+01:00</created-at>
        <id>1</id>
        <name>1</name>
        <updated-at>2008-03-07T09:58:18+01:00</updated-at>
        <user-id>1</user-id>
      </message>
    </messages>

    # File lib/active_support/core_ext/array/conversions.rb, line 179
    def to_xml(options = {})
      require 'active_support/builder' unless defined?(Builder)

      options = options.dup
      options[:indent]  ||= 2
      options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
      options[:root]    ||=        if first.class != Hash && all? { |e| e.is_a?(first.class) }
          underscored = ActiveSupport::Inflector.underscore(first.class.name)
          ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
        else
          'objects'
        end

      builder = options[:builder]
      builder.instruct! unless options.delete(:skip_instruct)

      root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
      children = options.delete(:children) || root.singularize
      attributes = options[:skip_types] ? {} : { type: 'array' }

      if empty?
        builder.tag!(root, attributes)
      else
        builder.tag!(root, attributes) do
          each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
          yield builder if block_given?
        end
      end
    end