blythedunham-sms_on_rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/Manifest +101 -0
  3. data/README +163 -0
  4. data/README.rdoc +211 -0
  5. data/Rakefile +76 -0
  6. data/app/controllers/admin/sms_on_rails/base_controller.rb +11 -0
  7. data/app/controllers/admin/sms_on_rails/drafts_controller.rb +75 -0
  8. data/app/controllers/admin/sms_on_rails/outbounds_controller.rb +117 -0
  9. data/app/controllers/admin/sms_on_rails/phone_carriers_controller.rb +85 -0
  10. data/app/controllers/admin/sms_on_rails/phone_numbers_controller.rb +101 -0
  11. data/app/controllers/sms_on_rails/creation_support.rb +99 -0
  12. data/app/controllers/sms_on_rails_controller.rb +14 -0
  13. data/app/helpers/admin/sms_on_rails/drafts_helper.rb +2 -0
  14. data/app/helpers/admin/sms_on_rails/phone_carriers_helper.rb +2 -0
  15. data/app/helpers/sms_on_rails/phone_numbers_helper.rb +9 -0
  16. data/app/helpers/sms_on_rails/sms_helper.rb +44 -0
  17. data/app/models/sms_on_rails/draft.rb +9 -0
  18. data/app/models/sms_on_rails/outbound.rb +17 -0
  19. data/app/models/sms_on_rails/phone_carrier.rb +14 -0
  20. data/app/models/sms_on_rails/phone_number.rb +8 -0
  21. data/app/views/admin/sms_on_rails/base/index.html.erb +5 -0
  22. data/app/views/admin/sms_on_rails/drafts/_show.html.erb +34 -0
  23. data/app/views/admin/sms_on_rails/drafts/edit.html.erb +36 -0
  24. data/app/views/admin/sms_on_rails/drafts/index.html.erb +32 -0
  25. data/app/views/admin/sms_on_rails/drafts/new.html.erb +34 -0
  26. data/app/views/admin/sms_on_rails/drafts/send_sms.html.erb +3 -0
  27. data/app/views/admin/sms_on_rails/drafts/show.html.erb +4 -0
  28. data/app/views/admin/sms_on_rails/outbounds/edit.html.erb +68 -0
  29. data/app/views/admin/sms_on_rails/outbounds/index.html.erb +37 -0
  30. data/app/views/admin/sms_on_rails/outbounds/new.html.erb +54 -0
  31. data/app/views/admin/sms_on_rails/outbounds/show.html.erb +69 -0
  32. data/app/views/admin/sms_on_rails/phone_carriers/edit.html.erb +24 -0
  33. data/app/views/admin/sms_on_rails/phone_carriers/index.html.erb +24 -0
  34. data/app/views/admin/sms_on_rails/phone_carriers/new.html.erb +22 -0
  35. data/app/views/admin/sms_on_rails/phone_carriers/show.html.erb +24 -0
  36. data/app/views/admin/sms_on_rails/phone_numbers/edit.html.erb +33 -0
  37. data/app/views/admin/sms_on_rails/phone_numbers/index.html.erb +28 -0
  38. data/app/views/admin/sms_on_rails/phone_numbers/new.html.erb +31 -0
  39. data/app/views/admin/sms_on_rails/phone_numbers/show.html.erb +32 -0
  40. data/app/views/layouts/sms_on_rails/basic.html.erb +26 -0
  41. data/app/views/sms_on_rails/_phone_carrier_form_item.html.erb +6 -0
  42. data/app/views/sms_on_rails/_send_sms.html.erb +33 -0
  43. data/app/views/sms_on_rails/index.html.erb +8 -0
  44. data/app/views/sms_on_rails/send_sms.html.erb +3 -0
  45. data/app/views/sms_on_rails/show.html.erb +29 -0
  46. data/config/routes.rb +19 -0
  47. data/db/data/fixtures/sms_phone_carriers.yml +110 -0
  48. data/db/migrate/sms_on_rails_carrier_tables.rb +9 -0
  49. data/db/migrate/sms_on_rails_model_tables.rb +48 -0
  50. data/db/migrate/sms_on_rails_phone_number_tables.rb +11 -0
  51. data/db/seed_data.rb +16 -0
  52. data/generators/sms_on_rails/USAGE +31 -0
  53. data/generators/sms_on_rails/commands/inserts.rb +63 -0
  54. data/generators/sms_on_rails/commands/timestamps.rb +33 -0
  55. data/generators/sms_on_rails/runners/add_all_models.rb +6 -0
  56. data/generators/sms_on_rails/runners/dependencies.rb +1 -0
  57. data/generators/sms_on_rails/runners/remove_all_models.rb +5 -0
  58. data/generators/sms_on_rails/runners/sms_on_rails_routes.rb +14 -0
  59. data/generators/sms_on_rails/sms_on_rails_generator.rb +255 -0
  60. data/generators/sms_on_rails/templates/configuration/clickatell.rb +6 -0
  61. data/generators/sms_on_rails/templates/configuration/email_gateway.rb +7 -0
  62. data/generators/sms_on_rails/templates/migrate/schema_migration.rb +15 -0
  63. data/generators/sms_on_rails/templates/migrate/sms_on_rails_update_phone_numbers.rb +40 -0
  64. data/generators/sms_on_rails/templates/phone_number_collision.rb +2 -0
  65. data/init.rb +3 -0
  66. data/install.rb +1 -0
  67. data/lib/sms_on_rails.rb +8 -0
  68. data/lib/sms_on_rails/activerecord_extensions/acts_as_deliverable.rb +92 -0
  69. data/lib/sms_on_rails/activerecord_extensions/acts_as_substitutable.rb +80 -0
  70. data/lib/sms_on_rails/activerecord_extensions/has_a_sms_service_provider.rb +101 -0
  71. data/lib/sms_on_rails/activerecord_extensions/lockable_record.rb +186 -0
  72. data/lib/sms_on_rails/all_models.rb +3 -0
  73. data/lib/sms_on_rails/model_support/draft.rb +178 -0
  74. data/lib/sms_on_rails/model_support/outbound.rb +136 -0
  75. data/lib/sms_on_rails/model_support/phone_carrier.rb +77 -0
  76. data/lib/sms_on_rails/model_support/phone_number.rb +248 -0
  77. data/lib/sms_on_rails/model_support/phone_number_associations.rb +13 -0
  78. data/lib/sms_on_rails/schema_helper.rb +51 -0
  79. data/lib/sms_on_rails/service_providers/base.rb +222 -0
  80. data/lib/sms_on_rails/service_providers/clickatell.rb +52 -0
  81. data/lib/sms_on_rails/service_providers/dummy.rb +19 -0
  82. data/lib/sms_on_rails/service_providers/email_gateway.rb +68 -0
  83. data/lib/sms_on_rails/service_providers/email_gateway_support/errors.rb +20 -0
  84. data/lib/sms_on_rails/service_providers/email_gateway_support/sms_mailer.rb +21 -0
  85. data/lib/sms_on_rails/service_providers/email_gateway_support/sms_mailer/sms_through_gateway.erb +6 -0
  86. data/lib/sms_on_rails/util/sms_error.rb +12 -0
  87. data/lib/smsonrails.rb +1 -0
  88. data/public/images/sms_on_rails/railsYoDawg.jpg +0 -0
  89. data/public/stylesheets/sms_on_rails.css +137 -0
  90. data/sms_on_rails.gemspec +32 -0
  91. data/tasks/sms_on_rails_tasks.rake +67 -0
  92. data/test/active_record_extensions/delivery_and_locking_test.rb +84 -0
  93. data/test/models/draft_test.rb +72 -0
  94. data/test/models/outbound_test.rb +89 -0
  95. data/test/models/phone_number_test.rb +131 -0
  96. data/test/run.rb +18 -0
  97. data/test/service_providers/abstract_test_support.rb +104 -0
  98. data/test/service_providers/clickatell_test.rb +39 -0
  99. data/test/service_providers/email_gateway_test.rb +30 -0
  100. data/test/test_helper.rb +24 -0
  101. data/uninstall.rb +1 -0
  102. metadata +187 -0
@@ -0,0 +1,8 @@
1
+
2
+ <h1> SMS On Rails </h1>
3
+
4
+ <%= image_tag "sms_on_rails/railsYoDawg.jpg", :class => 'smsOnRailsImage' %>
5
+ <br />
6
+ <%= link_to 'Send SMS', new_sms_path %>
7
+ <br/>
8
+ <%= link_to 'Administer SMS', sms_admin_path %>
@@ -0,0 +1,3 @@
1
+ <h1> Send an SMS</h1>
2
+ <%= render :partial => '/sms_on_rails/send_sms.html' %>
3
+ <%= link_to 'Sms Home', sms_index_path %>
@@ -0,0 +1,29 @@
1
+
2
+ <p>
3
+ <b>Message:</b>
4
+ <%=h @draft.actual_message %>
5
+ </p>
6
+
7
+ <p>
8
+ <b>Status:</b>
9
+ <%=h @draft.status %>
10
+ </p>
11
+
12
+ <p>
13
+ <b>Deliver after:</b>
14
+ <%=h @draft.deliver_after %>
15
+ </p>
16
+
17
+ <p>
18
+ <b>Delivery date:</b>
19
+ <%=h @draft.delivery_date %>
20
+ </p>
21
+
22
+ <p>
23
+ <b> Phone Numbers: </b><br>
24
+ <% @draft.outbounds.each do |outbound| %>
25
+ <%= outbound.phone_number.human_display %><br>
26
+ <% end %>
27
+ </p>
28
+
29
+ <%= link_to 'Send More SMS Messages', new_sms_path %>
@@ -0,0 +1,19 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+
3
+ #Resources for sms on rails admin routes
4
+ #url: localhost:3000/admin/sms/drafts goes to the app/controllers/admin/sms_on_rails/draft_controller.rb
5
+
6
+ map.resources :sms_drafts, :new => {:send_sms => :any}, :as => 'admin/sms/drafts', :controller => 'admin/sms_on_rails/drafts' do |draft|
7
+ draft.resources :outbounds, :collection => {:deliver_sms => :any}, :controller => 'admin/sms_on_rails/outbounds'
8
+ end
9
+
10
+ map.resources :sms_drafts, :collection => {:send_sms => :any}, :as => 'admin/sms/drafts', :controller => 'admin/sms_on_rails/drafts'
11
+
12
+ map.resources :sms_phone_numbers, :as => 'admin/sms/phone_numbers', :controller => 'admin/sms_on_rails/phone_numbers'
13
+ map.resources :sms_phone_carriers, :as => 'admin/sms/phone_carriers', :controller => 'admin/sms_on_rails/phone_carriers'
14
+
15
+ map.resources :sms, :as => 'sms', :controller => 'sms_on_rails', :only => [:create, :show, :new, :index], :singular => 'sms'
16
+
17
+ map.sms_admin '/admin/sms', :controller => 'admin/sms_on_rails/base', :action => 'index'
18
+
19
+ end#end sms routeM
@@ -0,0 +1,110 @@
1
+ carrier_1:
2
+ id: "1"
3
+ name: Verizon
4
+ email_domain: "vtext.com"
5
+
6
+ carrier_2:
7
+ id: "2"
8
+ name: Alltel
9
+ email_domain: "message.alltel.com"
10
+
11
+ carrier_3:
12
+ id: "3"
13
+ name: Cingular mmode
14
+ email_domain: "mmode.com"
15
+ notes: "formerly AT&T, then Cingular, now AT&T Wireless - Original grandfathered rateplan customers"
16
+
17
+ carrier_4:
18
+ id: "4"
19
+ name: Cellular One
20
+ email_domain: "mobile.celloneusa.com"
21
+
22
+ carrier_5:
23
+ id: "5"
24
+ name: AT&T
25
+ email_domain: "txt.att.net"
26
+
27
+ carrier_6:
28
+ id: "6"
29
+ name: Nextel
30
+ email_domain: "page.nextel.com"
31
+
32
+ carrier_7:
33
+ id: "7"
34
+ name: OmnipointPCS
35
+ email_domain: "omnipointpcs.com"
36
+
37
+ carrier_8:
38
+ id: "8"
39
+ name: Qwest
40
+ email_domain: "qwestmp.com"
41
+
42
+ carrier_9:
43
+ id: "9"
44
+ name: Sprint
45
+ email_domain: "messaging.sprintpcs.com"
46
+
47
+ carrier_10:
48
+ id: "10"
49
+ name: T-Mobile
50
+ email_domain: "tmomail.net"
51
+
52
+ carrier_11:
53
+ id: "11"
54
+ name: Virgin Mobile
55
+ email_domain: "vmobl.com"
56
+
57
+ carrier_12:
58
+ id: "12"
59
+ name: US Cellular
60
+ email_domain: "email.uscc.com"
61
+
62
+ carrier_13:
63
+ id: "13"
64
+ name: Amp'd
65
+ email_domain: "ampdpix.com"
66
+
67
+ carrier_14:
68
+ id: 14
69
+ name: AT&T Formerly Cingular
70
+ email_domain: "cingularme.com"
71
+
72
+ carrier_15:
73
+ id: 15
74
+ name: AT&T Formerly Cingular MMS
75
+ email_domain: "mms.att.net"
76
+
77
+ carrier_16:
78
+ id: 16
79
+ name: Alaska Communications Systems
80
+ email_domain: "msg.acsalaska.com"
81
+
82
+ carrier_17:
83
+ id: 17
84
+ name: AT&T Enterprise Paging
85
+ email_domain: "number@page.att.net"
86
+
87
+ carrier_18:
88
+ id: 22
89
+ name: MetroPCS
90
+ email_domain: "mymetropcs.com"
91
+
92
+ carrier_19:
93
+ id: 19
94
+ name: Plateau Wireless
95
+ email_domain: "smsx.plateaugsm.com"
96
+
97
+ carrier_20:
98
+ id: 20
99
+ name: 7-11 Speakout
100
+ email_domain: "cingularme.com"
101
+
102
+ carrier_21:
103
+ id: 21
104
+ name: Cricket
105
+ email_domain: "sms.mycricket.com"
106
+
107
+
108
+
109
+
110
+
@@ -0,0 +1,9 @@
1
+
2
+ create_table :sms_phone_carriers, :force => true do |t|
3
+ t.string :name, :length => 100, :null => false
4
+ t.string :email_domain, :length => 100, :default => nil
5
+ t.string :notes, :default => nil
6
+ t.string :options, :default => nil
7
+ end
8
+
9
+ add_index :sms_phone_carriers, :name, :unique => 'true', :name => 'uk_phone_carriers_name'
@@ -0,0 +1,48 @@
1
+ use_fk = respond_to?(:add_foreign_key)
2
+ puts "#{use_fk ? '': 'NOT'} USING FOREIGN KEYS"
3
+
4
+ create_table :sms_drafts, :force => true do |t|
5
+ t.column :message, :string, :default => nil
6
+ t.column :header, :string, :default => nil
7
+ t.column :footer, :string, :default => nil
8
+ t.column :status, :string, :limit => 15, :null => false, :default => 'NOT_PROCESSED'
9
+ t.column :deliver_after, :datetime, :default => nil
10
+ t.column :delivery_date, :datetime, :default => nil
11
+ t.column :sender_id, :integer, :default => nil
12
+ t.column :lock_version, :integer, :null => false, :default => 0, :limit => 1
13
+ t.column :options, :string, :default => nil
14
+ t.column :updated_at, :string, :default => nil
15
+ t.column :created_at, :string, :default => nil
16
+ end
17
+
18
+
19
+ #Add a unique id to track vendor
20
+ create_table :sms_outbounds, :force => true do |t|
21
+ t.column :sms_phone_number_id, :integer, :null => false, :references => :phone_number, :on_delete => :cascade
22
+ t.column :sms_draft_id, :integer, :default => nil, :on_delete => :cascade
23
+ t.column :status, :string, :limit => 15, :null => false, :default => 'NOT_PROCESSED'
24
+ t.column :retry_count, :integer, :limit => 1, :null => false, :default => 0
25
+ t.column :sub_status, :string, :limit => 35, :default => nil
26
+ t.column :notes, :string, :limit => 80, :default => nil
27
+ t.column :created_at, :datetime, :default => nil
28
+ t.column :processed_on, :datetime, :default => nil
29
+ t.column :lock_version, :integer, :null => false, :default => 0, :limit => 1
30
+ t.column :sms_service_provider_id, :integer, :limit => 4, :default => nil, :references => nil
31
+ t.column :options, :string, :default => nil
32
+ t.column :send_priority, :integer, :limit => 4, :null => false, :default => 0
33
+ t.column :actual_message, :string, :limit => 160, :null => true, :default => nil
34
+ end
35
+
36
+ execute "ALTER TABLE sms_outbounds ADD COLUMN `unique_id` varchar(255) character set latin1 collate latin1_bin default NULL"
37
+ add_index :sms_outbounds, :unique_id, :unique => 'true', :name => 'uk_sms_outbounds_unique_id'
38
+ add_index :sms_outbounds, [:sms_draft_id, :sms_phone_number_id], :unique => 'true', :name => 'uk_sms_outbounds_draft_phone_number'
39
+
40
+ # Add composite accross sms_outbounds for lookup speed
41
+ #add_index :sms_outbounds, [:status, :send_priority, :sms_draft_id], :name => 'idx_sms_outbounds_status_priority_draft'
42
+
43
+ #Add a unique id to track vendor
44
+ unless use_fk
45
+ #add_index :sms_outbounds, :sms_draft_id
46
+ #do not index :sms_draft_id because their is already a composite on
47
+ add_index :sms_outbounds, :sms_phone_number_id
48
+ end
@@ -0,0 +1,11 @@
1
+ create_table :phone_numbers, :force => true do |t|
2
+ t.string :number, :length => 20, :null => false
3
+ t.integer :carrier_id, :default => nil
4
+ t.integer :owner_id, :default => nil
5
+ t.boolean :white_list, :null => false, :default => false
6
+ t.string :do_not_send, :length => 30, :default => nil
7
+ t.integer :country_code, :length => 2, :default => 1
8
+ end
9
+
10
+ add_index :phone_numbers, :number, :unique => 'true', :name => 'uk_phone_numbers_number'
11
+
@@ -0,0 +1,16 @@
1
+ require 'active_record/fixtures'
2
+
3
+ unless defined?(SmsOnRails::PhoneCarrier)
4
+ require 'sms_on_rails/phone_carrier'
5
+ end
6
+
7
+ fixture_class_names = {
8
+ :sms_phone_carriers => 'SmsOnRails::PhoneCarrier',
9
+ }
10
+
11
+ fixture_path = File.dirname(__FILE__) + '/data/fixtures'
12
+
13
+ fixture_files = Dir.glob(fixture_path + '/*.yml').collect{|f| File.basename(f, '.yml')}
14
+ fixture_class_names.values.each {|klass| klass.constantize.delete_all }
15
+
16
+ Fixtures.create_fixtures(fixture_path, fixture_files, fixture_class_names)
@@ -0,0 +1,31 @@
1
+ Description:
2
+ Setup Sms On Rails
3
+
4
+ The following actions can be specified seperately or together
5
+
6
+ environment (default)
7
+ - add the configuration to config/environment.rb and runs dependencies
8
+ models
9
+ - copy the vanilla models up to app/models/sms_on_rails so they can be
10
+ edited/overwritten accordingly
11
+ dependencies
12
+ - install dependent plugins and gems (enviroment does this automatically)
13
+ migration (default)
14
+ - creates three migration templates for sms tables. To skip one, for example if
15
+ only the carriers and phone numbers are desired,
16
+ use --skip-models, --skip-phone-number or --skip-carriers to skip
17
+
18
+ Example:
19
+ Set up the environment and create models in app/models/sms_on_rails
20
+ ./script/generate sms_on_rails setup environment models
21
+
22
+ Just setup the environment and create the migration
23
+ ./script/generate sms_on_rails setup
24
+
25
+ Setup the views
26
+ ./script/generate sms_on_rails setup views
27
+
28
+ Create a migration skipping models migration
29
+ ./script/generate sms_on_rails setup migration --skip-models
30
+
31
+
@@ -0,0 +1,63 @@
1
+ # Most of this was derived from the clearance gem work
2
+ Rails::Generator::Commands::Base.class_eval do
3
+
4
+ # Return true if the file contains the line (String or Regexp)
5
+ def file_contains?(relative_destination, line)
6
+ File.read(destination_path(relative_destination)).scan(line).any?
7
+ end
8
+
9
+ def margin_text(options={})
10
+ margin = ' ' * (options[:margin]||2)
11
+ margin
12
+ end
13
+
14
+ def append_to_file(relative_destination, content)
15
+ path = destination_path(relative_destination)
16
+ File.open(path, 'ab') { |file| file.write("\n" + content + "\n") }
17
+ end
18
+ end
19
+
20
+ Rails::Generator::Commands::Create.class_eval do
21
+
22
+ # Insert the new line into the file
23
+ # +file+ - the name of the file to update
24
+ # +new_line+ - the new line to insert
25
+ # == Options
26
+ # <tt>:quiet</tt> - turn off logging
27
+ # <tt>:append</tt> - when true append to the end of the file instead of <tt>:insert_after</tt>
28
+ # <tt>:match</tt> - (String or Regexp). If the file contents matches then do not add this line again. This defaults to the actual line itself
29
+ # <tt>:replace</tt> - (Regexp) Replace the matching regexp completely with the new line. If nothing matches the replace regexp, append to the end of the file. <tt>:insert_after</tt> value is ignored.
30
+ # <tt>:insert_after</tt> (Regexp) Insert the new line after this match. By default, the line is inserted after a class or module
31
+ # <tt>:margin</tt> - length of the margin to add before the line. Defaults to 2.
32
+ def insert_into(file, new_line, options={})
33
+ logger.insert "#{new_line} into #{file}" unless options[:quiet]
34
+
35
+ line = margin_text(options) + new_line
36
+
37
+ unless options[:pretend] || file_contains?(file, options[:match]||line)
38
+ if options[:append] || (options[:replace] && !file_contains?(file, options[:replace]))
39
+ append_to_file file, line
40
+ else
41
+ regex = options[:insert_after]||options[:replace]||/^(class|module) .+$/
42
+ gsub_file file, regex do |match|
43
+ options[:replace] ? line : "#{match}\n#{line}"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Rails::Generator::Commands::Destroy.class_eval do
51
+ def insert_into(file, line, options={})
52
+ logger.remove "#{line} from #{file}"
53
+ unless options[:pretend]
54
+ gsub_file file, "\n#{margin_text(options)}#{line}", ''
55
+ end
56
+ end
57
+ end
58
+
59
+ Rails::Generator::Commands::List.class_eval do
60
+ def insert_into(file, line)
61
+ logger.insert "#{line} into #{file}"
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ Rails::Generator::Commands::Create.class_eval do
2
+
3
+ #overwrite next migration string to add a count to the timestamp
4
+ def next_migration_string(padding = 3)#:nodoc:
5
+ if ActiveRecord::Base.timestamped_migrations
6
+ time_str = Time.now.utc.strftime("%Y%m%d%H%M%S")
7
+ time_str << "#{migration_count}" if migration_count > 1
8
+ time_str
9
+ else
10
+ "%.#{padding}d" % next_migration_number
11
+ end
12
+ end
13
+
14
+ def migration_count
15
+ @@mig_count||=0
16
+ end
17
+
18
+ def increment_migration_count
19
+ @@mig_count = migration_count + 1
20
+ end
21
+
22
+ # When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.
23
+ def migration_template(relative_source, relative_destination, template_options = {})#:nodoc:
24
+ increment_migration_count
25
+ migration_directory relative_destination
26
+ migration_file_name = template_options[:migration_file_name] || file_name
27
+ if migration_exists?(migration_file_name)
28
+ logger.exists "#{existing_migrations(migration_file_name).first}"
29
+ else
30
+ template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,6 @@
1
+ append_file 'config/environment.rb', <<-EOS
2
+ # Include vanilla sms models. If you wish to make changes and create your own
3
+ # models/sms_on_rails this line should be removed.
4
+ require 'sms_on_rails/all_models'
5
+
6
+ EOS
@@ -0,0 +1 @@
1
+ plugin 'static_record_cache', :git => 'git://github.com/blythedunham/static_record_cache.git'
@@ -0,0 +1,5 @@
1
+
2
+ sentinel = "[^#](require\\s+['|\"]sms_on_rails/all_models['|\"])"
3
+ gsub_file 'config/environment.rb', Regexp.new(sentinel) do |match|
4
+ "\n##{match.strip}"
5
+ end
@@ -0,0 +1,14 @@
1
+
2
+ route <<-EOS
3
+
4
+ #Resources for sms on rails admin routes
5
+ #url: localhost:3000/admin/sms/drafts goes to the app/controllers/admin/sms_on_rails/draft_controller.rb
6
+ map.resources :sms_drafts, :as => 'admin/sms/drafts', :controller => 'admin/sms_on_rails/drafts' do |draft|
7
+ draft.resources :outbounds, :controller => 'admin/sms_on_rails/outbounds'
8
+ end
9
+ map.resources :sms_phone_numbers, :as => 'admin/sms/phone_numbers', :controller => 'admin/sms_on_rails/phone_numbers'
10
+ map.resources :sms_outbounds, :as => 'admin/sms/outbounds', :controller => 'admin/sms_on_rails/outbounds'
11
+ map.resources :sms_phone_carriers, :as => 'admin/sms/phone_carriers', :controller => 'admin/sms_on_rails/phone_carriers'
12
+ EOS
13
+
14
+
@@ -0,0 +1,255 @@
1
+ require 'rails_generator/generators/applications/app/template_runner'
2
+ require File.dirname(__FILE__) + '/commands/inserts.rb'
3
+ require File.dirname(__FILE__) + '/commands/timestamps.rb'
4
+
5
+ class SmsOnRailsGenerator < Rails::Generator::NamedBase
6
+
7
+ default_options :skip_models => false, :skip_carriers => false,
8
+ :skip_phone_numbers => false, :skip_migration => false,
9
+ :default_service_provider => :email_gateway
10
+
11
+ unless defined?(SERVICE_PROVIDERS)
12
+ SERVICE_PROVIDERS = [:clickatell, :email_gateway]
13
+ SET_SERVICE_PROVIDER_CONFIG = "SmsOnRails::ServiceProviders::Base.set_default_service_provider"
14
+ end
15
+
16
+ def manifest
17
+ @actions = (actions.blank?) ? %w(environment migration phone_collision assets) : self.actions
18
+ @actions.sort! #we want environment to run first
19
+ @actions.delete('dependencies') if @actions.include?('environment')
20
+
21
+ record do |m|
22
+ @actions.each do |action|
23
+ case(action)
24
+ when 'views' then create_views(m)
25
+ when 'models' then copy_models(m)
26
+ when 'environment' then add_configuation_options(m)
27
+ when 'dependencies' then add_dependencies(m)
28
+ when 'migration' then generate_migration_templates(m)
29
+ when 'phone_collision' then handle_phone_number_collision(m)
30
+ when 'assets' then copy_assets(m)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def after_generate
37
+ end
38
+
39
+ protected
40
+
41
+ def banner
42
+ "Usage: #{$0} sms_on_rails setup [models views environment]"
43
+ end
44
+
45
+ # options specific to sms on rails generator
46
+ def add_options!(opt)
47
+ opt.separator ''
48
+ opt.separator 'Options:'
49
+ opt.on("-m", "--skip-models",
50
+ "Skip the models migration",
51
+ "Default: false") { |v| options[:skip_models] = v }
52
+ opt.on("-c", "--skip-carriers",
53
+ "Skip the phone carriers migrations",
54
+ "Default: false") { |v| options[:skip_carriers] = v }
55
+ opt.on("-p", "--skip-phone-numbers",
56
+ "Skip the phone numbers migrations",
57
+ "Default: false") { |v| options[:skip_phone_numbers] = v }
58
+ opt.on("-s", "--default-service-provider=[name]",
59
+ "Name of the default service provider: clickatell or email_gateway",
60
+ "Default: email_gateway") { |v| options[:default_service_provider] = v.to_s.downcase.underscore.to_sym }
61
+ end
62
+
63
+ # If app/models/phone_number.rb exists, add include the Sms functionality
64
+ # and define app/models/sms_on_rails/phone_number.rb to point to PhoneNumber
65
+ def handle_phone_number_collision(m)
66
+ #if the phone_number.rb file exists on the main
67
+ phone_number_model = "app/models/phone_number.rb"
68
+ if File.exists?(phone_number_model)
69
+ m.insert_into phone_number_model, "include SmsOnRails::ModelSupport::PhoneNumber # include custom sms on rails phone number handling"
70
+ m.insert_into phone_number_model, "include SmsOnRails::ModelSupport::PhoneNumberAssociations # remove this for custom sms on rails associations"
71
+
72
+ sms_on_rails_dir = File.join("app", "models", "sms_on_rails")
73
+ m.directory sms_on_rails_dir
74
+ m.file "phone_number_collision.rb", File.join(sms_on_rails_dir, "phone_number.rb")
75
+ end
76
+ end
77
+
78
+ # add sms on rails dependencies such as the clickatell gem and static record cache
79
+ def add_dependencies(m)
80
+ add_clickatell_gem(m) if options[:default_service_provider] == :clickatell
81
+ logger.log 'plugin', 'static_record_cache'
82
+ run_template 'dependencies'
83
+ end
84
+
85
+ # add the clickatell gem dependency to the app's config/enviornment.rb file
86
+ def add_clickatell_gem(m)
87
+ logger.log 'gem', 'clickatell'
88
+ m.insert_into 'config/environment.rb', "config.gem 'clickatell'\n",
89
+ :margin => 2, :insert_after => /Rails::Initializer\.run.*\n/, :quiet => true
90
+ end
91
+
92
+ #copy up the public folder
93
+ def copy_assets(m)
94
+ create_app_files(m, 'public', :dest_base => '.', :relative_src => '/../../../')
95
+ end
96
+
97
+ # Use template runner to run specified template and output message
98
+ def run_template(template_name, message = nil)
99
+ logger.log message.first, message.last if message
100
+ logger.quiet = true
101
+ Rails::TemplateRunner.new(File.join(File.dirname(__FILE__),'runners', template_name + '.rb'), @destination_root)
102
+ ensure
103
+ logger.quiet = options[:quiet]
104
+ end
105
+
106
+ # generate the 3 sms on rails migrations by creating them in the main app dir
107
+ def generate_migration_templates(m)
108
+ generate_migration_template(m, :carrier) unless options[:skip_carriers]
109
+ generate_migration_template(m, :phone_number, phone_mig_options) unless options[:skip_phone_numbers]
110
+ generate_migration_template(m, :model) unless options[:skip_models]
111
+ end
112
+
113
+ #change to update if phone number exists
114
+ def phone_mig_options
115
+ if ActiveRecord::Base.connection.table_exists?(:phone_numbers)
116
+ {:migration_file_name => 'sms_on_rails_update_phone_numbers' }
117
+ else
118
+ {}
119
+ end
120
+ end
121
+
122
+ #generate the specified migration template
123
+ def generate_migration_template(m, migration_name, options={})
124
+ return if options[:skip_migration]
125
+
126
+ migration_file_name = options[:migration_file_name]||"sms_on_rails_create_#{migration_name}s"
127
+ template_file_name = (options[:migration_file_name]||'schema_migration') +'.rb'
128
+
129
+ m.migration_template "migrate/#{template_file_name}", 'db/migrate', :assigns => {
130
+ :migration_name => "#{migration_file_name.classify}s",
131
+ :files => ["sms_on_rails_#{migration_name}_tables"]
132
+ }, :migration_file_name => migration_file_name
133
+
134
+ end
135
+
136
+ def add_configuation_options(m)
137
+ add_require_all_models unless supports_engines?
138
+ add_dependencies(m)
139
+
140
+ logger.update "configuration options in environment.rb"
141
+ disable_logger do
142
+ add_service_provider_configuration(m)
143
+ add_default_service_provider(m)
144
+ end
145
+ end
146
+
147
+ protected
148
+
149
+ def disable_logger(&block)
150
+ logger.quiet = true
151
+ yield
152
+ ensure
153
+ logger.quiet = options[:quiet]
154
+ end
155
+
156
+ def add_service_provider_configuration(m)
157
+ SERVICE_PROVIDERS.each do |sp_name|
158
+ config_file = File.dirname(__FILE__) + "/templates/configuration/#{sp_name}.rb"
159
+ if File.exists?(config_file)
160
+ m.insert_into 'config/environment.rb', File.read(config_file),
161
+ :margin => 0, :append => true, :quiet => true,
162
+ :match => "SmsOnRails::ServiceProviders::#{sp_name.to_s.classify}.config"
163
+ end
164
+ end
165
+ end
166
+
167
+
168
+ def add_default_service_provider(m)
169
+ line = "#{SET_SERVICE_PROVIDER_CONFIG} #{options[:default_service_provider].to_sym.inspect}"
170
+
171
+ m.insert_into "config/environment.rb", line, :margin => 0, :quiet => true,
172
+ :replace => Regexp.new("#{SET_SERVICE_PROVIDER_CONFIG}.*(\\n|$)")
173
+ end
174
+
175
+
176
+ ##############################################################################
177
+ # Pre Rails engine support: copy to app directly
178
+ ##############################################################################
179
+
180
+ def create_views(m)
181
+ create_admin_view_files m
182
+ create_helper_files m
183
+ create_controller_files m
184
+ add_sms_routes
185
+ end
186
+
187
+ def copy_models(m)
188
+ create_app_files(m, 'models/sms_on_rails')
189
+ remove_require_all_models
190
+ end
191
+
192
+ def add_sms_routes
193
+ return if supports_engines?
194
+ run_template 'sms_on_rails_routes', ['routes', 'sms_on_rails routes']
195
+ end
196
+
197
+ #return true if the rails version has support for engines
198
+ def supports_engines?
199
+ @@supports_engines ||= ActiveRecord::VERSION::STRING >= '2.3.0'
200
+ end
201
+
202
+ # remove the require 'sms_on_rails/all_models.rb from environment.rb'
203
+ def remove_require_all_models
204
+ run_template 'remove_all_models', ['removing', 'references to vanilla models']
205
+ end
206
+
207
+ # add the require 'sms_on_rails/all_models.rb from environment.rb'
208
+ def add_require_all_models
209
+ if !@actions.include?('models') && !File.exists?(File.join(@destination_root, 'app/models/sms_on_rails'))
210
+ run_template 'add_all_models', ['using', 'all vanilla models']
211
+ end
212
+ end
213
+
214
+ # create admin views by copying to main app/views
215
+ def create_admin_view_files(m)
216
+ create_app_files(m, 'views/admin/sms_on_rails')
217
+ end
218
+
219
+ # create admin views by copying to main app/helper
220
+ def create_helper_files(m)
221
+ create_app_files(m, 'helpers/admin/sms_on_rails')
222
+ create_app_files(m, 'helpers/sms_on_rails')
223
+ end
224
+
225
+ # create admin views by copying to main app/controller
226
+ def create_controller_files(m)
227
+ create_app_files(m, 'controllers/admin/sms_on_rails')
228
+ end
229
+
230
+ #recursively copy files from templates/* to app/*
231
+ def create_app_files(m, dir, options={})
232
+
233
+ dest_base = options[:dest_base]||'app'
234
+ relative_src = (options[:relative_src]||'/../../../app').to_s
235
+ actual_src = File.join(source_root, relative_src)
236
+
237
+ m.directory(File.join(dest_base, dir))
238
+
239
+ Dir.glob(File.join(actual_src, dir, '*')) do |f|
240
+ relative_path = relative_source_path(f, actual_src)
241
+ if File.directory?(f)
242
+ create_app_files(m, relative_path, options)
243
+ else
244
+ m.file(File.join(relative_src, relative_path) , File.join(dest_base, relative_path))
245
+ end
246
+ end
247
+ end
248
+
249
+ #path relative to the source root
250
+ def relative_source_path(path, src_base = source_root)
251
+ File.expand_path(path).gsub(File.expand_path(src_base) + '/', '')
252
+ end
253
+
254
+ end
255
+