开发者

ROR: select from multiplt tables with .each do

I have three tables: users, events, and user_events, then I do the following in controlle开发者_开发技巧r:

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

but it ends up only save the last matched event. Where did I do wrong?


First, the short-term solution:

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

Now, the long-term solution:

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

To get the above to work, you have to do 2 things:

  1. set up your associations correctly. It looks like you need a 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. set up nested resource routes in config/routes.rb:

    resources :users do
      resources :events
    end
    

I strongly urge you to look at the long-term solution. If you go with the short-term solution, you are missing much of the benefits that rails has to offer!


Do a map, instead of each:

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

But @bowsersenior is right: use the proper relations to let rails do the right thing. Is more efficient too, because it will do only 2 queries instead of 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


What went wrong?

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

You are reassigning the variable @event_names each time you go through the loop and hence the only values that @event_names will hold are from the final pass through that loop.

What you should have done:

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

Also, as noted by others, this is not really the best/good way to do this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜