validar validaciones relaciones realizan rails polimorficas las formulario cómo asociaciones ruby-on-rails ruby activerecord ruby-on-rails-3 associations

ruby-on-rails - relaciones - validaciones rails



Rails-Mejores prácticas: cómo crear relaciones has_one dependientes (6)

¿Podría decirme cuál es la mejor práctica para crear has_one relations?

fe si tengo un modelo de usuario, y debe tener un perfil ...

¿Cómo podría lograr eso?

Una solución sería:

# user.rb class User << ActiveRecord::Base after_create :set_default_association def set_default_association self.create_profile end end

Pero eso no parece muy limpio ... ¿Alguna sugerencia?


Así es como lo hago. No estoy seguro de qué tan estándar es esto, pero funciona muy bien y es flojo en cuanto a que no crea una sobrecarga adicional a menos que sea necesario construir la nueva asociación (me complace que se corrija al respecto):

def profile_with_auto_build build_profile unless profile_without_auto_build profile_without_auto_build end alias_method_chain :profile, :auto_build

Esto también significa que la asociación está allí tan pronto como lo necesite. Supongo que la alternativa es enlazar en after_initialize, pero parece agregar bastante sobrecarga, ya que se ejecuta cada vez que se inicializa un objeto y puede haber ocasiones en las que no te importa acceder a la asociación. Parece un desperdicio verificar su existencia.



La mejor práctica para crear una relación has_one es utilizar la devolución de llamada ActiveRecord before_create lugar de after_create . O utilice una devolución de llamada incluso anterior y trate los problemas (si los hay) del niño que no pasa su propio paso de validación.

Porque:

  • con una buena codificación, tiene la oportunidad de mostrar las validaciones del registro secundario al usuario si las validaciones fallan
  • es más limpio y cuenta con el respaldo explícito de ActiveRecord: AR completa automáticamente la clave externa en el registro secundario después de guardar el registro principal (en la creación). AR luego guarda el registro secundario como parte de la creación del registro principal.

Cómo hacerlo:

# in your User model... has_one :profile before_create :build_default_profile private def build_default_profile # build default profile instance. Will use default params. # The foreign key to the owning User model is set automatically build_profile true # Always return true in callbacks as the normal ''continue'' state # Assumes that the default_profile can **always** be created. # or # Check the validation of the profile. If it is not valid, then # return false from the callback. Best to use a before_validation # if doing this. View code should check the errors of the child. # Or add the child''s errors to the User model''s error array of the :base # error item end


Probablemente no sea la solución más limpia, pero ya teníamos una base de datos con medio millón de registros, algunos de los cuales ya tenían el modelo ''Perfil'' creado y otros no. Fuimos con este enfoque, que garantiza que un modelo de perfil está presente en cualquier punto, sin necesidad de pasar y generar retroactivamente todos los modelos de perfil.

alias_method :db_profile, :profile def profile self.profile = Profile.create(:user => self) if self.db_profile.nil? self.db_profile end


Si esta es una nueva asociación en una gran base de datos existente, administraré la transición de esta manera:

class User << ActiveRecord::Base has_one :profile before_create :build_associations def profile super || build_profile(avatar: "anon.jpg") end private def build_associations profile || true end end

para que los registros de usuario existentes ganen un perfil cuando se le solicite y se creen nuevos con él. Esto también coloca los atributos predeterminados en un lugar y funciona correctamente con accepts_nested_attributes_for en Rails 4 en adelante.


Su solución es definitivamente una forma decente de hacerlo (al menos hasta que crezca), pero puede simplificarla:

# user.rb class User < ActiveRecord::Base has_one :profile after_create :create_profile end