The Crystal Programming Language Forum

How to transcend the power of enums to be used with Arrays?

I’ve tried to reduce this as much as possible to explain what I am trying to do, please bear with me (no macros if possible).

enum Notifications
  LeaveJoinChat
  Friend_login
  Friend_logout
  Friend_cg
  Friend_jg
end

class Client
  property notifications = Array(Int8).new
end

p = Client.new

stored_data_from_mysql = "00001"

p.notifications = Array(Int8).new(Notifications.values.size, 0)

# map the mysql string to the Array(Int8)
stored_data_from_mysql.each_char_with_index do |v, i|
  p.notifications[i] = 1 if v == '1'
end

def update_notification(what, value, client)
  test = Notifications.parse(what)
  client.notifications[test.value] = (value ? 1_i8 : 0_i8)
  # EXAMPLE CODE, updating string to mysql
  # db.exec "update users set notifications = ? where user_id = ?", client.notifications.join, client.user_id


rescue e
  pp "Can't update notification: #{e.message}"
end

update_notification("Friend_login", true, p)

pp p.notifications

p.notifications now gets set from the mysql data and mapped to the Array(Int8).

However, I would have to do:

if p.notifications[1] == 1
# okay, I can run friend login block here
end

Which kind of sucks because I’m now using [1] and 1… I want to use my ENUMS!!

Is it possible to do something like this?

if p.notifications.friend_login?
# okay, I can run friend login block here
end

You can convert you numerical ids to enum values using Notifications.from_value(id).

But I want to take advantage of the short syntax form for enum checking!!

Check this out, I think I’m getting closer.

enum NotificationEnum
  LeaveJoinChat
  Friend_login
  Friend_logout
  Friend_cg
  Friend_jg
end

class NotificationClass
  property notifications = Array(Int8).new

  def initialize(@notifications)
  end

  def leavejoinchat?
    notifications[0] == 1
  end

  def friend_login?
    notifications[1] == 1
  end

  def friend_logout?
    notifications[2] == 1
  end

  def friend_cg?
    notifications[3] == 1
  end

  def friend_jg?
    notifications[4] == 1
  end
end

class Client
  property notifications : NotificationClass

  def initialize(new_data)
    @notifications = NotificationClass.new(new_data)
  end
end

p = Client.new (Array(Int8).new(NotificationEnum.values.size, 0))

pp p.notifications.friend_login?

Now, it’s possible to do p.notifications.friend_login? But I don’t know if this is the proper way, however, works for me and the compiler isn’t complaining.

edit: Short syntax form as in method_name? not &. my bad.
edit2: Nevermind, got these confused with the safe navigation operator, short syntax form with rescue, and the short syntax argument… FML
edit3: Looks like this is not enum checking anymore, it’s checking an array.

ROFL :grin::grin::grin::grin::grin:

Hi, it looks to me like you want to model events, not an enumeration.

Event driven programming is a big topic, but I think that’s the spirit of what you’re after. You have the beginnings of an observable (NotificationsClass) and an Observer(Client), and you need a channel between these two things to publish and subscribe to various events.

Check out the link here for a more in-depth discussion of this battle hardened pattern. You’ll probably find that there are a number of areas in your system that can benefit from this programming style.

cheers,
-b

https://www.codementor.io/joshuaudensi/getting-started-event-driven-programming-cvb5mgbzh