
Security News
Scaling Socket from Zero to 10,000+ Organizations
Socket CEO Feross Aboukhadijeh shares lessons from scaling a developer security startup to 10,000+ organizations in this founder interview.
pk-merb_messenger
Advanced tools
A plugin for the Merb framework that provides messaging and notifications functionality.
The goal is to create a simple transport agnostic library that can be used for Jabber, Growl, HTTP, mail and other notifications with minimal effort in web controllers.
Core actors of this library are messaging controllers and transports. Messaging controllers are called from web controllers that handle incoming requests, render message templates, do messaging-related filtering and pass the result to transports to deliver.
Note that messaging controllers share rendering and filtering code with Merb core's AbstractController so no wheel is invented.
What transports do is up to specific implementation:
Messaging controllers are used from web controllers (that handle requests) and can render templates, have filters and all that. Transports can be used directly in models and not supposed to render (at least at this point in evolution of merb messenger).
Transports must be required explicitly at this point. Do it in init.rb or add config/messengers.rb and load it from init.rb, and require transport file there. This is because otherwise lazy loading can only be accomplished using Kernel#autoload which some people do not like (for instance, it is not thread safe in MRI).
Say we have a group journal/blog and we want to be notified on updates using Jabber. Our web controller action may look like this:
class Entries < Application def create(entry) @entry = Entry.new(entry) if @entry.save run_later do JournalMessenger.dispatch(:create, self, :entry => @entry) end redirect url(:entries) else @entries = Entry.all render :index end end end
As you can see, messaging controller is explicitly called from web controller using dispatch method. That method takes an action as a symbol, web controller instance (to have access to request parameters and session) and a Hash of extra options you'd like to pass to it.
Now lets look at our messenger:
class JournalMessenger < Merb::MessagingController delivery_options :lan_growl, :notification => "journal notification", :title => "New journal entry posted"
delivery_options :remote, :title => "New journal entry posted", :to => ["app.notifications@jabber.org"], :message_type => :chat
def create(options) # render the template in app/messengers/views/journal/create.text.erb body = render(:index)
# deliver using XMPP
# transport is called :remote
# in the application
deliver :remote, :body => body
# deliver using Growl transport
# that is called :lan_growl across
# the app
deliver :lan_growl, :body => body
end end
Every messenger action takes a hash of options that includes web controller parameters and additional options you passed on dispatch.
Every messenger uses +deliver+ method to deliver notifications instantly and (in the future) +queue+ method to stack a notification in a queue to be delivered later. Queueing functionality will be 100% ORM agnostic.
This plugin is all about connecting your web controllers and transports. It supposed to be generic. Because message transports are very different, it's up to particular transport what options delivery and queue methods would take.
To eliminate the need to constantly duplicate some common options (like "from", "title" and similar), Merb messenger lets you set them up messenger-wide:
delivery_options :remote, :title => "Journal event", :to => ["app.notifications@jabber.org"], :message_type => :chat
Above we say that all messages that go via transport called "remote" (that is XMPP transport in this example) use title "Journal event", delivered to "app.notifications@jabber.org" and use message type "chat".
+deliver+ method's options are merged with class-wide delivery options before they are passed on to transport. Obviously, former take precedence over the latter.
Transport API is simple and may be as little work as implementing a single method, deliver. Some transports that need to establish connection and handle disconnection may add a few more methods: connect, reconnect, disconnect. Those providing queuing functionality may add queue method that acts as deliver but does not do immediate delivery.
Here is a Jabber transport implementation that uses xmpp4r: require 'xmpp4r/client'
module Merb module Messenger class Xmpp4rTransport include ::Jabber
class_inheritable_accessor :_default_delivery_options
self._default_delivery_options = Mash.new(:message_type => :chat)
def self.delivery_options(options)
self._default_delivery_options = options
end
attr_reader :transport
def initialize(options)
@transport = Client.new(options[:jid])
@transport.connect
@transport.auth(options[:password])
end
def connect
self.transport.connect
end
def disconnect
self.transport.close
end
def deliver(options = {})
options = _default_delivery_options.merge(options)
m = Message.new(options[:to], options[:body])
m.set_subject(options[:subject]) if options[:subject]
m.set_subject(options[:id]) if options[:id]
m.set_type(options[:message_type] || :normal)
self.transport.send(m)
end
end
end end
Transports are usually set up before Merb loads your application classes, but it's obviously neither a requirement, nor a convention. It just makes messaging classes loaded before code that uses them loads.
To set up a transport you use Merb::Messenger.setup_transport method that takes transport name (can be anything, pick how you'd like to address that transport in your application), transport type alias (:growl, :xmpp4r, can be anything people already written transports for) and a Hash of options.
Since transports are so different by nature (Growl has host, port, password, notifications list and application name options, XMPP usually has jid, server, port, SASL/TLS options and password, smpt transport would have SMTP server settings, sendmail would have a sendmail path, etc), possible options are up to transport authors.
Merb::BootLoader.before_app_loads do Merb::Messenger.setup_transport(:lan_growl, :growl, { :application => "merbpack", :notifications => ["journal_notification"] }) end
You can use transports directly if you need to. For instance, you can set up a Jabber transport that's gonna notify you when Merb worker is shut down or restarted. This way you can be notified on crashes and application deployments.
Here is an example:
Merb::BootLoader.after_app_loads do im = Merb::MessagingController.message_transport :lan_growl
im.deliver({ :title => "MerbPack presence", :body => "MerbPack agent is back online", :notification => "presence notification" }) end
Merb::BootLoader.before_master_shutdown do Merb.logger.info "MerbPack agent is going offline..." im = Merb::MessagingController.message_transport :lan_growl
im.deliver({ :title => "MerbPack presence", :body => "MerbPack agent is about to shut down", :notification => "presence notification" }) end
Merb::BootLoader.before_worker_shutdown do Merb.logger.info "Shutting down worker..."
Merb::MessagingController.message_transport(:remote).disconnect end
Here we use two transports named :lan_growl and :remote. First uses Growl transport in local area network, and second is a Jabber transport that sends XMPP notifications.
We use them to notify people when application goes down and comes back up online.
Merb messenger will be part of Merb 1.1 in early 2009. The Holy Grails of this plugin is to provide simple generic interface for messaging of all kinds: from Jabber and mail notifications to talking to AMQP brokers like RabbitMQ or ZeroMQ, doing "web hooks" and so forth.
FAQs
Unknown package
We found that pk-merb_messenger demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh shares lessons from scaling a developer security startup to 10,000+ organizations in this founder interview.

Research
Socket Threat Research maps a rare inside look at OtterCookie’s npm-Vercel-GitHub chain, adding 197 malicious packages and evidence of North Korean operators.

Research
Socket researchers identified a malicious Chrome extension that manipulates Raydium swaps to inject an undisclosed SOL transfer, quietly routing fees to an attacker wallet.