Pregunta

Nuevo para Ruby y Rails, pero ahora estoy educado en libros (lo que aparentemente no significa nada, jaja).

Tengo dos modelos, Evento y Usuario unidos a través de una tabla EventUser

class User < ActiveRecord::Base
  has_many :event_users
  has_many :events, :through => :event_users
end

class EventUser < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

  #For clarity's sake, EventUser also has a boolean column "active", among others
end

class Event < ActiveRecord::Base
  has_many :event_users
  has_many :users, :through => :event_users
end

Este proyecto es un calendario, en el que tengo que hacer un seguimiento de las personas que se registran y tachan su nombre para un evento determinado. Pienso que muchos a muchos es un buen enfoque, pero no puedo hacer algo como esto:

u = User.find :first
active_events = u.events.find_by_active(true)

Debido a que los eventos en realidad NO TIENEN esos datos adicionales, el modelo EventUser sí lo tiene. Y mientras pude hacerlo:

u = User.find :first
active_events = []
u.event_users.find_by_active(true).do |eu|
  active_events << eu.event
end

Esto parece ser contrario a " la manera de los carriles " ;. ¿Alguien me puede iluminar, esto me ha estado molestando durante mucho tiempo esta noche (esta mañana)?

¿Fue útil?

Solución

¿Qué te parece agregar algo como esto a tu modelo de usuario?

has_many  :active_events, :through => :event_users, 
          :class_name => "Event", 
          :source => :event, 
          :conditions => ['event_users.active = ?',true]

Después de eso, deberías poder obtener eventos activos para un usuario simplemente llamando:

User.first.active_events

Otros consejos

Milan Novota tiene una buena solución, pero : condition ahora está en desuso y el : condition = > ['event_users.active =?', true] simplemente no parece ser una barandilla. Prefiero algo como esto:

has_many :event_users
has_many :active_event_users, -> { where active: true }, class_name: 'EventUser'
has_many :active_events, :through => :active_event_users, class_name: 'Event', :source => :event

Después de eso, aún debería poder obtener eventos activos para un usuario simplemente llamando:

User.first.active_events

A pesar de que u.events no está explícitamente llamando a la tabla user_events, esa tabla aún se incluye en el SQL implícitamente debido a las combinaciones necesarias. Por lo tanto, aún puedes usar esa tabla en tus condiciones de búsqueda:

u.events.find(:all, :conditions => ["user_events.active = ?", true])

Por supuesto, si planeas hacer esta búsqueda mucho, entonces seguro, dale una asociación separada como sugiere Milan Novota, pero no hay requisito para que lo hagas de esa manera

Bueno, se pone más responsabilidad en el modelo Usuario de lo que realmente se necesita, y no hay una buena razón para hacerlo.

Primero podemos definir el alcance en el modelo EventUser porque donde realmente pertenece, como:

class EventUser < ActiveRecord::Base
  belongs_to :event
  belongs_to :user

  scope :active,   -> { where(active: true)  }
  scope :inactive, -> { where(active: false) } 
end

Ahora, un usuario podría tener ambos tipos de eventos: eventos activos y eventos inactivos, por lo que podemos definir la relación en el modelo Usuario de la siguiente manera:

class User < ActiveRecord::Base
  has_many :active_event_users,   -> { active },   class_name: "EventUser"
  has_many :inactive_event_users, -> { inactive }, class_name: "EventUser"

  has_many :inactive_events, through: :inactive_event_user,
                             class_name: "Event",
                             source: :event
  has_many :active_events,   through: :active_event_users,
                             class_name: "Event",
                             source: :event
end

La belleza de esta técnica es que la funcionalidad de ser un evento activo o inactivo pertenece al modelo EventUser , y si en el futuro la funcionalidad necesita ser modificada, se modificaría solo en uno Coloque: EventUser , y los cambios se reflejarán en todos los demás modelos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top