I wrote a basic Eventable module that allows other Classes to create events for itself. All the Models have their own set of events such as a Message
being sent
or a User
having a sign_in
event. I would like to create an array of events as a constant at the class level and access that array inside the module to build helper methods for creating events like so:
class User
EVENT_TYPES = ['sign_in', 'sign_out']
include Eventable
end
class Message
EVENT_TYPES = ['sent', 'opened']
include Eventable
end
module Eventable
extend ActiveSupport::Concern
included do
has_many :events, as: :eventable
attr_accessor :metadata
self::EVENT_TYPES.each do |event_type|
define_method "create_#{event_type}_event" do |args={}|
Event.create(eventable: self, event_type: event_type)
end
end
end
end
The issue with this is: the methods are not being defined properly. It cannot reference the respective Model's constant EVENT_TYPES
properly.
How can I access a class constant from insude a module?
Using constant like that is not very rubyesque, I'd say. This is much more idiomatic (in rails, at least).
class Message
include Eventable
event_types :sent, :opened
end
And here's the implementation
module Eventable
extend ActiveSupport::Concern
module ClassMethods
def event_types(*names)
names.each do |event_type|
define_method "create_#{event_type}_event" do |args={}|
Event.create(eventable: self, event_type: event_type)
end
end
end
end
end
Constants can be obtained by Module#const_get
method. But I would not present the event types for individual classes as constants, but as either class methods or instance variables belonging to the class:
class User
def self.event_types
[:sign_in, :sign_out]
end
end
# or
class User
@event_types = [:sign_in, :sign_out]
class << self
attr_reader :event_types
end
end
It seems that another answer expressed most of the remaining things I wanted to say. But one more thing: I would not name the module Eventable
, but eg. HavingEvents
or simply Events
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With