Module: TwilioContactable::Contactable

Defined in:
lib/contactable.rb

Defined Under Namespace

Classes: Configuration

Constant Summary collapse

Attributes =
[
  :phone_number,
  :formatted_phone_number,
  :sms_blocked,
  :sms_confirmation_code,
  :sms_confirmation_attempted,
  :sms_confirmed_phone_number,
  :voice_blocked,
  :voice_confirmation_code,
  :voice_confirmation_attempted,
  :voice_confirmed_phone_number
]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(model) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/contactable.rb', line 38

def self.included(model)

  # set up the configuration, available within the class object
  # via this same 'twilio_contactable' method
  class << model
    def twilio_contactable(&block)
      @twilio_contactable = Configuration.new(&block) if block
      @twilio_contactable ||= Configuration.new
    end
  end

  # normalize the phone number before it's saved in the database
  # (only for model classes using callbacks a la ActiveModel,
  #  other folks will have to do this by hand)
  if model.respond_to?(:before_save)
    model.before_save :format_phone_number
    model.class_eval do
      def format_phone_number
        self._TC_formatted_phone_number =
          TwilioContactable.internationalize(_TC_phone_number)
      end
    end
  end
end

Instance Method Details

#has_valid_phone_number?Boolean

Returns:

  • (Boolean)


80
81
82
83
# File 'lib/contactable.rb', line 80

def has_valid_phone_number?
  format_phone_number
  _TC_formatted_phone_number =~ /^\+[\d]{10,12}$/
end

#send_sms!(msg, allow_multiple = false) ⇒ Object

Sends one or more TXT messages to the contactable record’s mobile number (if the number has been confirmed). Any messages longer than 160 characters will need to be accompanied by a second argument true to clarify that sending multiple messages is intentional.



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/contactable.rb', line 195

def send_sms!(msg, allow_multiple = false)
  if msg.to_s.size > 160 && !allow_multiple
    raise ArgumentError, "SMS Message is too long. Either specify that you want multiple messages or shorten the string."
  end
  return false if msg.to_s.strip.blank? || _TC_sms_blocked
  return false unless sms_confirmed?

  # split into pieces that fit as individual messages.
  msg.to_s.scan(/.{1,160}/m).map do |text|
    if TwilioContactable::Gateway.deliver_sms(text, _TC_formatted_phone_number).success?
      text.size
    else
      false
    end
  end
end

#send_sms_confirmation!Object

Sends an SMS validation request through the gateway



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/contactable.rb', line 86

def send_sms_confirmation!
  return false if _TC_sms_blocked
  return true  if sms_confirmed?
  return false if _TC_phone_number.blank?

  format_phone_number
  confirmation_code =
    if sms_confirmation_attempted &&
       sms_confirmation_code &&
       sms_confirmation_attempted > Time.now.utc - 60*5
      sms_confirmation_code
    else
      TwilioContactable.generate_confirmation_code
    end

  # Use this class' confirmation_message method if it
  # exists, otherwise use the generic message
  message = (self.class.respond_to?(:confirmation_message) ?
               self.class :
               TwilioContactable).confirmation_message(confirmation_code)

  if message.to_s.size > 160
    raise ArgumentError, "SMS Confirmation Message is too long. Limit it to 160 characters of unescaped text."
  end

  response = TwilioContactable::Gateway.deliver(message, _TC_phone_number)

  if response.success?
    update_twilio_contactable_sms_confirmation confirmation_code
  else
    false
  end
end

#send_voice_confirmation!Object

Begins a phone call to the user where they’ll need to type their confirmation code



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/contactable.rb', line 122

def send_voice_confirmation!
  return false if _TC_voice_blocked
  return true  if voice_confirmed?
  return false if _TC_phone_number.blank?

  format_phone_number
  confirmation_code =
    if voice_confirmation_attempted &&
       voice_confirmation_code &&
       voice_confirmation_attempted > Time.now.utc - 60*5
      voice_confirmation_code
    else
      TwilioContactable.generate_confirmation_code
    end

  response = TwilioContactable::Gateway.initiate_voice_call(self, _TC_formatted_phone_number)

  if response.success?
    update_twilio_contactable_voice_confirmation confirmation_code
  else
    false
  end
end

#sms_confirm_with(code) ⇒ Object

Compares user-provided code with the stored confirmation code. If they match then the current phone number is set as confirmed by the user.



149
150
151
152
153
154
155
156
157
158
# File 'lib/contactable.rb', line 149

def sms_confirm_with(code)
  check_for_twilio_contactable_columns(:sms)
  if _TC_sms_confirmation_code.to_s.downcase == code.downcase
    # save the phone number into the 'confirmed phone number' attribute
    self._TC_sms_confirmed_phone_number = _TC_formatted_phone_number
    save
  else
    false
  end
end

#sms_confirmed?Boolean

Returns true if the current phone number has been confirmed by the user for recieving TXT messages.

Returns:

  • (Boolean)


162
163
164
165
166
# File 'lib/contactable.rb', line 162

def sms_confirmed?
  check_for_twilio_contactable_columns(:sms)
  return false if _TC_sms_confirmed_phone_number.blank?
  self._TC_sms_confirmed_phone_number == _TC_formatted_phone_number
end

#twilio_contactableObject

Set up a bridge to access the data for a specific instance by referring to the column values in the configuration.



65
66
67
# File 'lib/contactable.rb', line 65

def twilio_contactable
  self.class.twilio_contactable
end

#voice_confirm_with(code) ⇒ Object

Compares user-provided code with the stored confirmation code. If they match then the current phone number is set as confirmed by the user.



171
172
173
174
175
176
177
178
179
180
# File 'lib/contactable.rb', line 171

def voice_confirm_with(code)
  check_for_twilio_contactable_columns(:voice)
  if _TC_voice_confirmation_code.to_s.downcase == code.downcase
    # save the phone number into the 'confirmed phone number' attribute
    self._TC_voice_confirmed_phone_number = _TC_formatted_phone_number
    save
  else
    false
  end
end

#voice_confirmed?Boolean

Returns true if the current phone number has been confirmed by the user by receiving a phone call

Returns:

  • (Boolean)


184
185
186
187
188
# File 'lib/contactable.rb', line 184

def voice_confirmed?
  check_for_twilio_contactable_columns(:voice)
  return false if _TC_voice_confirmed_phone_number.blank?
  self._TC_voice_confirmed_phone_number == _TC_formatted_phone_number
end