

# Como trabalhar com camadas em Ruby para funções do Lambda
<a name="ruby-layers"></a>

Use [camadas do Lambda](chapter-layers.md) para empacotar o código e as dependências que você quiser reutilizar em várias funções. As camadas geralmente contêm dependências de biblioteca, um [runtime personalizado](runtimes-custom.md) ou arquivos de configuração. A criação de uma camada envolve três etapas gerais:

1. Empacotar o conteúdo da sua camada. Isso significa criar um arquivo .zip contendo as dependências que você deseja usar em suas funções.

1. Criar a camada no Lambda.

1. Adicionar a camada às suas funções.

**Topics**
+ [Empacotar o conteúdo da sua camada](#ruby-layers-package)
+ [Criar a camada no Lambda](#publishing-layer)
+ [Como usar gems de camadas em uma função](#ruby-layers-bundler-limitations)
+ [Adicionar a camada à função](#ruby-layer-adding)
+ [Aplicação de amostra](#ruby-layer-sample-app)

## Empacotar o conteúdo da sua camada
<a name="ruby-layers-package"></a>

Para criar uma camada, reúna os pacotes em um arquivo .zip que atenda aos seguintes requisitos:
+ Crie a camada usando a mesma versão do Ruby que você planeja usar para a função do Lambda. Por exemplo, se você criar a camada para o Ruby 3.4, use o runtime do Ruby 3.4 para a função.
+ O arquivo .zip da camada deve usar uma destas estruturas de diretório:
  + `ruby/gems/x.x.x` (onde *x.x.x* é sua versão do Ruby, por exemplo `3.4.0`)
  + `ruby/lib`

  Para obter mais informações, consulte [Caminhos da camada para cada runtime do Lambda](packaging-layers.md#packaging-layers-paths).
+ Os pacotes da camada devem ser compatíveis com o Linux. As funções do Lambda são executadas no Amazon Linux.

Você pode criar camadas que contenham gems em Ruby de terceiros ou seus próprios módulos e classes em Ruby. Muitos gems em Ruby populares contêm extensões nativas (código C) que devem ser compiladas para o ambiente Lambda Linux.

### Gems em Ruby Pure
<a name="ruby-layers-pure-ruby-gems"></a>

Os gems em Ruby puras contêm somente código Ruby e não precisam de compilação. Essas geas são mais simples de empacotar e trabalhar em diferentes plataformas.

**Para criar uma camada usando os gems em Ruby Pure**

1. Crie um `Gemfile` para especificar os gems em Ruby Pure que você deseja incluir na sua camada:  
**Example Gemfile**  

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

1. Instale os gems no diretório `vendor/bundle` usando o Bundler:

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

1. Copie os gems instalados para a estrutura de diretórios exigida pelo Lambda`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. Crie um arquivo .zip do conteúdo da camada:

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

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

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

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

------

   A estrutura de diretórios do arquivo zip deve ser assim:

   ```
   ruby/              
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── concurrent-ruby-1.3.5/
           │   └── tzinfo-2.0.6/
           ├── specifications/
           ├── cache/
           ├── build_info/
           └── (other bundler directories)
   ```
**nota**  
Você deve exigir cada gem individualmente em seu código de função. Você pode usar `bundler/setup` ou `Bundler.require`. Para obter mais informações, consulte [Como usar gems de camadas em uma função](#ruby-layers-bundler-limitations).

### Gems com extensões nativas
<a name="ruby-layers-native-extensions"></a>

Muitos gems em Ruby populares contêm extensões nativas (código C) que devem ser compiladas para a plataforma de destino. Gemas populares com extensões nativas incluem [nokogiri](https://rubygems.org/gems/nokogiri/), [pg](https://rubygems.org/gems/pg/), [mysql2](https://rubygems.org/gems/mysql2/), [sqlite3](https://rubygems.org/gems/sqlite3/) e [ffi](https://rubygems.org/gems/ffi/). Esses gems devem ser criados em um ambiente Linux compatível com o runtime do Lambda.

**Para criar uma camada usando gems com extensões nativas**

1. Crie um `Gemfile`.  
**Example Gemfile**  

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

1. Use o Docker para criar os gems em um ambiente Linux compatível com o Lambda. Especifique uma [imagem base da AWS](ruby-image.md#ruby-image-base) em seu 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. Crie a imagem e extraia a camada:

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

   Isso cria os gems no ambiente Linux correto e copia o arquivo `layer.zip` para o diretório local. A estrutura de diretórios do arquivo zip deve ser assim:

   ```
   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**  
Você deve exigir cada gem individualmente em seu código de função. Você pode usar `bundler/setup` ou `Bundler.require`. Para obter mais informações, consulte [Como usar gems de camadas em uma função](#ruby-layers-bundler-limitations).

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

**Para criar uma camada usando seu próprio código**

1. Crie a estrutura de diretório necessária para sua camada:

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

1. Crie seus módulos de Ruby no diretório `ruby/lib`. O exemplo de módulo a seguir valida os pedidos confirmando que eles contêm as informações necessárias.  
**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. Crie um arquivo .zip do conteúdo da camada:

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

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

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

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

------

   A estrutura de diretórios do arquivo zip deve ser assim:

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

1. Na função, exija e use os módulos. Você deve exigir cada gem individualmente em seu código de função. Você pode usar `bundler/setup` ou `Bundler.require`. Para obter mais informações, consulte [Como usar gems de camadas em uma função](#ruby-layers-bundler-limitations). Exemplo:

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

   Você pode usar os seguinte [evento de teste](testing-functions.md#invoke-with-event)para invocar a função:

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

   Resposta esperada:

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

## Criar a camada no Lambda
<a name="publishing-layer"></a>

Você pode publicar a camada usando a AWS CLI ou o console do Lambda.

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

Execute o comando da AWS CLI [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) para criar a camada do Lambda:

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

O parâmetro [runtimes compatíveis](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes) é opcional. Quando especificado, o Lambda usa esse parâmetro para filtrar camadas no console do Lambda.

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

**Para criar uma camada (console)**

1. Abra a [página Layers](https://console.aws.amazon.com/lambda/home#/layers) (Camadas) do console do Lambda.

1. Escolha **Criar camada**.

1. Escolha **Carregar um arquivo .zip** e depois carregue o arquivo .zip que você criou anteriormente.

1. (Opcional) Para ver quais são os **runtimes compatíveis**, escolha o runtime Ruby que corresponde à versão do Ruby que você usou para criar a camada.

1. Escolha **Criar**.

------

## Como usar gems de camadas em uma função
<a name="ruby-layers-bundler-limitations"></a>

Em seu código de função, você deve exigir explicitamente cada gem que você deseja usar. Comandos do bundler, como `bundler/setup` e `Bundler.require` não são compatíveis. Veja como usar corretamente os gems de uma camada em uma função do Lambda:

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

## Adicionar a camada à função
<a name="ruby-layer-adding"></a>

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

Para anexar a camada à função, execute o comando da AWS CLI [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) . Para o parâmetro `--layers` use o ARN da camada. O ARN deve especificar a versão (por exemplo, `arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1`). Para obter mais informações, consulte [Camadas e versões da camada](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"
```

A opção **cli-binary-format** será necessária se você estiver usando a AWS CLI versão 2. Para que essa seja a configuração padrão, execute `aws configure set cli-binary-format raw-in-base64-out`. Para obter mais informações, consulte [A AWS CLI comporta opções de linha de comando globais](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) no *Guia do usuário da AWS Command Line Interface versão 2*.

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

**Para adicionar uma camada a uma função**

1. Abra a [página Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda.

1. Escolha a função.

1. Role a tela para baixo até a seção **Camadas** e depois escolha **Adicionar uma camada**.

1. Em **Escolher uma camada**, selecione **Camadas personalizadas** e depois escolha a camada.
**nota**  
Se você não adicionou um [runtime compatível](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes) ao criar a camada, ela não estará listada aqui. Em vez disso, você pode especificar o ARN da camada.

1. Escolha **Adicionar**.

------

## Aplicação de amostra
<a name="ruby-layer-sample-app"></a>

Para obter mais exemplos de como usar camadas do Lambda, consulte a aplicação de amostra [layer-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-ruby) no repositório AWS Lambda Developer Guide do GitHub. Essa aplicação inclui uma camada que contém a biblioteca [zinfo](https://rubygems.org/gems/tzinfo). Após criar a camada, você pode implantar e invocar as funções correspondentes para confirmar que ela funciona conforme o esperado.