Reputation: 382
Let's say we have the following scenario in a Rails application:
Users
have many Websites
, and Websites
have many Simulations
(likewise, Websites
belong to Users
, and Simulations
belong to Websites
).
Now the problem is, how do I display a list of all of a User's Simulations on the User Show page?
My first gut attempt was to define the following in the Users Controller
:
def show
@user = User.find(params[:id])
@websites = @user.websites
@simulations = @user.websites.simulations
end
And then use <%= render @simulations %>
in the Users Show Page
, but that gives a NoMethodError
: undefined method
simulations' for []:Array` when I visit localhost:3000.
So how can I create a variable in my User Controller
that holds all the Simulations
that belong to the Websites
that belong to a particular User
?
Any and all help is greatly appreciated!
Upvotes: 1
Views: 161
Reputation: 3330
You asked for it - I don't know about ruby, but each website in @websites should already contain a field that has a simulation.
This is what you're doing.
1 - You take user, a single object, and get its websites. Cool. User looks something like this (in pseudocode):
Object @user
{
Array[] websites = [(Website)site1, (Website)site2];
}
Alright, that's cool. So user.websites
should return an array of websites.
2 - You try to get the simulations from a website. A website probably looks like this:
Object @website
{
Array[] simulations = [(Simulation)sim1, (Simulation)sim2];
}
Hm, why doesn't it work? Well lets break down what you're doing:
@user.websites.simulations
You're taking websites
, which is an array, and trying to reference a variable that belongs to a website
type and not an array
type. @user.websites
is an array object that holds websites, not a website itself. What you want is to get @website.simulations
, not websites.simulations
.
So the first step is getting a website. That's easy - one way would be to try to fetch a website from your website array in the user.
@User.websites[0] <-- may not be syntactically correct; I don't know ruby.
Now if you want to get all of the websites, iterate through them using a loop and push them to a new array. Again in pseudocode:
@all_simulations = new Array();
for(@i=0;@i<count(@user.websites);@i++) //first loop through the websites
{
for(@q=0;@q<count(@user.websites[@i].simulations);@q++) //then loop through the simulations
{
@all_simulations.push(@user.websites[@i].simulations[@q]); //push the simulation into @all_websites
}
}
What we do here is we go into each website in the user.websites
array and then grab each simulation from that website and throw that into our @all_simulations
variable. If you understand the concept, you should be able to convert this logic into valid ruby.
Upvotes: 0
Reputation: 15788
class User < ActiveRecord::Base
has_many :websites
has_many :simulations, :through => :websites
end
now you can use @simulations = @user.simulations
and get all the user's simulations
Upvotes: 2
Reputation: 16730
In your user model add this method. This will produce 2 queries but still better then joining simulations in ruby code.
def websites_simulations
Simulation.where(website_id: website_ids)
end
Upvotes: 0