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:
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
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.
精彩评论