I'm trying to figure out how to add records to an existing object for each iteration of a loop. I'm having a hard time discovering the difference between an object and an array.
I have this
@events = Event.find(1)
@loops = Choices.find(:all, :limit => 5) #so loop for 5 instances of choice model
for loop in @loops
@events = Event.find(:all,:conditions => ["event.id = ?", loop.event_id ])
end
I'm trying to add a new events to the existing @events object based on the id of whatever the loop variable is. But the ( = ) operator just creates a new instance of the @events object.
I tried ( += ) and ( << ) as operators but got the error
"You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil"
I tried created an array
events = []
events << Event.find(1)
@loops = Choices.find(:all, :limit => 5) #so loop for 5 instances of choice model
for loop in @loops
events << Event.find(:all,:conditions => ["event.id = ?", loop.event_id ])
end
But I dont know how to call that arrays attributes within the view
With objects I was able do create a loop within the view and call all the attributes of that object as well...
<table>
<% for event in @events %>
<tr>
<td><%= link_to event.title, event %></td>
<td><%= event.start_date %></td>
<td><%= event.price %></td>
</tr>
<% end %>
</table>
How could i do this with an array set?
So the questions are
1) Whats the difference between arrays and objects?
2) Is there a way to add into the existing object for each iteration?
3) If I use an array, is there a way to call the attributes for each array record within the view?
@events = []
@events << Event.find(1)
@loops = Choices.find(:all, :limit => 5)
for loop in @loops
es = Event.find(:all, :conditions => ["event.id = ?", loop.event_id])
for e in es
@events << e
end
end
First, take a step back. Let's figure out exactly what you're trying to do.
To me, it seems like: Find all of the events referenced by the first five choices.
If this is all you are trying to do, save yourself some time and queries by writing:
@choices = Choices.limit(5).include(:event)
This assumes there's a has_{one,many}
/belongs_to
association between the two, which there should be, I think. Though the class names are vague enough that I may be missing something.
You can then loop through @choices
and pull out the event
associated with it. Or use something like Enumerable#collect
You can tack on Event.find(1)
to the array this produces by using Array#push or Array#<<.
We have to guess because there is no detailed information about the models and their relations. But Assuming that a choice has_many events I'd do (add an include of events if you care for efficiency):
@events = [Event.find(1)] + Choice.all(:limit => 5).map(&:events).flatten
This should also work even if you don't have Rails associations, though it looks uglier (isn't ActiveRecord's find a bit promiscous on what accepts as arguments?):
@events = Event.find(1, Choice.all(:limit => 5).map(&:event_id))
If you are using Rails 3, you can do this:
loops = [1] + Choice.select("event_id").limit(5).collect {|x| x.event_id}
@events = Event.all(:conditions => ["id in (?)", loops])
This will collect all of the event_id's from choices into an array, appended to the event id 1, that can then be used in the IN clause of the Event.all query. This should be more efficient than looping through your choices and generating queries for each one.