Ruby/Rails - Add records to an object with each lo

2019-04-17 11:28发布

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?

5条回答
叛逆
2楼-- · 2019-04-17 12:12
@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
查看更多
别忘想泡老子
3楼-- · 2019-04-17 12:12

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#<<.

查看更多
干净又极端
4楼-- · 2019-04-17 12:17
  1. In JavaScript, there is an Object that stores key-value pairs (similar to a Hash in Ruby) and there is an Array (which stores an ordered set of values). In JavaScript, Arrays (as with all objects) can have arbitrary properties added at any time. This causes some confusion between Object and Array in JavaScript. In Ruby, this is not the case.

    • In Ruby, Object is the base class from which all other objects inherit. You can read the documentation for Object here.
    • In Ruby, Array is a class for storing an ordered list of values. You can read the documentation for Array here.
    • In Ruby, just about everything is an "object", insofar as it has methods.
       

    Instead of "Object", though, I think perhaps you mean "instance variable". Instance variables are prefixed with an 'at' sign, e.g. @foo. Variables are not themselves objects, nor do they contain objects; rather, they point to (or reference) objects. The objects that they reference may be of many different types.

  2. @Justice has shown you one way to add items to an array inside a loop.

  3. If you have an instance variable that is an array, you can iterate over its values inside the view. The syntax for this depends on what template system you are using (Erb, Haml, etc.)

查看更多
贪生不怕死
5楼-- · 2019-04-17 12:20

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.

查看更多
地球回转人心会变
6楼-- · 2019-04-17 12:22

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))
查看更多
登录 后发表回答