Access parent object instance variable

Hi there,

I have a class which looks like this:

class EventRoster{
@events = []
@event_occurrences = []
}

@events is an array of Event which contains various information about a
financial event on a calendar (title, amount, date etc). This ‘event’
may repeat (weekly for example) but I don’t want to make a copy of the
entire event with a new date for every single instance. (This calendar
could span 20 years)

I have thus created @event_occurrences which is an array of objects that
simply hold their ‘parent’ Event#object_id and a date.

I want to be able to loop over all the event_occurrences and access the
data of the parent event. At the moment I’m doing this via something
like:

ObjectSpace._id2ref(@parent_event_object_id).title

but this is sometimes returning RangeError(xxx is a recycled object).
Assumedly the parent objects are being garbage collected.

Does anybody have any suggestions on how this could be done correctly?

On Jan 30, 12:51am, “Ellicks M.” [email protected] wrote:

I want to be able to loop over all the event_occurrences and access the
data of the parent event. At the moment I’m doing this via something
like:

ObjectSpace._id2ref(@parent_event_object_id).title

but this is sometimes returning RangeError(xxx is a recycled object).
Assumedly the parent objects are being garbage collected.

Does anybody have any suggestions on how this could be done correctly?

Why could events not have an array of the dates on which they occur
(or indeed, why do occurrences need to exist ahead of time - it seems
that Event could have a method that given a range of dates computes
all the occurrences for that range)

Fred

First off…this isn’t valid ruby.

class EventRoster{
@events = []
@event_occurrences = []
}

try
class EventRoster
def initialize
@events = []
@event_occurrences = []
end
end

Frederick C. wrote in post #978493:

On Jan 30, 12:51am, “Ellicks M.” [email protected] wrote:

I want to be able to loop over all the event_occurrences and access the
data of the parent event. At the moment I’m doing this via something
like:

ObjectSpace._id2ref(@parent_event_object_id).title

but this is sometimes returning RangeError(xxx is a recycled object).
Assumedly the parent objects are being garbage collected.

Does anybody have any suggestions on how this could be done correctly?

Why could events not have an array of the dates on which they occur
(or indeed, why do occurrences need to exist ahead of time - it seems
that Event could have a method that given a range of dates computes
all the occurrences for that range)

Fred

Hi Fred,

Mainly speed/performance but these ‘events’ are looped through all over
the show. I think it’d be impractical to write a method for each unique
set of criteria:

er = get_eventroster
the_date = “2010-12-31”.to_date

er.allevents.select{|e| e.calendar_id == 20135 && e.amount >= 500.0 &&
e.calendar_date == the_date}.each{|e| balance += e.amount}

is far more flexible than, say:

er.get_events_by_calendar_id_and_amount_greater_than_and_date(20135,
500.0, the_date).each{|e| balance += e.amount}

I have already tried something like:

er.allevents.select{|e| e.calendar_id == 20135 && e.amount >= 500.0 &&
e.occurs_on(the_date)}.each{|e| balance += e.amount}

but these events are being looped through in many places throughout my
application and this slowed the creation of a 1-year forecast calendar
from 0.5 seconds (where there was an individual event for every
instance) to 5.5 seconds (where each event held an array of dates
representing its instances) and 50-60 seconds (where the event held a
single date and occurrences where calculated on the fly based on repeat
information)

Using functions to calculate the number of occurrences between two dates
(etc) slows it down but lightens the amount of data stored in session.
The purpose of this challenge was to satisfy both–keep it fast but
don’t repeat all the data that each event contains.

Does anybody know how I could loop through every instance of an event
and call it’s parent events methods?

justinbaker wrote in post #978517:

First off…this isn’t valid ruby.

class EventRoster{
@events = []
@event_occurrences = []
}

try
class EventRoster
def initialize
@events = []
@event_occurrences = []
end
end

Thank you, Justin, for your valued input. Unfortunately, I wasn’t
attempting to provide valid Ruby–I was trying to show ruby-ish
pseudocode that showed a quick overview of the information that was
needed in order to ask my question.

class EventRoster contains about 30 methods for dealing with events, and
far more instance variables. 90% of this code is irrelevant to the
question being asked, so I simply gave an overview.

But again, thank you VERY much for your help. I will remember this in
the future, should I ever accidentally dump code directly into the class
instead of making a constructor.

Peace.

Why do event occurrences not store their parent event rather than the
object_id? Whatever you do ObjectSpace is really best avoided. I’m
still not sure why this is better/more expressive than calculating
them on the fly - you’re clearly able to calculate the occurrences
pragmatically, so I don’t see why calculating them ahead of time would
be less flexible/slower than calculating them on demand (provided you
cache things so that you don’t calculate things repeatedly)

Fred

Fred

Hi Fred,

I thought grabbing an instance of an object was probably a bad idea.

If the event occurrences (RollingEvents as they’re called) actually
store their parent event then they would not be any better than storing
multiple copies of the event itself.

The aim here is to have an array that can be selected from and iterated
over without having to store the same data x number of times. A user
may have 200 Events, repeating weekly. They want to get a balance 20
years down the line. That would require 2005220 (or lots of) Events,
yet essentially only 200 different sets of data.

Example:

Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-04-16”)

repeat_type_id of 2 means this event repeats every repeat_interval weeks
(or 1x7 days). Now, this Event example is not all of an Events data,
but you can see how this is unwanted:

Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-04-23”)
Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-04-30”)
Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-05-06”)
Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-05-13”)
Event(id = 20135, title = “Rent”, amount = “200.0”, repeat_type_id = 2,
repeat_interval = 1, event_type = “E”, exception_count = 0, calendar_id
= 13722, calendar_date = “2010-05-20”)

…and so on

I was hoping to have something like this:

all_events = [RollingEvent(parent_event_object_id = 0x3c55d12, date =
“2010-04-16”),
RollingEvent(parent_event_object_id = 0x3c55d12, date = “2010-04-23”),
RollingEvent(parent_event_object_id = 0x3c55d12, date = “2010-04-30”),
RollingEvent(parent_event_object_id = 0x3c55d12, date = “2010-04-06”),
RollingEvent(parent_event_object_id = 0x3c55d12, date = “2010-04-13”)]

and use:

er.all_events.select{|e| e.calendar_id == 2}.each{ etc etc etc}

Cheers,
Ellicks

P.S. Thank you for your help :slight_smile:

er.allevents.select{|e| e.calendar_id == 20135 && e.amount >= 500.0 &&
e.occurs_on(the_date)}.each{|e| balance += e.amount}
(etc) slows it down but lightens the amount of data stored in session.
The purpose of this challenge was to satisfy both–keep it fast but
don’t repeat all the data that each event contains.

Does anybody know how I could loop through every instance of an event
and call it’s parent events methods?

Why do event occurrences not store their parent event rather than the
object_id? Whatever you do ObjectSpace is really best avoided. I’m
still not sure why this is better/more expressive than calculating
them on the fly - you’re clearly able to calculate the occurrences
pragmatically, so I don’t see why calculating them ahead of time would
be less flexible/slower than calculating them on demand (provided you
cache things so that you don’t calculate things repeatedly)

Fred

Fred

On Jan 30, 10:27pm, “Ellicks M.” [email protected] wrote:

I thought grabbing an instance of an object was probably a bad idea.

If the event occurrences (RollingEvents as they’re called) actually
store their parent event then they would not be any better than storing
multiple copies of the event itself.

Are you under the assumption that

parent = Event.new

rolling_event_one.parent = parent
rolling_event_two.parent = parent
rolling_event_three.parent = parent

creates 3 copies of parents? It doesn’t (unless you’ve written parent=
to store a copy of parent)

Fred

On Jan 31, 12:29am, “Ellicks M.” [email protected] wrote:

So, essentially on creation of a RollingEvent I’d be passing in a
reference to the parent Event?

That is how things work in ruby

Would I have to make a method for every single data member like so:

def amount
@parent_event.amount
end
def title
@parent_event.title
end
end

You could just write @parent_event.amount each time, although there’s
no harm in writing the above (You might also want to read up on
delegation)

Fred

Are you under the assumption that

parent = Event.new

rolling_event_one.parent = parent
rolling_event_two.parent = parent
rolling_event_three.parent = parent

creates 3 copies of parents? It doesn’t (unless you’ve written parent=
to store a copy of parent)

Fred

Hi Fred,

So, essentially on creation of a RollingEvent I’d be passing in a
reference to the parent Event?

Something like:

@events.each |parent_event| do
date = parent_event.start_date
while date <= parent_event.end_date
allevents << RollingEvent.new(parent_event, date)
date += days_between_repeats
end
end

class RollingEvent{
def initialize(parent_event, date)
@parent_event = parent_event
@date = date
end

Would I have to make a method for every single data member like so:

def amount
@parent_event.amount
end
def title
@parent_event.title
end
end

??