

# Uso de capas para funciones de Lambda en Ruby
<a name="ruby-layers"></a>

Utilice [capas de Lambda](chapter-layers.md) para empaquetar el código y las dependencias que desee reutilizar en varias funciones. Las capas suelen contener dependencias de biblioteca, un [tiempo de ejecución personalizado](runtimes-custom.md) o archivos de configuración. La creación de una capa implica tres pasos generales:

1. Empaquete el contenido de su capa. Esto significa crear un archivo de archivo. zip que contenga las dependencias que desea usar en sus funciones.

1. Cree la capa en Lambda.

1. Agregue la capa a sus funciones.

**Topics**
+ [Empaquete el contenido de su capa.](#ruby-layers-package)
+ [Creación de la capa en Lambda](#publishing-layer)
+ [Utilización de gemas de capas en una función](#ruby-layers-bundler-limitations)
+ [Adición de la capa a la función](#ruby-layer-adding)
+ [Aplicación de ejemplo](#ruby-layer-sample-app)

## Empaquete el contenido de su capa.
<a name="ruby-layers-package"></a>

Para crear una capa, agrupe sus paquetes en un archivo .zip que cumpla con los siguientes requisitos:
+ Cree la capa con la misma versión de Ruby que tiene previsto usar para la función de Lambda. Por ejemplo, si crea una capa para Ruby 3.4, utilice el tiempo de ejecución de Ruby 3.4 para su función.
+ El archivo .zip de su capa debe usar una de estas estructuras de directorios:
  + `ruby/gems/x.x.x` (donde *x.x.x* es su versión de Ruby, por ejemplo `3.4.0`)
  + `ruby/lib`

  Para obtener más información, consulte [Rutas de capa para cada tiempo de ejecución de Lambda](packaging-layers.md#packaging-layers-paths).
+ Los paquetes de la capa deben ser compatibles con Linux. Las funciones de Lambda se ejecutan en Amazon Linux.

Puede crear capas que contengan gemas de Ruby de terceros o sus propios módulos y clases de Ruby. Muchas gemas populares de Ruby contienen extensiones nativas (código C) que deben compilarse para el entorno de Lambda de Linux.

### Ruby con gemas puras
<a name="ruby-layers-pure-ruby-gems"></a>

Las gemas puras de Ruby contienen solo código de Ruby y no requieren compilación. Estas gemas son más fáciles de empaquetar y funcionan en diferentes plataformas.

**Creación de una capa usando gemas puras de Ruby**

1. Cree un `Gemfile` para especificar las gemas puras de Ruby que desea incluir en su capa:  
**Example Archivo Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'tzinfo'
   ```

1. Instale las gemas en el directorio `vendor/bundle` mediante Bundler:

   ```
   bundle config set --local path vendor/bundle
   bundle install
   ```

1. Copie las gemas instaladas a la estructura de directorios que Lambda requiere `ruby/gems/3.4.0`):

   ```
   mkdir -p ruby/gems/3.4.0
   cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   ```

1. Comprima en formato zip el contenido de la capa:

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   La estructura de directorios del archivo .zip debería ser similar a la siguiente:

   ```
   ruby/              
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── concurrent-ruby-1.3.5/
           │   └── tzinfo-2.0.6/
           ├── specifications/
           ├── cache/
           ├── build_info/
           └── (other bundler directories)
   ```
**nota**  
Debe incluir cada gema de forma individual en el código de la función. No puede utilizar `bundler/setup` o `Bundler.require`. Para obtener más información, consulte [Utilización de gemas de capas en una función](#ruby-layers-bundler-limitations).

### Gemas con extensiones nativas
<a name="ruby-layers-native-extensions"></a>

Muchas gemas de Ruby populares contienen extensiones nativas (código C) que deben compilarse para la plataforma de destino. Entre las gemas más populares con extensiones nativas se encuentran [nokogiri](https://rubygems.org/gems/nokogiri/), [pg](https://rubygems.org/gems/pg/), [mysql2](https://rubygems.org/gems/mysql2/), [sqlite3](https://rubygems.org/gems/sqlite3/) y [ffi](https://rubygems.org/gems/ffi/). Estas gemas se deben crear en un entorno de Linux que sea compatible con el tiempo de ejecución de Lambda.

**Creación de una capa con gemas con extensiones nativas**

1. Creación de una `Gemfile`.  
**Example Archivo Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'nokogiri'
   gem 'httparty'
   ```

1. Utilice Docker para crear las gemas en un entorno de Linux que sea compatible con Lambda. Especifique una [imagen base de AWS](ruby-image.md#ruby-image-base) en su Dockerfile:  
**Example Dockerfile para Ruby 3.4**  

   ```
   FROM public.ecr.aws/lambda/ruby:3.4
   
   # Copy Gemfile
   COPY Gemfile ./
   
   # Install system dependencies for native extensions
   RUN dnf update -y && \
       dnf install -y gcc gcc-c++ make
   
   # Configure bundler and install gems
   RUN bundle config set --local path vendor/bundle && \
       bundle install
   
   # Create the layer structure
   RUN mkdir -p ruby/gems/3.4.0 && \
       cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   
   # Create the layer zip file
   RUN zip -r layer.zip ruby/
   ```

1. Cree la imagen y extraiga la capa:

   ```
   docker build -t ruby-layer-builder .
   docker run --rm -v $(pwd):/output --entrypoint cp ruby-layer-builder layer.zip /output/
   ```

   Esto crea las gemas en el entorno de Linux correcto y copia el archivo `layer.zip` a su directorio local. La estructura de directorios del archivo .zip debería ser similar a la siguiente:

   ```
   ruby/
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── bigdecimal-3.2.2/
           │   ├── csv-3.3.5/
           │   ├── httparty-0.23.1/
           │   ├── mini_mime-1.1.5/
           │   ├── multi_xml-0.7.2/
           │   ├── nokogiri-1.18.8-x86_64-linux-gnu/
           │   └── racc-1.8.1/
           ├── build_info/
           ├── cache/
           ├── specifications/
           └── (other bundler directories)
   ```
**nota**  
Debe incluir cada gema de forma individual en el código de la función. No puede utilizar `bundler/setup` o `Bundler.require`. Para obtener más información, consulte [Utilización de gemas de capas en una función](#ruby-layers-bundler-limitations).

### Módulos de Ruby personalizados
<a name="custom-ruby-modules"></a>

**Creación de una capa con su propio código**

1. Cree la estructura del directorio necesario para su capa:

   ```
   mkdir -p ruby/lib
   ```

1. Cree sus módulos de Ruby en el directorio `ruby/lib`. El siguiente módulo de ejemplo valida los pedidos mediante la confirmación de que contienen la información requerida.  
**Example ruby/lib/order\$1validator.rb**  

   ```
   require 'json'
   
   module OrderValidator
     class ValidationError < StandardError; end
   
     def self.validate_order(order_data)
       # Validates an order and returns formatted data
       required_fields = %w[product_id quantity]
       
       # Check required fields
       missing_fields = required_fields.reject { |field| order_data.key?(field) }
       unless missing_fields.empty?
         raise ValidationError, "Missing required fields: #{missing_fields.join(', ')}"
       end
       
       # Validate quantity
       quantity = order_data['quantity']
       unless quantity.is_a?(Integer) && quantity > 0
         raise ValidationError, 'Quantity must be a positive integer'
       end
       
       # Format and return the validated data
       {
         'product_id' => order_data['product_id'].to_s,
         'quantity' => quantity,
         'shipping_priority' => order_data.fetch('priority', 'standard')
       }
     end
   
     def self.format_response(status_code, body)
       # Formats the API response
       {
         statusCode: status_code,
         body: JSON.generate(body)
       }
     end
   end
   ```

1. Comprima en formato zip el contenido de la capa:

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   La estructura de directorios del archivo .zip debería ser similar a la siguiente:

   ```
   ruby/              
   └── lib/
       └── order_validator.rb
   ```

1. En su función, solicite y utilice los módulos. Debe incluir cada gema de forma individual en el código de la función. No puede utilizar `bundler/setup` o `Bundler.require`. Para obtener más información, consulte [Utilización de gemas de capas en una función](#ruby-layers-bundler-limitations). Ejemplo:

   ```
   require 'json'
   require 'order_validator'
   
   def lambda_handler(event:, context:)
     begin
       # Parse the order data from the event body
       order_data = JSON.parse(event['body'] || '{}')
       
       # Validate and format the order
       validated_order = OrderValidator.validate_order(order_data)
       
       OrderValidator.format_response(200, {
         message: 'Order validated successfully',
         order: validated_order
       })
     rescue OrderValidator::ValidationError => e
       OrderValidator.format_response(400, {
         error: e.message
       })
     rescue => e
       OrderValidator.format_response(500, {
         error: 'Internal server error'
       })
     end
   end
   ```

   Puede usar el siguiente [evento de prueba](testing-functions.md#invoke-with-event) para invocar la función:

   ```
   {
       "body": "{\"product_id\": \"ABC123\", \"quantity\": 2, \"priority\": \"express\"}"
   }
   ```

   Respuesta esperada:

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"Order validated successfully\",\"order\":{\"product_id\":\"ABC123\",\"quantity\":2,\"shipping_priority\":\"express\"}}"
   }
   ```

## Creación de la capa en Lambda
<a name="publishing-layer"></a>

También puede publicar la capa con la AWS CLI o la consola de Lambda.

------
#### [ AWS CLI ]

Ejecute el comando [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) de la AWS CLI para crear la capa de Lambda:

```
aws lambda publish-layer-version --layer-name my-layer --zip-file fileb://layer.zip --compatible-runtimes ruby3.4
```

El parámetro [Tiempos de ejecución compatibles](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes) es opcional. Cuando se especifica, Lambda usa este parámetro para filtrar las capas en la consola de Lambda.

------
#### [ Console ]

**Para crear una capa (consola)**

1. Abra la página de [Capas](https://console.aws.amazon.com/lambda/home#/layers) de la consola de Lambda.

1. Elija **Crear capa**.

1. Elija **Cargar un archivo .zip** y, a continuación, cargue el archivo .zip que creó anteriormente.

1. (Opcional) En **Tiempos de ejecución compatibles**, elija el tiempo de ejecución de Ruby que corresponda a la versión de Ruby que utilizó para crear la capa.

1. Seleccione **Crear**.

------

## Utilización de gemas de capas en una función
<a name="ruby-layers-bundler-limitations"></a>

En el código de la función, debe especificar de forma explícita cada gema que desee utilizar. Los comandos de Bundler como `bundler/setup` y `Bundler.require` no son compatibles. A continuación, se explica cómo utilizar las gemas de una capa en una función de Lambda correctamente:

```
# Correct: Use explicit requires for each gem
require 'nokogiri'
require 'httparty'

def lambda_handler(event:, context:)
  # Use the gems directly
  doc = Nokogiri::HTML(event['html'])
  response = HTTParty.get(event['url'])
  # ... rest of your function
end

# Incorrect: These Bundler commands will not work
# require 'bundler/setup'
# Bundler.require
```

## Adición de la capa a la función
<a name="ruby-layer-adding"></a>

------
#### [ AWS CLI ]

Para adjuntar la capa a la función, ejecute el comando [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) de la AWS CLI. Para el parámetro `--layers`, use el ARN de la capa. El ARN debe especificar la versión (por ejemplo, `arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1`). Para obtener más información, consulte [Capas y versiones de capas](chapter-layers.md#lambda-layer-versions).

```
aws lambda update-function-configuration --function-name my-function --cli-binary-format raw-in-base64-out --layers "arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1"
```

La opción **cli-binary-format** es obligatoria si va a utilizar la versión 2 de la AWS CLI. Para que esta sea la configuración predeterminada, ejecute `aws configure set cli-binary-format raw-in-base64-out`. Para obtener más información, consulte [Opciones de la línea de comandos globales compatibles con AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) en la *Guía del usuario de la AWS Command Line Interface versión 2*.

------
#### [ Console ]

**Adición de una capa a una función**

1. Abra la página de [Funciones](https://console.aws.amazon.com/lambda/home#/functions) en la consola de Lambda.

1. Elija la función.

1. Desplácese hacia abajo hasta la sección **Capas** y, a continuación, elija **Agregar una capa**.

1. En **Elija una capa**, seleccione **Capas personalizadas** y, a continuación, elija su capa.
**nota**  
Si no agregó un [tiempo de ejecución compatible](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes) al crear la capa, su capa no aparecerá aquí. Puede especificar el ARN de la capa en su lugar.

1. Elija **Agregar**.

------

## Aplicación de ejemplo
<a name="ruby-layer-sample-app"></a>

Para ver más ejemplos de cómo usar las capas de Lambda, consulte la aplicación de ejemplo [layer-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-ruby) en el repositorio de GitHub de la Guía para desarrolladores de AWS Lambda. Esta aplicación incluye una capa que contiene la biblioteca [tzinfo](https://rubygems.org/gems/tzinfo). Después de crear la capa, puede implementar e invocar las funciones correspondientes para confirmar que la capa funciona como se espera.