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.

¿Cómo puedo generar la lista de `EntityField`s para un `PersistEntity`?

Estaba tratando de implementar alguna forma de repsertBy: repsert donde la clave es un Unique proporcionado, de la misma manera que getBy y upsertBy, etc.

Mi enfoque: implementarlo en función de upsertBy. Ahora, upsertBy toma una restricción Unique, un registro y una lista de cambios para aplicar en caso de una colisión Unique. Para implementar repsertBy, me gustaría que esa lista de cambios sea “asignar todos los campos al nuevo valor”.

repsertBy :: (MonadIO m, PersistRecordBackend record backend)
          => Unique record -> record
          -> ReaderT backend m (Entity record)
repsertBy unique record = upsertBy unique record [ entifyField =. value | ... ]

Y ahí es donde me quedé atascado.

Puedo generar la lista de valores llamando a toPersistValue en los toPersistFields del registro. Pero, ¿de dónde puedo obtener los EntityFields?

Esperaba que estuvieran disponibles en alguna parte de la definición de entidad en entityDef, pero hasta ahora no encontré ninguno. He intentando comparar con las implementaciones reales de los backends de replace y upsert, pero solo encontré manipulaciones de cadenas a nivel SQL.

Actualmente, estoy escribiendo los campos a mano, pero en algún momento agregaré uno al entity y olvidaré actualizarlo en repsertBy. ¿Hay alguna forma de acceder a los EntityFields?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece que estás intentando implementar una función repsertBy en Haskell utilizando la función upsertBy. Sin embargo, tienes dificultades para generar la lista de cambios a aplicar en caso de una colisión única porque no puedes encontrar los EntityField.

    Desafortunadamente, no estoy familiarizado con los detalles de haskell-persistent, pero puedo sugerir algunas soluciones potenciales que podrían ayudarte.

    En primer lugar, ¿has revisado la documentación o el código fuente de haskell-persistent para ver si hay alguna forma de acceder a los EntityField? Es posible que estén disponibles a través de una función o estructura de datos diferente.

    En segundo lugar, mencionaste que actualmente estás escribiendo manualmente los campos, lo cual propicia errores. Una forma de mitigar este problema es utilizar Template Haskell para generar automáticamente la lista de campos basada en EntityDef. Aquí tienes un ejemplo de implementación:

    import Language.Haskell.TH.Syntax
    
    repsertBy :: (MonadIO m, PersistRecordBackend record backend)
              => Unique record -> record -> ReaderT backend m (Entity record)
    repsertBy unique record = upsertBy unique record changes
      where
        changes = $( do
          EntityDef _ name _ _ fields _ <- lift $ entityDef $ Just record
          let assignments = map ( \f -> [| f =. $(varE $ mkName $ nameBase $ fieldHaskellName f) record|] ) fields
          listE assignments
          )
    

    Esta implementación utiliza la función entityDef para obtener el EntityDef del registro, que contiene información sobre sus campos. Luego genera una lista de asignaciones utilizando Template Haskell, donde cada asignación establece un campo en el valor correspondiente en el registro de entrada. La función listE se utiliza para convertir la lista de asignaciones en una lista de expresiones que se pueden pasar a upsertBy. Ten en cuenta que esta implementación asume que los campos tienen los mismos nombres que los campos del registro (sin el prefijo del registro), lo cual puede no ser el caso en todas las situaciones.

    ¡Espero que esto te ayude a resolver tu problema!

Comments are closed.