active_sms

Easily send sms using various sms backends!


Keywords
ruby, sms, sms-api, sms-backend, sms-service
License
MIT
Install
gem install active_sms -v 0.2.1

Documentation

AnySMS

Build Status Gem Version

Simple and flexible solution to send sms in ruby, supporting variety of sms services.

Installation and usage

Add this line to your application's Gemfile:

gem "any_sms", "~> 0.4.0"

Then somewhere in your initialization code:

require "any_sms"
require "logger"

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

  config.default_backend = :my_backend_name
end

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

phone = "+10000000000"
text = "My sms text"

# Should print to console [SMS] +10000000000: text
AnySMS.send_sms(phone, 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 AnySMS::Backend::Logger which actually just print sms contents to console. To actually send sms you need gem-provider or your own simple class.

Here's a list of my implementations for some sms services.

Gem name Sms service name
any_sms-backend-aws Amazon Web Services SNS
any_sms-backend-smsru (russian) sms.ru

These gems documentation should be self explanatory.

Writing your own sms backend

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

require "any_sms"

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

    # (you may also use keyword arguments instead)
    @token = params.delete(:token)
  end

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

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

    # any other than :success response considered as failure
    respond_with_status :not_enough_funds

    # optionally you may return some metadata
    respond_with_status :success, meta: { funds_left: 42 }
  end
end

Then in initializer:

require "any_sms"
require_relative "mycustombackend"

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

  c.default_backend = :my_custom_backend
end

Usage:

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

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

# (optionally) Read metadata if any.
# Not recommended for control flow.
result.meta

Multiple backends

You can specify which backend to use per call:

require "any_sms"
require_relative "mycustombackend"

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

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

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

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

# Uses backend you specify
AnySMS.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:

require "any_sms"
require_relative "mycustombackend"
require_relative "mycustombackend2"

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

   # You can also, for example, 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,
                       AnySMS::Backend::Logger,
                       logger: logger,
                       severity: :info
  end

  if test?
    # Null sender does nothing when called for sending sms
    c.register_backend :my_custom_backend,  AnySMS::Backend::NullSender
    c.register_backend :my_custom_backend2, AnySMS::Backend::NullSender
  end

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

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

  c.default_backend = :my_custom_backend
end

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

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

# Uses backend you specify
AnySMS.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?, test? and production? are not real methods. You have to detect environment yourself somehow.

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 AnySMS.send_sms and check it was executed.

Contributing

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

Submitting a Pull Request

  1. Fork the official repository.
  2. Create a feature/bugfix branch.
  3. Implement your feature or bug fix.
  4. Add, commit, and push your changes.
  5. Submit a pull request.
  • Please add tests if you changed code. Contributions without tests won't be accepted.
  • If you don't know how to add tests, please put in a PR and leave a comment asking for help.
  • Please don't update the Gem version.

( Inspired by https://github.com/thoughtbot/factory_girl/blob/master/CONTRIBUTING.md )

License

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