Estoy buscando una solución al siguiente problema: Tengo una entidad ActiveRecord respaldada por una vista de base de datos actualizable (en DB2 a través del activerecord-jdbc -adapter gema). Esta vista contiene una columna que se calcula a partir de otras columnas y es 'de solo lectura': no puede establecer esa columna de ninguna manera válida. Cuando se crea un nuevo registro para esta entidad, se debe establecer ese campo no. Sin embargo, de forma predeterminada, ActiveRecord lo establece con el 'predeterminado' (NULL), que es rechazado por la base de datos.Ignorar columna 'solo lectura' en creaciones y actualizaciones en Ruby ActiveRecord
attr_readonly no es una solución, porque eso solo excluye una columna de las actualizaciones y no de las creaciones.
attr_ignore, como implementado por la gema 'lincoln', tampoco es una solución, porque entonces el campo se ignora por completo. Sin embargo, la columna aún debe leerse y ser accesible. En realidad, incluso se usa como parte de una relación.
Hay maneras para evitar que pueda establecer un determinado atributo de una entidad ActiveRecord, pero eso no significa por lo general evitan ese atributo de ser incluido en crear o instrucciones de actualización
¿alguien sabe si hay una manera de ActiveRecord para especificar una columna como 'nunca configurar este campo'?
Actualización, en respuesta a Arsen7: He intentado utilizar el gancho after_initialize para eliminar el atributo de una entidad recién creada, por lo que no está incluido en el SQL creado. El problema con esto es que el atributo se elimina por completo y ya no está disponible, prácticamente idéntico a la situación 'igonre_attr' descrita anteriormente. Debido al almacenamiento en caché, no es trivial para moverse y requeriría una lógica adicional para forzar una recarga de entidades de estas tablas específicas. Eso probablemente se puede lograr anulando create
para agregar una 'recarga', además de usar after_initialize.
(Como ha señalado Arsen7, se me olvidó mencionar que estoy en ActiveRecord 3.0.9)
Mi solución
Desde mis entidades ya heredan de una subclase de ActiveRecord::Base
, no tengo optó por agregar ganchos before_create
y after_create
. En el gancho before_create
, elimino las columnas 'calculadas' del @attributes
de la instancia. En el gancho after_create
, los vuelvo a agregar y leo los valores de las columnas 'calculadas' de la base de datos para establecerlos en los valores que recibieron.
La adición de tales ganchos es casi idéntica a la creación superior, por lo que considero que la respuesta de Arsen7 es correcta.
Si está por volver a escribir 'crear', no sugiero retirar el atributo del objeto, sólo sugieren crear (y ejecutar) el SQL sin la columna especificada. Pero ¿qué hay de los factores desencadenantes? Parece la solución más elegante, su consulta será reescrita por la base de datos, allí puede eliminar esa columna de solo lectura de la consulta final. – Arsen7
Me gusta la idea de los factores desencadenantes, pero la desventaja es que el campo calculado debe actualizarse cuando cambia uno de los campos 'fuente'. Esencialmente, el campo calculado hace lo mismo que múltiples disparadores en una cantidad de otros campos. Como tal, es algo más simple que múltiples factores desencadenantes. En cuanto a modificar 'crear' (y tal vez 'actualizar'): prefiero que lo anterior modifique el método que crea el SQL, porque este último está más profundamente en los tazones de ActiveRecord. Los cambios de nivel más altos son generalmente más fáciles de entender. Sin embargo, todavía tengo que hacerlo y puedo equivocarme al respecto :) – Confusion