Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I improve the hierarchy of my event classes?
    primarykey
    data
    text
    <p>For the <a href="https://meta.stackexchange.com/questions/57316/offer-an-xmpp-method-for-chat/63420#63420">XMPP interface for the Stack Overflow chat</a> I am parsing the JSON feed from chat and generating Ruby objects for every chat events, such as messages sent, edits sent, users logging in or out, etc. I also generate events for "slash-commands" sent to the XMPP server, like "/help" or "/auth" in order to allow the XMPP user to authenticate with their Stack Overflow chat account.</p> <p>I have set up these classes in a hierarchy I feel makes good logical sense:</p> <pre><code>class SOChatEvent # base class | |--- class SOXMPPEvent # base for all events that are initiated via XMPP | | | |--- class SOXMPPMessage # messages sent to the XMPP bridge via XMPP | | | | | |--- class SOXMPPMessageToRoom # messages sent from an XMPP user to an XMPP MUC | | | | | |--- class SOXMPPUserCommand # class for "slash commands", that is, messages starting | | | | # with /, used for sending commands to the bridge | | | | | | | |--- class SOXMPPUserHelpCommand | | | |--- class SOXMPPUserLoginCommand | | | |--- class SOXMPPUserBroadcastCommand | |--- class SOChatRoomEvent # base class for all events that originate from an SO chat room | | | |--- class SOChatMessage # messages sent to an SO chat room via the SO chat system | | | | | |--- class SOChatMessageEdit # edits made to a prior SOChatMessage | | | |--- class SOChatUserEvent # events related to SO chat users | | | | | |--- class SOChatUserJoinRoom #Event for when a So user joins a room | | |--- class SOChatUserLeaveRoom #Event for when a So user leaves a room (etc) </code></pre> <p>You can see the full hierarchy and source <a href="http://trac.digitalfruition.com/soxmpp/browser/trunk/classes/SOChatEvents.rb" rel="nofollow noreferrer">in Trac</a> or <a href="https://svn.smart-safe-secure.com/soxmpp/trunk/classes/SOChatEvents.rb" rel="nofollow noreferrer">via SVN</a>.</p> <p>My question is twofold: First, what is the best way to instantiate these events? What I'm currently doing is parsing the JSON events using a giant <code>switch</code> statement --well, it's ruby so it's a <code>case</code> statement -- and, it's not giant <em>yet</em>, but it will be if I continue this way:</p> <pre><code>rooms.each do |room| rid = "r"+"#{room.room_id}" if !data[rid].nil? @last_update = data[rid]['t'] if data[rid]['t'] if data[rid]["e"] data[rid]["e"].each do |e| puts "DEBUG: found an event: #{e.inspect}" case e["event_type"] when 1 event = SOChatMessage.new(room,e['user_name']) event.encoded_body = e['content'] event.server = @server events.push event when 2 event = SOChatMessageEdit.new(room,e['user_name']) event.encoded_body = e['content'] event.server = @server events.push event when 3 user = SOChatUser.new(e['user_id'], e['user_name']) event = SOChatUserJoinRoom.new(room,user) event.server = @server events.push event when 4 user = SOChatUser.new(e['user_id'], e['user_name']) event = SOChatUserLeaveRoom.new(room,user) event.server = @server events.push event end end end end end </code></pre> <p>But I imagine there has to be a better way to handle that! Something like <code>SOChatEvent.createFromJSON( json_data )</code>... But, what's the best way to structure my code so that objects of the proper subclass are created in response to a given <code>event_type</code>?</p> <p>Second, I'm not actually using ant subclasses of <code>SOXMPPUserCommand</code> yet. Right now all commands are just instances of <code>SOXMPPUserCommand</code> itself, and that class has a single <code>execute</code> method which switches based upon regex of the command. Much the same problem -- I know there's a better way, I just am not sure what the best way is:</p> <pre><code>def handle_message(msg) puts "Room \"#{@name}\" handling message: #{msg}" puts "message: from #{msg.from} type #{msg.type} to #{msg.to}: #{msg.body.inspect}" event = nil if msg.body =~ /\/.*/ #puts "DEBUG: Creating a new SOXMPPUserCommand" event = SOXMPPUserCommand.new(msg) else #puts "DEBUG: Creating a new SOXMPPMessageToRoom" event = SOXMPPMessageToRoom.new(msg) end if !event.nil? event.user = get_soxmpp_user_by_jid event.from handle_event event end end </code></pre> <p>and:</p> <pre><code>class SOXMPPUserCommand &lt; SOXMPPMessage def execute case @body when "/help" "Available topics are: help auth /fkey /cookie\n\nFor information on a topic, send: /help &lt;topic&gt;" when "/help auth" "To use this system, you must send your StackOverflow chat cookie and fkey to the system. To do this, use the /fkey and /cookie commands" when "/help /fkey" "Usage: /fkey &lt;fkey&gt;. Displays or sets your fkey, used for authentication. Send '/fkey' alone to display your current fkey, send '/fkey &lt;something&gt;' to set your fkey to &lt;something&gt;. You can obtain your fkey via the URL: javascript:alert(fkey().fkey)" when "/help /cookie" "Usage: /cookie &lt;cookie&gt;. Displays or sets your cookie, used for authentication. Send '/cookie' alone to display your current fkey, send '/cookie &lt;something&gt;' to set your cookie to &lt;something&gt;" when /\/fkey( .*)?/ if $1.nil? "Your fkey is \"#{@user.fkey}\"" else @user.fkey = $1.strip if @user.authenticated? "fkey set to \"#{@user.fkey}\". You are now logged in and can send messages to the chat" else "fkey set to \"#{@user.fkey}\". You must also send your cookie with /cookie before you can chat" end end when /\/cookie( .*)?/ if $1.nil? "Your cookie is: \"#{@user.cookie}\"" else if $1 == " chocolate chip" "You get a chocolate chip cookie!" else @user.cookie = $1.strip if @user.authenticated? "cookie set to \"#{@user.cookie}\". You are now logged in and can send messages to the chat" else "cookie set to \"#{@user.cookie}\". You must also send your fkey with /fkey before you can chat" end end end else "Unknown Command \"#{@body}\"" end end end </code></pre> <p>I know there's a better way to do this, just not sure what specifically it is. Should the responsibility of creating subclasses of <code>SOXMPPUserCommand</code> fall on <code>SOXMPPUserCommand</code> itself? Should all subclasses register with the parent? Do I need a new class?</p> <p>What's the best way to instantiate objects of subclasses in such a hierarchal structure?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload