4info 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/4info.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{4info}
8
- s.version = "1.1.1"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jack Danger Canty"]
12
- s.date = %q{2010-02-10}
12
+ s.date = %q{2010-02-11}
13
13
  s.description = %q{A complete Ruby API for handling SMS messages via 4info.com}
14
14
  s.email = %q{gitcommit@6brand.com}
15
15
  s.extra_rdoc_files = [
data/README.markdown CHANGED
@@ -3,12 +3,12 @@
3
3
 
4
4
  Connect to the 4info SMS gateway
5
5
 
6
- If you're using 4info.com as your SMS gateway this gem will give you a painless API.
6
+ If you're using 4info.com as your SMS gateway this gem will give you a painless API for both sending and receiving messages.
7
7
 
8
- USAGE
8
+ Setting Up Your Model
9
9
  =====
10
10
 
11
- Include FourInfo::Contactable into your User class or whatever you're using to represent an entity with a phone number.
11
+ Include FourInfo::Contactable into your User class or whatever you're using to represent an entity with a phone number.
12
12
 
13
13
  class User < ActiveRecord::Base
14
14
  include FourInfo::Contactable
@@ -25,25 +25,39 @@ You can also specify which attributes you'd like to use instead of the defaults
25
25
  sms_confirmation_attempted_column :when_was_the_sms_confirmation_attempted
26
26
  sms_confirmed_phone_number_column :the_mobile_number_thats_been_confirmed
27
27
 
28
- # Defaults to the name on the left (minus the word '_column')
28
+ # Defaults to the name on the left (minus the '_column' at the end)
29
29
  end
30
30
 
31
+
32
+ Confirming Phone Number And Sending Messages
33
+ ====
34
+
31
35
  You can manage the user's SMS state like so:
32
36
 
33
37
  @user = User.create(:sms_phone_number => '5552223333')
34
- @user.confirm_sms!
35
- # then ask the user for the confirmation code and
36
- # compare it to @user.sms_confirmation_code
37
- # if they're the same, call
38
- @user.sms_confirmed!
39
- @user.update_attributes(:sms_confirmed_phone_number => @user.sms_phone_number)
38
+ @user.send_sms_confirmation!
39
+
40
+ then ask the user for the confirmation code off their phone and pass it in to sms_confirm_with:
41
+
42
+ @user.sms_confirm_with(user_provided_code)
43
+
44
+ If the code is right then the user's current phone number will be automatically marked as confirmed. You can check this at any time with:
45
+
46
+ @user.sms_confirmed? # => true
40
47
  @user.send_sms!("Hi! This is a text message.")
41
- # Then maybe the user will reply with 'BLOCK' by accident
48
+
49
+ Then maybe the user will reply with 'BLOCK' by accident and @user.sms_blocked? will be true.
50
+ You can fix this by calling:
51
+
42
52
  @user.unblock_sms!
43
53
 
44
54
 
45
- There's also a controller module that allows you to super-easily create a controller
46
- that receives data from 4info.com
55
+ Receiving Messages From 4info.com
56
+ ====
57
+
58
+ You can also receive data posted to you from 4info.com. This is how you'll receive messages and notices that users have been blocked.
59
+ All you need is to create a bare controller and include FourInfo::Controller into it. Then specify which Ruby class you're using as a contactable user model (likely User)
60
+
47
61
 
48
62
  class SMSController < ApplicationController
49
63
  include FourInfo::Controller
@@ -51,10 +65,24 @@ that receives data from 4info.com
51
65
  sms_contactable User # or whichever class you included FourInfo::Contactable into
52
66
  end
53
67
 
54
- Now anything posted to the index (or create, if you've hooked this up RESTfully) action
55
- will automatically work. If a user sends 4info.com a message their user record on your site
56
- will (if User has a 'receive_sms' method defined) receive the message directly.
68
+ And hook this up in your routes.rb file like so:
69
+
70
+ ActionController::Routing::Routes.draw do |map|
71
+ map.route '4info', :controller => 'four_info', :action => :index
72
+ end
73
+
74
+ Now just tell 4info.com to POST messages and block notices to you at:
75
+
76
+ http://myrubyapp.com/4info
77
+
78
+ Now if your users reply to an SMS with 'STOP' your database will be updated to reflect this.
79
+
80
+ Incoming messages from a user will automatically be sent to that user's record:
81
+
82
+ # If "I love you!" is sent to you from a user with the phone
83
+ # number "555-111-9999" then the following will be executed:
84
+ User.find_by_sms_phone_number('5551119999').receive_sms("I love you!")
57
85
 
58
86
  That's it. Patches welcome, forks celebrated.
59
87
 
60
- Copyright (c) 2010 Jack Danger Canty (http://jåck.com/), released under the MIT license
88
+ Copyright (c) 2010 [Jack Danger Canty](http://jåck.com/), released under the MIT license
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.1
1
+ 1.2.0
data/lib/contactable.rb CHANGED
@@ -13,7 +13,7 @@ module FourInfo
13
13
  require 'net/http'
14
14
 
15
15
  Attributes.each do |attribute|
16
- # add a method for setting or retrieving
16
+ # add a method in the class for setting or retrieving
17
17
  # which column should be used for which attribute
18
18
  #
19
19
  # :sms_phone_number_column defaults to :sms_phone_number, etc.
@@ -24,34 +24,34 @@ module FourInfo
24
24
  @#{attribute}_column
25
25
  end
26
26
  "
27
- # provide a helper method to access the right value
28
- # no matter which column it's stored in
27
+ # provide helper methods to access the right value
28
+ # no matter which column it's stored in.
29
29
  #
30
30
  # e.g.: @user.four_info_sms_confirmation_code
31
31
  # == @user.send(User.sms_confirmation_code_column)
32
32
  model.class_eval "
33
- def four_info_#{attribute}(value = nil)
34
- value ?
35
- send(self.class.#{attribute}_column.to_s+'=', value) :
36
- send(self.class.#{attribute}_column)
33
+ def four_info_#{attribute}
34
+ send self.class.#{attribute}_column
37
35
  end
38
36
  alias_method :four_info_#{attribute}?, :four_info_#{attribute}
39
- alias_method :four_info_#{attribute}=, :four_info_#{attribute}
37
+ def four_info_#{attribute}=(value)
38
+ send self.class.#{attribute}_column.to_s+'=', value
39
+ end
40
40
  "
41
41
  end
42
42
  end
43
43
 
44
- def current_phone_number_confirmed_for_sms?
45
- return false if four_info_sms_confirmed_phone_number.blank?
46
- four_info_sms_confirmed_phone_number == four_info_sms_phone_number
47
- end
48
-
44
+ # Sends one or more TXT messages to the contactable record's
45
+ # mobile number (if the number has been confirmed).
46
+ # Any messages longer than 160 characters will need to be accompanied
47
+ # by a second argument <tt>true</tt> to clarify that sending
48
+ # multiple messages is intentional.
49
49
  def send_sms!(msg, allow_multiple = false)
50
50
  if msg.to_s.size > 160 && !allow_multiple
51
51
  raise ArgumentError, "SMS Message is too long. Either specify that you want multiple messages or shorten the string."
52
52
  end
53
53
  return false if msg.to_s.strip.blank? || four_info_sms_blocked?
54
- return false unless current_phone_number_confirmed_for_sms?
54
+ return false unless sms_confirmed?
55
55
 
56
56
  # split into pieces that fit as individual messages.
57
57
  msg.to_s.scan(/.{1,160}/m).map do |text|
@@ -59,15 +59,18 @@ module FourInfo
59
59
  end
60
60
  end
61
61
 
62
- def confirm_sms!
62
+ # Sends an SMS validation request via xml to the 4info gateway.
63
+ # If request succeeds the 4info-generated confirmation code is saved
64
+ # in the contactable record.
65
+ def send_sms_confirmation!
63
66
  return false if four_info_sms_blocked?
64
- return true if current_phone_number_confirmed_for_sms?
67
+ return true if sms_confirmed?
65
68
  return false if four_info_sms_phone_number.blank?
66
69
 
67
70
  response = FourInfo::Request.new.confirm(four_info_sms_phone_number)
68
71
  if response.success?
69
- self.four_info_sms_confirmation_code response.confirmation_code
70
- self.four_info_sms_confirmation_attempted Time.now
72
+ self.four_info_sms_confirmation_code = response.confirmation_code
73
+ self.four_info_sms_confirmation_attempted = Time.now
71
74
  save
72
75
  else
73
76
  # "Confirmation Failed: #{response['message'].inspect}"
@@ -75,21 +78,37 @@ module FourInfo
75
78
  end
76
79
  end
77
80
 
78
- def sms_confirmed!
79
- # save the phone number into the 'confirmed phone number' attribute
80
- four_info_sms_confirmed_phone_number four_info_sms_phone_number
81
- end
82
-
81
+ # Sends an unblock request via xml to the 4info gateway.
82
+ # If request succeeds, changes the contactable record's
83
+ # sms_blocked_column to false.
83
84
  def unblock_sms!
84
85
  return false unless four_info_sms_blocked?
85
86
 
86
87
  response = FourInfo::Request.new.unblock(four_info_sms_phone_number)
87
88
  if response.success?
88
- four_info_sms_blocked 'false'
89
+ self.four_info_sms_blocked = 'false'
89
90
  save!
90
91
  else
91
92
  false
92
93
  end
93
94
  end
95
+
96
+ # Compares user-provided code with the stored confirmation
97
+ # code. If they match then the current phone number is set
98
+ # as confirmed by the user.
99
+ def sms_confirm_with(code)
100
+ if four_info_sms_confirmation_code == code
101
+ # save the phone number into the 'confirmed phone number' attribute
102
+ self.four_info_sms_confirmed_phone_number = four_info_sms_phone_number
103
+ save
104
+ end
105
+ end
106
+
107
+ # Returns true if the current phone number has been confirmed by
108
+ # the user for recieving TXT messages.
109
+ def sms_confirmed?
110
+ return false if four_info_sms_confirmed_phone_number.blank?
111
+ four_info_sms_confirmed_phone_number == four_info_sms_phone_number
112
+ end
94
113
  end
95
114
  end
data/lib/controller.rb CHANGED
@@ -47,7 +47,7 @@ module FourInfo
47
47
  end
48
48
 
49
49
  def find_contactable(id)
50
- [id, id.sub(/^\+/,''), id.sub(/^\+1/,'')].each do |possible_phone_number|
50
+ [id, id.sub(/^\+/,''), id.sub(/^\+1/,'')].uniq.compact.each do |possible_phone_number|
51
51
  found = @@contactable_class.find(
52
52
  :first,
53
53
  :conditions =>
@@ -60,7 +60,7 @@ class FourInfoContactableTest < ActiveSupport::TestCase
60
60
  context "when phone number is blank" do
61
61
  setup { @user.sms_phone_number = nil}
62
62
  context "confirming phone number" do
63
- setup { @user.confirm_sms! }
63
+ setup { @user.send_sms_confirmation! }
64
64
  should_not_change "any attributes" do
65
65
  @user.attributes.inspect
66
66
  end
@@ -82,7 +82,7 @@ class FourInfoContactableTest < ActiveSupport::TestCase
82
82
  context "confirming phone number" do
83
83
  setup {
84
84
  FourInfo::Request.any_instance.stubs(:perform).returns(ValidationSuccess)
85
- @worked = @user.confirm_sms!
85
+ @worked = @user.send_sms_confirmation!
86
86
  }
87
87
  should "work" do assert @worked end
88
88
  should "save confirmation number in proper attribute" do
@@ -95,15 +95,25 @@ class FourInfoContactableTest < ActiveSupport::TestCase
95
95
  @user.four_info_sms_confirmation_code
96
96
  end
97
97
  should "not have number confirmed yet" do
98
- assert !@user.current_phone_number_confirmed_for_sms?
98
+ assert !@user.sms_confirmed?
99
99
  end
100
- context "calling sms_confirmed!" do
101
- setup { @user.sms_confirmed! }
100
+ context "calling sms_confirm_with(right_code)" do
101
+ setup { @user.sms_confirm_with(@user.four_info_sms_confirmation_code) }
102
102
  should "save the phone number into the confirmed attribute" do
103
103
  assert_equal @user.four_info_sms_confirmed_phone_number,
104
104
  @user.four_info_sms_phone_number
105
105
  end
106
- should_change "confirmed phone number attribuet" do
106
+ should_change "confirmed phone number attribute" do
107
+ @user.four_info_sms_confirmed_phone_number
108
+ end
109
+ end
110
+ context "calling sms_confirm_with(wrong_code)" do
111
+ setup { @user.sms_confirm_with('wrong_code') }
112
+ should "not save the phone number into the confirmed attribute" do
113
+ assert_not_equal @user.four_info_sms_confirmed_phone_number,
114
+ @user.four_info_sms_phone_number
115
+ end
116
+ should_not_change "confirmed phone number attribute" do
107
117
  @user.four_info_sms_confirmed_phone_number
108
118
  end
109
119
  end
@@ -111,7 +121,7 @@ class FourInfoContactableTest < ActiveSupport::TestCase
111
121
  context "confirming phone number when the confirmation fails for some reason" do
112
122
  setup {
113
123
  FourInfo::Request.any_instance.stubs(:perform).returns(ValidationError)
114
- @worked = @user.confirm_sms!
124
+ @worked = @user.send_sms_confirmation!
115
125
  }
116
126
  should "not work" do assert !@worked end
117
127
  should "not save confirmation number" do
@@ -149,7 +159,7 @@ class FourInfoContactableTest < ActiveSupport::TestCase
149
159
  context "when the number is confirmed" do
150
160
  setup {
151
161
  FourInfo::Request.any_instance.stubs(:perform).returns(SendMsgSuccess)
152
- @user.stubs(:current_phone_number_confirmed_for_sms?).returns(true)
162
+ @user.stubs(:sms_confirmed?).returns(true)
153
163
  }
154
164
  context "sending a message" do
155
165
  setup { @result = @user.send_sms!('message') }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 4info
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Danger Canty
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-10 00:00:00 -08:00
12
+ date: 2010-02-11 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency