The error you're getting is due to overriding initialize
on ApplicationController without calling super
as follows:
require "date"
module BeforeOrAfter
attr_accessor :past
attr_accessor :future
def initialize(*args)
@future = []
@past = []
super
end
def before_or_after(event)
if event < DateTime.now
@past << event.id
else
@future << event.id
end
end
end
On the other hand, after clarifying your question, it looks like this is entirely unnecessary. You have an Enumerable (e.g. an array) of objects representing events and you just want to split them into past and future events. The Enumerable#partition method is ideal for this purpose: it takes a block and splits the input into two arrays, one with all the items which match the condition and another with all the items that do not. So, my recommendation is:
- Delete the module you were attempting to include
- Add partition code to the controller where you need to split the events.
Assuming your array is called events
and contains ActiveRecord-like objects with a time
field:
(@past, @future) = events.partition { |event| event.time < Time.current }
And that's it! You now have @past
and @future
available in your view. If the events really are ActiveRecord models you could take it a step further and add this to the Event
class:
def past?
self.time < Time.current
end
And then change your controller as follows:
(@past, @future) = events.partition(&:past?)
# equivalent to the following:
# (@past, @future) = events.partition { |event| event.past? }
If you need to do this across a range of controllers and want to encapsulate the functionality you don't need a separate module, just define a function in your ApplicationController to be called by each controller.
# application_controller.rb
def prepare_events(events)
(@past, @future) = events.partition { |event| event.time < Time.current }
events
end
# widgets_controller.rb
def index
@widgets = Widget.all
prepare_events(@widgets)
end
If you always populate the same instance variable regardless of your collection's contents you can even make it an after_filter in the application controller:
after_filter :prepare_events
def prepare_events
(@past, @future) = @resources.partition { |event| event.time < Time.current }
true
end
To make it possible to add events multiple times you would need to join the arrays. The simplest way would be to add them and split them again.
# application_controller.rb
def prepare_events(events)
events = events + @past + @future if @past
(@past, @future) = events.uniq.partition { |event| event.time < Time.current }
true
end