Pergunta

Novo para Ruby e Rails, mas estou livro educado por agora (que, aparentemente, não significa nada, haha).

Eu tenho dois modelos, eventos e usuário se juntou através de uma tabela 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 projeto é um calendário, no qual eu tenho que manter o controle de pessoas se inscrever e arranhando seu nome para um determinado evento. Eu acho que a muitos para muitos é uma boa abordagem, mas eu não posso fazer algo como isto:

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

Como os eventos não têm realmente que os dados extras, o modelo EventUser faz. E enquanto eu poderia fazer:

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

Este parece ser contrário à "o caminho trilhos". Alguém pode me esclarecer, este foi me incomodando há muito esta noite (esta manhã) tempo?

Foi útil?

Solução

Como sobre a adição de algo como isto em seu modelo de usuário?

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

Depois que você deve ser capaz de obter eventos ativos para um usuário apenas chamando:

User.first.active_events

Outras dicas

Milão Novota tem uma boa solução - mas :conditions agora está obsoleto e o :conditions => ['event_users.active = ?',true] mordeu simplesmente não parece muito trilhos de qualquer maneira. Eu prefiro algo como isto:

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

Depois que você ainda deve ser capaz de obter eventos ativos para um usuário apenas chamando:

User.first.active_events

Mesmo que seus u.events não é explicitamente de chamar a mesa de user_events, que a tabela está ainda incluído no SQL implicitamente por causa da necessária junta. Então, você ainda pode usar essa tabela em suas condições de encontrar:

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

Claro que, se você pretende fazer essa pesquisa muito, então a certeza, dar-lhe uma associação separada, como Milan Novota sugere, mas não há nenhuma exigência para você fazer isso dessa maneira

Bem, mais responsabilidade está sendo colocado no modelo User do que realmente necessário, e não há nenhuma boa razão para fazê-lo.

Podemos primeiro definir o escopo no modelo EventUser porque onde ele realmente pertence, como:

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

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

Agora, um usuário pode ter ambos os tipos de eventos: eventos ativos, bem como eventos inativos, assim podemos definir a relação no modelo User da seguinte forma:

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

A beleza desta técnica é que a funcionalidade de ser um ativo ou um evento inativa pertence a modelo EventUser, e se, no futuro, a funcionalidade tem de ser modificado, seria modificado apenas em um lugar: Modelo EventUser, eo alterações serão refletidas em todos os outros modelos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top