2011-03-23 13 views
6

Dado el siguiente modelo de base de datos, cómo y dónde definiría las relaciones entre los modelos de eliminación? Descubrí la configuración básica de la asociación de tablas, pero cuando quiero agregar dependencias para habilitar la eliminación de los objetos anidados me pierdo.Cómo definir allow_destroy y: dependent =>: destroy en Rails?

Database relationship model

Aquí es el modelo de relación que he creado.

class User < ActiveRecord::Base 
    has_many :studies 
end 

class Study < ActiveRecord::Base 
    has_many :internships 
    belongs_to :student, :class_name => "User", :foreign_key => "user_id" 
    belongs_to :subject 
    belongs_to :university, :class_name => "Facility", :foreign_key => "facility_id" 
    accepts_nested_attributes_for :subject, :university, :locations 
end 

class Subject < ActiveRecord::Base 
    has_many :studies 
end 

class Internship < ActiveRecord::Base 
    belongs_to :study 
    belongs_to :company, :class_name => "Facility", :foreign_key => 'facility_id' 
    accepts_nested_attributes_for :company, :study 
end 

class Facility < ActiveRecord::Base 
    has_many :internships 
    has_many :locations 
    has_many :studies 
    accepts_nested_attributes_for :locations 
end 

class Location < ActiveRecord::Base 
    belongs_to :facility 
end 

¿Dónde pondrías :dependent => :destroy y :allow_destroy => true para habilitar las siguientes escenarios? No quiero confundirte. Por lo tanto, dejo afuera mis intentos.

Escenario de prácticas: Un usuario quiere eliminar una pasantía.

  • Su empresa asociada se puede eliminar si la empresa no está relacionada con otra pasantía.
  • Si es así, se pueden eliminar las ubicaciones de la empresa asociada.
  • El estudio relacionado no se verá afectado.

escenario Estudio: Un usuario desea eliminar un estudio.

  • Su tema asociado se puede eliminar si ningún otro estudio se refiere a este tema.
  • Su universidad asociada (instalación) se puede eliminar si no hay otro estudio se refiere a esta universidad.
  • Sus prácticas asociadas se pueden eliminar. La empresa solo puede ser eliminada si no se refiere a ninguna otra pasantía.

estoy totalmente seguro de si puedo añadir :dependent => :destroy sólo después has_one y has_many o también después de belongs_to.


Editar: Para simplificar el problema, siga la implementación de ejemplo siguiente (reducida).

class Study < ActiveRecord::Base 
    belongs_to :subject 
    accepts_nested_attributes_for :subject, :allow_destroy => true 
end 

class Subject < ActiveRecord::Base 
    has_many :studies, :dependent => :destroy 
end 

En mi opinión proporciono el siguiente enlace.

<%= link_to "Destroy", study, :method => :delete, :confirm => "Are you sure?" %> 

La ruta se basa en las rutas con nombre dadas por una configuración de descanso en routes.rb.

resources :studies 
resources :subjects 

El estudio se eliminará cuando haga clic en el enlace - los temas permanecen intactos. ¿Por qué?

+0

Puede agregar ': dependent =>: destroy' a todos los tres – lebreeze

+0

¿Podría indicar dónde exactamente ponerlo? – JJD

Respuesta

1

Puede agregar :dependent => :destroy a las tres, pero no estoy seguro si eso le dará suficiente poder para hacer las verificaciones necesarias antes de determinar si un objeto asociado debe ser destruido.

Tiene algunas opciones.

Agregue una devolución de llamada before_destroy en cada modelo que genera una excepción o detiene la eliminación.

class Facility < ActiveRecord::Base 
    has_many :internships 
    has_many :locations 
    has_many :studies 

    def before_destroy 
    raise SomethingException if internships.any? || ... 
    # or 
    errors.add(... 
    end 
end 

o lo hacen en silencio anulando destruir

class Facility < ActiveRecord::Base 
    has_many :internships 
    has_many :locations 
    has_many :studies 

    def destroy 
    return false if internships.any || ... 
    super 
    end 
end 

Nota: Esto es básicamente significaba sólo una guía y puede no ser la forma correcta de anular destruir etc ...

+0

Los controles no son el problema principal. 'before_destroy' puede encargarse de eso. - Pero intenta destruir, por ejemplo, un sujeto en el escenario de prácticas. ¿Dónde tengo que poner ': dependent =>: destroy' ..? – JJD

+0

Quiero decir que probablemente no usarías ': dependent =>: destroy' en absoluto en este escenario. Solo si siempre desea que se destruyan los objetos asociados en lugar de si desea que se destruyan condicionalmente. Entonces usaría las devoluciones de llamada 'before_destroy' en su lugar. – lebreeze

+0

Pensé que siempre que 'before_destroy' devuelva' false' para un objeto/modelo específico, el proceso de eliminación continuará. ¿Cree que es posible? – JJD

2

Creo que sus relaciones son las equivocadas aquí ...
El accepts_nested_attributes_for debe declararse en el modelo que has_many para el modelo que lo has_many de. Además, en su ejemplo, destruir el sujeto impondría dependent_destroy en muchos studies, y no al revés.

Cuestiones relacionadas