Estoy tratando de encontrar la mejor manera de establecer valores predeterminados para objetos en Rails.
Lo mejor que se me ocurre es establecer el valor predeterminado en el new
método en el controlador.
¿Alguien tiene alguna sugerencia si esto es aceptable o si hay una mejor manera de hacerlo?
ruby-on-rails
ruby
biagidp
fuente
fuente
Respuestas:
"Correcto" es una palabra peligrosa en Ruby. Por lo general, hay más de una forma de hacer cualquier cosa. Si sabe que siempre querrá ese valor predeterminado para esa columna en esa tabla, configurarlos en un archivo de migración de base de datos es la forma más fácil:
Debido a que ActiveRecord detecta automáticamente las propiedades de su tabla y columna, esto hará que se establezca el mismo valor predeterminado en cualquier modelo que lo use en cualquier aplicación estándar de Rails.
Sin embargo, si solo desea establecer valores predeterminados en casos específicos, por ejemplo, es un modelo heredado que comparte una tabla con otros, entonces otra forma elegante es hacerlo directamente en su código Rails cuando se crea el objeto modelo:
Luego, cuando hagas una
GenericPerson.new()
, siempre se filtrará el atributo "Doe" aPerson.new()
menos que lo anules con otra cosa.fuente
.new
método de clase. La discusión de esa publicación de blog sobre la llamada directa de ActiveRecord.allocate
fue sobre objetos modelo cargados con datos existentes de la base de datos. ( Y es una idea terrible que ActiveRecord funcione de esa manera, en mi opinión. Pero eso nochange_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520change_column :people, :last_name, :string, default: "Doe"
Basado en la respuesta de SFEley, aquí hay uno actualizado / fijo para las versiones más nuevas de Rails:
fuente
change_column
puede ser bastante "estructurante", no se puede deducir la operación inversa. Si no está seguro, simplemente pruébelo ejecutándolodb:migrate
edb:rollback
inmediatamente después. Respuesta aceptada como el mismo resultado, pero al menos se asume.up
ydown
como se describe arriba de @GoBustoEn primer lugar, no puede sobrecargar,
initialize(*args)
ya que no se llama en todos los casos.Su mejor opción es poner sus valores predeterminados en su migración:
La segunda mejor opción es colocar valores predeterminados en su modelo, pero esto solo funcionará con atributos que inicialmente son nulos. Puede tener problemas como yo con las
boolean
columnas:Necesita el
new_record?
para que los valores predeterminados no anulen los valores cargados desde la base de datos.Es necesario
||=
dejar de rieles anule los parámetros pasados al método initialize.fuente
after_initiation :your_method_name
... 2 usoself.max_users ||= 10
after_initialize do
lugar dedef after_initialize
También puede probar
change_column_default
en sus migraciones (probado en Rails 3.2.8):change_column_default Documentos de la API de Rails
fuente
Si se refiere a objetos ActiveRecord, tiene (más de) dos formas de hacerlo:
1. Utilice un: parámetro predeterminado en la base de datos
P.EJ
Más información aquí: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
2. Utilice una devolución de llamada
P.EJ
before_validation_on_create
Más información aquí: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
fuente
En Ruby on Rails v3.2.8, usando la
after_initialize
devolución de llamada ActiveRecord, puede llamar a un método en su modelo que asignará los valores predeterminados para un nuevo objeto.Entonces, en mi opinión, debería verse así:
Foo.bar = default_value
para esta instancia, a menos que la instancia contengaattribute_whose_presence_has_been_validated
previamente un guardado / actualización. Eldefault_value
se utilizará entonces en conjunción con su visión para hacer que el formulario utilizando eldefault_value
para elbar
atributo.En el mejor de los casos, esto es hacky ...
EDITAR - use 'new_record?' para comprobar si se crea una instancia desde una nueva llamada
En lugar de comprobar el valor de un atributo, utilice el
new_record?
método integrado con rieles. Entonces, el ejemplo anterior debería verse así:Esto es mucho más limpio. Ah, la magia de Rails, es más inteligente que yo.
fuente
after_initialize
devolver la llamada aquí? La documentación de Rails sobre devoluciones de llamada tiene un ejemplo de configuración del valor predeterminadobefore_create
sin verificaciones de condición adicionalesSubscription
after_initialize
, en lugar de labefore_create
devolución de llamada, es que queremos establecer un valor predeterminado para el usuario (para usar en una vista) cuando están creando nuevos objetos. Labefore_create
devolución de llamada se llama después de que el usuario haya recibido un nuevo objeto, haya proporcionado su entrada y haya enviado el objeto para su creación al controlador. Luego, el controlador verifica si haybefore_create
devoluciones de llamada. Parece contrario a la intuición, pero es una cuestión de nomenclatura: sebefore_create
refiere a lacreate
acción. Crear una instancia de un nuevo objeto no escreate
el objeto.Para los campos booleanos en Rails 3.2.6 al menos, esto funcionará en su migración.
Poner
1
o0
por defecto no funcionará aquí, ya que es un campo booleano. Debe ser un valortrue
ofalse
.fuente
En caso de que se trate de un modelo, puede utilizar la API de atributos en Rails 5+ http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
simplemente agregue una migración con un nombre de columna adecuado y luego en el modelo configúrelo con:
fuente
Genera una migración y uso
change_column_default
, es sucinto y reversible:fuente
Si solo está configurando valores predeterminados para ciertos atributos de un modelo respaldado por una base de datos, consideraría usar valores de columna predeterminados de SQL: ¿puede aclarar qué tipos de valores predeterminados está utilizando?
Hay varios enfoques para manejarlo, este complemento parece una opción interesante.
fuente
La sugerencia de anular new / initialize probablemente esté incompleta. Rails (con frecuencia) llamará a allocate para los objetos ActiveRecord, y las llamadas a allocate no resultarán en llamadas a inicializar.
Si está hablando de objetos ActiveRecord, eche un vistazo a anular after_initialize.
Estas publicaciones de blog (no las mías) son útiles:
Valores predeterminados No se llaman los constructores predeterminados
[Editar: SFEley señala que Rails en realidad mira el valor predeterminado en la base de datos cuando crea una instancia de un nuevo objeto en la memoria; no me había dado cuenta de eso].
fuente
Necesitaba establecer un valor predeterminado como si estuviera especificado como valor de columna predeterminado en la base de datos. Entonces se comporta así
Debido a que se llama a la devolución de llamada after_initialize después de establecer atributos a partir de argumentos, no había forma de saber si el atributo es nil porque nunca se estableció o porque se estableció intencionalmente como nil. Así que tuve que hurgar un poco y vine con esta sencilla solución.
Funciona muy bien para mi. (Rieles 3.2.x)
fuente
Una forma potencial potencialmente incluso mejor / más limpia que las respuestas propuestas es sobrescribir el descriptor de acceso, así:
Consulte "Sobrescritura de los descriptores de acceso predeterminados" en la documentación de ActiveRecord :: Base y más de StackOverflow sobre el uso de self .
fuente
Respondí una pregunta similar aquí ... una forma limpia de hacer esto es usando Rails attr_accessor_with_default
ACTUALIZAR
attr_accessor_with_default ha quedado obsoleto en Rails 3.2 ... puedes hacer esto en su lugar con Ruby puro
fuente
attr_accessor_with_default
está obsoleto a partir de rieles> 3.1.0Si estás hablando de objetos ActiveRecord, utilizo la gema 'atributos predeterminados'.
Documentación y descarga: https://github.com/bsm/attribute-defaults
fuente
Podrías usar la gema rails_default_value. p.ej:
https://github.com/keithrowell/rails_default_value
fuente
Puede anular el constructor del modelo ActiveRecord.
Me gusta esto:
fuente