Question

Nouveau pour Ruby et Rails, mais je suis un livre déjà éduqué (ce qui ne veut apparemment rien dire, haha).

J'ai deux modèles, Event et User joints via une table 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

Ce projet est un calendrier dans lequel je dois garder une trace des personnes qui s'inscrivent et qui grattent leur nom pour un événement donné. Je pense que plusieurs à plusieurs est une bonne approche, mais je ne peux pas faire quelque chose comme ça:

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

Etant donné que les événements ne possèdent PAS ces données supplémentaires, c'est le modèle EventUser. Et pendant que je pouvais faire:

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

Cela semble être contraire à "the rails way". Quelqu'un peut-il m'éclairer, cela me dérange depuis longtemps ce soir (ce matin)?

Était-ce utile?

La solution

Pourquoi ne pas ajouter quelque chose comme cela dans votre modèle d'utilisateur?

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

Ensuite, vous devriez pouvoir obtenir des événements actifs pour un utilisateur en appelant simplement:

User.first.active_events

Autres conseils

Milan Novota a une bonne solution - mais : conditions est maintenant obsolète et le : conditions = > Le bit ['event_users.active =?', true] ne semble tout simplement pas très gai. Je préfère quelque chose comme ça:

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

Après cela, vous devriez toujours pouvoir obtenir des événements actifs pour un utilisateur simplement en appelant:

User.first.active_events

Même si votre u.events n'appelle pas explicitement la table user_events, cette table est toujours incluse dans le SQL implicitement en raison des jointures nécessaires. Vous pouvez donc toujours utiliser cette table dans vos conditions de recherche:

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

Bien sûr, si vous envisagez de faire souvent cette recherche, assurez-vous de lui associer une association distincte, comme le suggère Milan Novota. >

Dans le modèle Utilisateur , le domaine de responsabilité est plus important que nécessaire, et il n'y a aucune bonne raison de le faire.

Nous pouvons d’abord définir l’étendue dans le modèle EventUser car son emplacement réel, comme:

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

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

À présent, un utilisateur peut avoir les deux types d'événements: les événements actifs et les événements inactifs, afin que nous puissions définir la relation dans le modèle Utilisateur comme suit:

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 beauté de cette technique réside dans le fait que la fonctionnalité d’événement actif ou inactif appartient au modèle EventUser , et si à l’avenir la fonctionnalité doit être modifiée, elle ne sera modifiée que dans un seul cas. place: EventUser , et les modifications seront répercutées dans tous les autres modèles.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top