ActiveSMS

Build Status Gem Version

Unified way to send SMS in ruby! Allows you to switch SMS services without having to rewrite any code that actually sends SMS. Supports multiple backends. Sending SMS is not pain anymore!

Installation and usage

Add this line to your application's Gemfile:

gem "active_sms"

Then somewhere in your initialization code:

ActiveSMS.configure do |config|
  c.register_backend :my_backend_name,
                     ActiveSMS::Backend::Logger,
                     logger: Logger.new(STDOUT),
                     severity: :info

  c.default_backend = :my_backend_name
end

Now, whenever you need to send SMS, just do:

phone = "799999999"
text = "My sms text"

# Should print to console [SMS] 79999999999: text
ActiveSMS.send_sms("79999999999", "text")

Now your code is capable of sending sms. Later you may add any sms-backend you want, or even write your own.

Adding real sms backend

If you followed steps above, you code still doesn't really send sms. It uses ActiveSMS::Backend::NullSender which actually does nothing when called. To actually send sms you need to pick gem-provider or write your own simple class.

At this moment i made ready to use implementation for only one service:

Gem name Sms service name
active_sms-backend-smsru sms-ru

The gem documentation should be self explanatory.

Writing your own sms backend

Here's simple class that can be used by ActiveSMS:

require "active_sms"

class ActiveSMS::Backend::MyCustomBackend < ActiveSMS::Backend::Base
  def initialize(params = {})
    # your initialization which parses params if needed.
    # the params here is the ones you set in initializer

    @token = params.delete(:token)
  end

  def send_sms(phone, sms_text)
    # your code to call your sms service
    # or somehow send actual sms

    # if everything went fine, you may use helper from base class:
    respond_with_status :success

    # Or if you want to return failed status code:
    respond_with_status :not_enough_funds
  end
end

Then in initializer:

ActiveSMS.configure do |c|
  c.register_backend :my_custom_backend,
                     ActiveSMS::Backend::MyCustomBackend,
                     token: ENV["token"]

  c.default_backend = :my_custom_backend
end

Usage:

# somewhere in your code
result = ActiveSMS.send_sms(phone, text)

if result.success?
  # do stuff
else
  # request failed
  fail_status = result.status
  # :not_enough_funds for example
end

Multiple backends

You can specify which backend to use per call:

ActiveSMS.configure do |c|
  c.register_backend :my_custom_backend,
                     ActiveSMS::Backend::MyCustomBackend,
                     token: ENV["token"]

  c.register_backend :null_sender, ActiveSMS::Backend::NullSender
  c.default_backend = :my_custom_backend
end

phone = "799999999"
text = "My sms text"

# Uses default backend
ActiveSMS.send_sms(phone, text)

# Uses backend you specify
ActiveSMS.send_sms(phone, text, backend: :null_sender)

Real life example

If you develop application in group, you probably don't want them all to send real SMS, and instead you would prefer to emulate sending, including SMS text preview (like SMS codes for registration).

However, on production you want to actually send them using your service. Here's how you can achieve that:

ActiveSMS.configure do |c|
  if development?
    c.register_backend :my_custom_backend,
                       ActiveSMS::Backend::Logger,
                       logger: Logger.new(STDOUT),
                       severity: :info

   # You can also specify different formatter for second one
   logger = Logger.new(STDOUT)
   logger.formatter = proc do |severity, datetime, progname, msg|
     "[MYBackend2]: #{msg}\n"
   end

    c.register_backend :my_custom_backend2,
                       ActiveSMS::Backend::Logger,
                       logger: logger,
                       severity: :info
  end

  if test?
    c.register_backend :my_custom_backend,  ActiveSMS::Backend::NullSender
    c.register_backend :my_custom_backend2, ActiveSMS::Backend::NullSender
  end

  if production?
    c.register_backend :my_custom_backend,
                       ActiveSMS::Backend::MyCustomBackend,
                       token: ENV["token"]

    c.register_backend :my_custom_backend2,
                       ActiveSMS::Backend::MyCustomBackend2,
                       token: ENV["token2"]
  end

  c.default_backend = :my_custom_backend
end

phone = "799999999"
text = "My sms text"

# Uses default backend
ActiveSMS.send_sms(phone, text)

# Uses backend you specify
ActiveSMS.send_sms(phone, text, backend: :my_custom_backend2)

# depending on your initializer it may use different backends (like in this example)
# in different environments.

Of course development? and production? is not real methods. You have to detect environment yourself.

While possible, i strongly discourage to use more than two backends (One default, another is required in certain situations for some reason). It may make your code mess ;)

Testing

I am planning to make rspec matcher to test if sms was sent. For now you may just mock ActiveSMS.send_sms and check it was executed.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Fedcomp/active_sms

License

The gem is available as open source under the terms of the MIT License.