ROR:使用.each从多个表中选择

时间:2010-12-10 23:27:46

标签: ruby-on-rails

我有三个表:users,events和user_events,然后我在控制器中执行以下操作:

    @temp = UserEvent.where(['user_id = ?', session[:uid]]).all
    @temp.each do |t|
        @event_names = Event.where(['id = ?', t.event_id]).all
    end

但它最终只保存最后一个匹配的事件。我哪里做错了?

3 个答案:

答案 0 :(得分:3)

首先,短期解决方案:

@event_names = UserEvent.where(['user_id = ?', session[:uid]]).all.map do |t|
  Event.where(['id = ?', t.event_id]).all
end.flatten

现在,长期解决方案:

@user = User.find(params[:id])
@user.events

要实现上述目标,您必须做两件事:

  1. 正确设置关联。看起来您需要has_many :through association

    class User
      has_many :user_events
      has_many :events, :through => :user_events
    end
    
    
    class UserEvent
      belongs_to :user
      belongs_to :event 
    end
    
    
    class Event
      has_many :user_events
      has_many :users, :through => :user_events
    end
    
  2. config/routes.rb中设置nested resource routes

    resources :users do
      resources :events
    end
    
  3. 我强烈建议您考虑一下长期解决方案。如果您采用短期解决方案,那么您将失去rails提供的许多好处!

答案 1 :(得分:0)

做一张地图,而不是每张地图:

@event_names = @temp.map do |t|
   Event.where(:id => t.event_id).all
end

但@bowsersenior是对的:使用适当的关系让rails做正确的事。效率也更高,因为它只会执行2次查询而不是N + 1。

class UserEvent < ActiveRecord::Base
  belongs_to :user
  belongs_to :event
end

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

@events = User.find(session[:uid]).events
@event_names = @events.map(&:name) # for example

答案 2 :(得分:0)

出了什么问题?

@temp.each do |t|
  @event_names = Event.where(['id = ?', t.event_id]).all # will reassign @event_name each time
end

每次循环时都会重新分配变量@event_names,因此@event_names将保留的唯一值来自最后一次循环。

你应该做什么:

@temp.each do |t|
  @event_names.push(Event.where(['id = ?', t.event_id]).all) or
end    

另外,正如其他人所指出的,这并不是最好/最好的方法。