es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

En Rails 6 / FactoryBot 6, ¿cómo puedo simular atributos attr_encrypted?

Recientemente actualicé a Rails 6 y FactoryBot 6.2.0. Tengo este modelo:

class Store < ApplicationRecord
  ...
  attr_encrypted :ein_number,
    key: APP_CONFIG[:app_encryption][::Rails.env]['secret_key']
end

Tengo una fábrica correspondiente:

FactoryBot.define do
  factory :store do
    name        { "Test Store" }
    ...
    ein_number  { "00-0000000" }
  end
end

Pero ahora, cuando intento crear una instancia de esta fábrica, obtengo el siguiente error:

Failure/Error: @store = create :store

NoMethodError:
  undefined method `encrypted_ein_number_iv' for #<store:0x00007feec319fbe0>

No estoy seguro de qué ha cambiado en Rails o FactoryBot, pero antes funcionaba sin necesidad de definir un método así. Además, parece una especie de truco. ¿Existe una forma más elegante de definir este atributo en una fábrica?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema parece estar relacionado con el uso de attr_encrypted en el modelo Store. Para crear una fábrica para este modelo, el atributo encriptado debe estar definido correctamente.

    Una opción es definir los atributos encrypted_ein_number y encrypted_ein_number_iv en la fábrica. Esto se puede hacer llamando al método encrypt de la gema attr_encrypted en el valor de ein_number:

    FactoryBot.define do
      factory :store do
        name        { "Tienda de prueba" }
        ein_number  { "00-0000000" }
    
        before(:create) do |store|
          encrypted = AttrEncrypted::Encryptor.encrypt(store.ein_number, key: APP_CONFIG[:app_encryption][::Rails.env]['secret_key'])
          store.encrypted_ein_number = encrypted[:value]
          store.encrypted_ein_number_iv = encrypted[:iv]
        end
      end
    end
    

    Esto encriptará el valor de ein_number usando la clave secreta APP_CONFIG y establecerá los atributos encrypted_ein_number y encrypted_ein_number_iv en la instancia de Store antes de que se cree.

    Alternativamente, si no deseas definir los atributos encriptados en la fábrica, puedes modificar el modelo Store y agregar los siguientes dos métodos:

    def ein_number
      attr_encrypted_ein_number
    end
    
    def ein_number=(value)
      self.attr_encrypted_ein_number = value
    end
    

    Esto permitirá que ein_number se utilice directamente en la fábrica, sin tener que definir los atributos encriptados:

    FactoryBot.define do
      factory :store do
        name        { "Tienda de prueba" }
        ein_number  { "00-0000000" }
      end
    end
    

    Cualquiera que sea la opción que elijas, asegúrate de actualizar cualquier prueba o código existente que pueda verse afectado por los cambios.

Comments are closed.