mxit-rails 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/mxit_rails/favicon.ico +0 -0
  5. data/app/assets/images/mxit_rails/go.png +0 -0
  6. data/app/assets/images/mxit_rails/in.png +0 -0
  7. data/app/assets/images/mxit_rails/nokia-5310-frame.png +0 -0
  8. data/app/assets/images/mxit_rails/out.png +0 -0
  9. data/app/assets/javascripts/mxit_rails/emulator.js +93 -0
  10. data/app/assets/javascripts/mxit_rails/jquery-1.8.0.min.js +2 -0
  11. data/app/assets/javascripts/mxit_rails/jquery.cookie.js +72 -0
  12. data/app/assets/stylesheets/mxit_rails/emulator.css.scss +173 -0
  13. data/app/assets/stylesheets/mxit_rails/included.css.scss +6 -0
  14. data/app/controllers/emulator_controller.rb +6 -0
  15. data/app/helpers/mxit_rails_helper.rb +35 -0
  16. data/app/views/emulator/index.html.erb +54 -0
  17. data/app/views/layouts/mxit.html.erb +53 -0
  18. data/app/views/mxit_rails/error.html.erb +2 -0
  19. data/config/routes.rb +5 -0
  20. data/lib/mxit-rails.rb +13 -0
  21. data/lib/mxit_rails/controller_extensions.rb +8 -0
  22. data/lib/mxit_rails/descriptor.rb +54 -0
  23. data/lib/mxit_rails/engine.rb +4 -0
  24. data/lib/mxit_rails/exception.rb +10 -0
  25. data/lib/mxit_rails/page.rb +187 -0
  26. data/lib/mxit_rails/railtie.rb +5 -0
  27. data/lib/mxit_rails/redirect_exception.rb +5 -0
  28. data/lib/mxit_rails/router.rb +11 -0
  29. data/lib/mxit_rails/styles.rb +25 -0
  30. data/lib/mxit_rails/validations.rb +21 -0
  31. data/lib/mxit_rails/version.rb +3 -0
  32. data/lib/tasks/mxit-rails_tasks.rake +4 -0
  33. data/test/dummy/README.rdoc +261 -0
  34. data/test/dummy/Rakefile +7 -0
  35. data/test/dummy/app/assets/javascripts/application.js +13 -0
  36. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  37. data/test/dummy/app/controllers/application_controller.rb +12 -0
  38. data/test/dummy/app/controllers/form_controller.rb +42 -0
  39. data/test/dummy/app/controllers/index_controller.rb +12 -0
  40. data/test/dummy/app/controllers/welcome_controller.rb +26 -0
  41. data/test/dummy/app/helpers/application_helper.rb +2 -0
  42. data/test/dummy/app/views/form/index/age.html.erb +4 -0
  43. data/test/dummy/app/views/form/index/done.html.erb +7 -0
  44. data/test/dummy/app/views/form/index/name.html.erb +4 -0
  45. data/test/dummy/app/views/form/index/start.html.erb +4 -0
  46. data/test/dummy/app/views/form/index/surname.html.erb +4 -0
  47. data/test/dummy/app/views/index/index.html.erb +6 -0
  48. data/test/dummy/app/views/index/success.html.erb +4 -0
  49. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/test/dummy/app/views/welcome/easter_egg.html.erb +4 -0
  51. data/test/dummy/app/views/welcome/index.html.erb +6 -0
  52. data/test/dummy/config/application.rb +59 -0
  53. data/test/dummy/config/boot.rb +10 -0
  54. data/test/dummy/config/database.yml +25 -0
  55. data/test/dummy/config/environment.rb +5 -0
  56. data/test/dummy/config/environments/development.rb +37 -0
  57. data/test/dummy/config/environments/production.rb +67 -0
  58. data/test/dummy/config/environments/test.rb +37 -0
  59. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  60. data/test/dummy/config/initializers/inflections.rb +15 -0
  61. data/test/dummy/config/initializers/mime_types.rb +5 -0
  62. data/test/dummy/config/initializers/secret_token.rb +7 -0
  63. data/test/dummy/config/initializers/session_store.rb +8 -0
  64. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  65. data/test/dummy/config/locales/en.yml +5 -0
  66. data/test/dummy/config/routes.rb +59 -0
  67. data/test/dummy/config.ru +4 -0
  68. data/test/dummy/db/development.sqlite3 +0 -0
  69. data/test/dummy/db/production.sqlite3 +0 -0
  70. data/test/dummy/log/development.log +29445 -0
  71. data/test/dummy/log/production.log +14 -0
  72. data/test/dummy/public/404.html +26 -0
  73. data/test/dummy/public/422.html +26 -0
  74. data/test/dummy/public/500.html +25 -0
  75. data/test/dummy/public/favicon.ico +0 -0
  76. data/test/dummy/public/index.html +26 -0
  77. data/test/dummy/script/rails +6 -0
  78. data/test/dummy/tmp/cache/assets/BF5/8C0/sprockets%2F78975330b80238b099744a81b812c803 +0 -0
  79. data/test/dummy/tmp/cache/assets/C9C/740/sprockets%2F3a56000c06453c8f0d7338c02df2a619 +0 -0
  80. data/test/dummy/tmp/cache/assets/CB3/340/sprockets%2F6176074062dc4ee8b1c0e9293973b8c1 +0 -0
  81. data/test/dummy/tmp/cache/assets/CBB/4B0/sprockets%2F84565b3ec7483468474ec41cbc1568b4 +0 -0
  82. data/test/dummy/tmp/cache/assets/CE1/DB0/sprockets%2F23cf9970f3b73a4a159e83fd1903d216 +0 -0
  83. data/test/dummy/tmp/cache/assets/CEB/750/sprockets%2F25cdf6f38dd877ab9524149059160ef1 +0 -0
  84. data/test/dummy/tmp/cache/assets/D03/D30/sprockets%2F039aef99b893884717dd47cbd5a47788 +0 -0
  85. data/test/dummy/tmp/cache/assets/D23/9D0/sprockets%2Fed6b8ea6bc85059f50a6257e47b86765 +0 -0
  86. data/test/dummy/tmp/cache/assets/D39/AA0/sprockets%2Fc45eb3a08b640eae8da941722428e38c +0 -0
  87. data/test/dummy/tmp/cache/assets/D45/960/sprockets%2Ff7a27b05b4c84c32ca5a49887a7b29c8 +0 -0
  88. data/test/dummy/tmp/cache/assets/D54/750/sprockets%2Fc16371b1a234c7c56cb01cb28a8bc5c3 +0 -0
  89. data/test/dummy/tmp/cache/assets/D56/060/sprockets%2F457df65dbf8649db0b377d828388db4b +0 -0
  90. data/test/dummy/tmp/cache/assets/D5B/540/sprockets%2Fe0e490354c54e5a850a6e3c3aa1ecb15 +0 -0
  91. data/test/dummy/tmp/cache/assets/D66/470/sprockets%2Facf17b280a44ef81b7a37d2c8e08070f +0 -0
  92. data/test/dummy/tmp/cache/assets/D6F/560/sprockets%2Fa572b066d908bae0d01dbc85f86a57d9 +0 -0
  93. data/test/dummy/tmp/cache/assets/D79/080/sprockets%2F9bba43c936e8d34a0d6bc9c6169c4f75 +0 -0
  94. data/test/dummy/tmp/cache/assets/D7A/C20/sprockets%2Fdbbf63c650611194adfc9276d6efa599 +0 -0
  95. data/test/dummy/tmp/cache/assets/D86/040/sprockets%2Fe7b969ffa4b195f4dd8553a3d62766ec +0 -0
  96. data/test/dummy/tmp/cache/assets/D99/110/sprockets%2Facbeeb823134865dd66d0489a7bcd00e +0 -0
  97. data/test/dummy/tmp/cache/assets/D9A/FD0/sprockets%2Ffadbf876155a124ed34b2e990f1c1cf4 +0 -0
  98. data/test/dummy/tmp/cache/assets/DAA/B80/sprockets%2Ff8082150f8c8beafcd445cc79a9a6a85 +0 -0
  99. data/test/dummy/tmp/cache/assets/DC7/E00/sprockets%2Fd24f3d9b3af0f25db8dd735d1564bdb1 +0 -0
  100. data/test/dummy/tmp/cache/assets/DF4/A00/sprockets%2F52e0cb214d2b778e61edb46c3b8eecca +0 -0
  101. data/test/dummy/tmp/cache/assets/DFB/940/sprockets%2F2faff4be90929be6a1b1de49ea25e33b +0 -0
  102. data/test/dummy/tmp/cache/assets/E15/260/sprockets%2Fea9c788716af4ccb19ff8e1d7ea47b8e +0 -0
  103. data/test/dummy/tmp/cache/assets/E26/4F0/sprockets%2F1cd8dafcb93f36aea8c2cf9d04c322d3 +0 -0
  104. data/test/dummy/tmp/cache/assets/E4F/E70/sprockets%2Fd9fffd76ac7c8ee08bedf3e257c81f99 +0 -0
  105. data/test/dummy/tmp/cache/assets/E76/0D0/sprockets%2Fcc9ce9eb21f4b4f9dbabfa0a3ca60b01 +0 -0
  106. data/test/dummy/tmp/pids/server.pid +1 -0
  107. data/test/integration/navigation_test.rb +10 -0
  108. data/test/mxit_rails_test.rb +7 -0
  109. data/test/test_helper.rb +15 -0
  110. metadata +283 -0
@@ -0,0 +1,173 @@
1
+ html, body {
2
+ margin: 0;
3
+ padding: 0;
4
+ overflow: hidden;
5
+ font-family: 'HelveticaNeue';
6
+ font-weight: normal;
7
+ }
8
+
9
+ #phone {
10
+ width: 240px;
11
+ height: 320px;
12
+ padding: 133px 56px 351px 56px;
13
+ margin: 35px auto 0 auto;
14
+ position: relative;
15
+ }
16
+ #phone.collapse {
17
+ background: none;
18
+ position: absolute;
19
+ top: 37px;
20
+ left: 0;
21
+ right: 0;
22
+ bottom: 0;
23
+ margin: 0;
24
+ padding: 0;
25
+ width: auto;
26
+ height: auto;
27
+ }
28
+ #screen {
29
+ width: 240px;
30
+ height: 320px;
31
+ position: relative;
32
+ overflow: hidden;
33
+ }
34
+ #phone.collapse #screen {
35
+ position: static;
36
+ width: 100%;
37
+ height: 100%;
38
+ }
39
+
40
+ iframe {
41
+ border: none;
42
+ margin: 0;
43
+ padding: 0;
44
+ }
45
+
46
+ .content {
47
+ width: 240px;
48
+ height: 320px;
49
+ position: absolute;
50
+ z-index: 1;
51
+ }
52
+ #phone.collapse .content {
53
+ width: 100%;
54
+ height: 100%;
55
+ }
56
+
57
+ #controls {
58
+ position: absolute;
59
+ top: 0;
60
+ left: 0;
61
+ right: 0;
62
+ height: 36px;
63
+ background-color: #eee;
64
+ border-bottom: 1px solid #999;
65
+ font-size: 14px;
66
+ line-height: 36px;
67
+ font-family: 'HelveticaNeue';
68
+ font-weight: normal;
69
+ text-align: center;
70
+ z-index: 1;
71
+ }
72
+ #not-registered, #registered {
73
+ float: left;
74
+ margin-left: 20px;
75
+ }
76
+ #registered {
77
+ display: none;
78
+ }
79
+ #mxit-id {
80
+ font-family: 'HelveticaNeue-Bold';
81
+ font-weight: normal;
82
+ }
83
+ #unlink, #link {
84
+ position: relative;
85
+ top: 0px;
86
+ float: right;
87
+ margin-right: 20px;
88
+ cursor: default;
89
+ }
90
+ #inputs {
91
+ display: none;
92
+ }
93
+
94
+
95
+ .link .icon {
96
+ width: 56px;
97
+ height: 56px;
98
+ border-radius: 56px;
99
+ border: 5px solid #fff;
100
+ box-shadow: 0 2px 2px rgba(64,64,64,0.4);
101
+ display: block;
102
+ background: -webkit-linear-gradient(-75deg, #f5a627 0%, #de6003 100%);
103
+ }
104
+ .link:active .icon { background: -webkit-linear-gradient(-75deg, #F58A27 0%, #CF3A00 100%); }
105
+ .link.disabled .icon { background: -webkit-linear-gradient(-75deg, #c6c6c6 0%, #7a7a7a 100%); }
106
+ .link .icon .image {
107
+ background-position: center;
108
+ background-repeat: no-repeat;
109
+ background-size: 50px;
110
+ width: 100%;
111
+ height: 100%;
112
+ display: block;
113
+ }
114
+
115
+ a.link {
116
+ padding: 0;
117
+ text-decoration: none;
118
+ font-family: 'HelveticaNeue-Medium';
119
+ font-weight: normal;
120
+ font-size: 14px;
121
+ color: #333;
122
+ position: relative;
123
+ top: 2px;
124
+ }
125
+ .link .icon {
126
+ width: 26px;
127
+ height: 26px;
128
+ border-radius: 26px;
129
+ border: 2px solid #fff;
130
+ display: inline-block;
131
+ vertical-align: middle;
132
+ position: relative;
133
+ top: -1px;
134
+ margin: 0 4px 4px 6px;
135
+ }
136
+ .link .icon .image {
137
+ background-size: 24px;
138
+ }
139
+ .in .icon .image, .out .icon .image {
140
+ background-size: 22px;
141
+ }
142
+
143
+ #expand {
144
+ position: absolute;
145
+ display: block;
146
+ right: 19px;
147
+ top: 27px;
148
+ }
149
+
150
+ #collapse {
151
+ position: absolute;
152
+ z-index: 10;
153
+ display: block;
154
+ right: 1px;
155
+ top: 5px;
156
+ display: none;
157
+ }
158
+ #phone.collapse #expand {
159
+ display: none;
160
+ }
161
+ #phone.collapse #collapse {
162
+ display: block;
163
+ }
164
+
165
+ #fadeout {
166
+ position: fixed;
167
+ height: 100px;
168
+ bottom: 0;
169
+ left: 0;
170
+ right: 0;
171
+ background: -webkit-linear-gradient(90deg, #fff 0%, #fff 5%, rgba(255,255,255,0.95) 15%, rgba(255,255,255,0) 100%);;
172
+ z-index: 10;
173
+ }
@@ -0,0 +1,6 @@
1
+ html, body {
2
+ margin: 2px;
3
+ padding: 0;
4
+ font-family: Helvetica, Arial, sans-serif;
5
+ font-weight: normal;
6
+ }
@@ -0,0 +1,6 @@
1
+ class EmulatorController < ApplicationController
2
+ layout false
3
+
4
+ def index
5
+ end
6
+ end
@@ -0,0 +1,35 @@
1
+ module MxitRailsHelper
2
+
3
+ def mxit_path route
4
+ MxitRails::Router.url route
5
+ end
6
+
7
+ def mxit_link route, label, variables=nil
8
+ unless variables.nil?
9
+ var_strings = []
10
+ #TODO: Use default Rails get encoding
11
+ variables.each do |key, value|
12
+ var_strings << "#{key}=#{value}"
13
+ end
14
+ route += "?#{var_strings.join('&')}"
15
+ end
16
+ output = "<a href=\"#{route}\">#{label}</a>".html_safe
17
+ end
18
+
19
+ def mxit_style *names
20
+ content = []
21
+ names.each do |name|
22
+ content << MxitRails::Styles.get(name) || ''
23
+ end
24
+ content.join(' ').html_safe
25
+ end
26
+
27
+ def mxit_nav_link target, label
28
+ "<p style=\"#{ mxit_style :right }\">#{ mxit_link target, label }</p>".html_safe
29
+ end
30
+
31
+ def mxit_proceed content
32
+ "<p><b style=\"#{ mxit_style :link }\">&gt; #{content}</b></p>".html_safe
33
+ end
34
+
35
+ end
@@ -0,0 +1,54 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Mxit Emulator</title>
5
+ <meta charset="UTF-8" />
6
+
7
+ <%= stylesheet_link_tag "mxit_rails/emulator" %>
8
+ <%= javascript_include_tag "mxit_rails/emulator" %>
9
+
10
+ <link rel="icon" type="image/x-icon" href="<%= image_path("mxit_rails/favicon.ico"); %>" />
11
+
12
+ <script type="text/javascript">
13
+ MXIT_ROOT = '<%= Rails.application.config.mxit_root %>';
14
+ </script>
15
+
16
+ <!-- The asset image-path helper isn't working in scss files, so moving those to here. sigh. -->
17
+ <style type="text/css">
18
+ #phone { background: url(<%= image_path("mxit_rails/nokia-5310-frame.png") %>) no-repeat; }
19
+ .go > .icon .image { background-image: url(<%= image_path("mxit_rails/go.png"); %>) }
20
+ .in > .icon .image { background-image: url(<%= image_path("mxit_rails/in.png"); %>) }
21
+ .out > .icon .image { background-image: url(<%= image_path("mxit_rails/out.png"); %>) }
22
+ </style>
23
+ </head>
24
+ <body>
25
+
26
+ <div id="controls">
27
+ <div id="default">
28
+ <span id="not-registered">No credentials</span>
29
+ <span id="registered">Mxit ID: <span id="mxit-id"></span></span>
30
+
31
+ <a id="unlink" class="go link" onclick="Emulator.clearCredentials()">Clear Credentials <span class="icon"><span class="image"></span></span></a>
32
+ <a id="link" class="go link" onclick="Emulator.enterCredentials()">Set Credentials <span class="icon"><span class="image"></span></span></a>
33
+ </div>
34
+
35
+ <div id="inputs">
36
+ <input type="text" placeholder="Mxit ID" id="mxit-id-input" />
37
+ <input type="text" placeholder="MSISDN" id="msisdn-input" />
38
+
39
+ <a id="link" class="go link" onclick="Emulator.saveCredentials()">Save <span class="icon"><span class="image"></span></span></a>
40
+ </div>
41
+ </div>
42
+
43
+ <div id="phone">
44
+ <a id="expand" class="out link" onclick="Emulator.expand()"><span class="icon"><span class="image"></span></span></a>
45
+ <a id="collapse" class="in link" onclick="Emulator.collapse()"><span class="icon"><span class="image"></span></span></a>
46
+ <div id="screen">
47
+ <iframe id="center" class="content" onLoad="Emulator.updateIframe(this)"></iframe>
48
+ </div>
49
+ </div>
50
+
51
+ <div id="fadeout"></div>
52
+
53
+ </body>
54
+ </html>
@@ -0,0 +1,53 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml">
4
+
5
+ <head>
6
+ <title>Mxit App</title>
7
+
8
+ <meta name="mxit" content="no_prefix,show_progress,clear_on_new,no_heading" />
9
+
10
+ <% if request.headers['x-mxit-login'].nil? %>
11
+ <!-- Include a CSS file, but only in a browser/emulator, not on mxit -->
12
+ <%= stylesheet_link_tag "mxit_rails/included" %>
13
+ <% end %>
14
+
15
+ <style type="text/css">
16
+ a:hover { <%= mxit_style :link_hover %> }
17
+ a { <%= mxit_style :link %> }
18
+ </style>
19
+ </head>
20
+
21
+ <body style="<%= mxit_style :body %>">
22
+
23
+ <table title="mxit:table:full" style="width:100%" name="title_table" cellspacing="0" cellpadding="0">
24
+ <colgroup span="1" width="100%"></colgroup>
25
+ <tr>
26
+ <td style="<%= mxit_style :title %>">
27
+ <b><%= yield :title %></b>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+
32
+ <%= yield :navigation %>
33
+
34
+ <% if !@_mxit_validated %>
35
+ <%= @_mxit_validation_messages.first %>
36
+
37
+ <% else %>
38
+ <%= yield %>
39
+ <% end %>
40
+
41
+ <% if @_mxit.input %>
42
+ <%= mxit_proceed @_mxit.input_label %>
43
+ <form method="POST" action="<%= @_mxit.url %>">
44
+ <input type="text" name="<%= @_mxit.input %>" />
45
+ <input type="submit" name="_mxit_rails_submit" value="Proceed" />
46
+ </form>
47
+
48
+ <% elsif @_mxit.proceed %>
49
+ <%= mxit_proceed mxit_link(@_mxit.url, @_mxit.proceed.to_s.capitalize, {_mxit_rails_submit: 'Proceed'}) %>
50
+ <% end %>
51
+
52
+ </body>
53
+ </html>
@@ -0,0 +1,2 @@
1
+ <p><%= @_mxit_error_message %></p>
2
+
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Rails.application.routes.draw do
2
+
3
+ match '/emulator', :controller => 'emulator', :action => 'index'
4
+
5
+ end
data/lib/mxit-rails.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "mxit_rails/railtie"
2
+ require "mxit_rails/exception"
3
+ require "mxit_rails/redirect_exception"
4
+ require "mxit_rails/descriptor"
5
+ require "mxit_rails/engine"
6
+ require "mxit_rails/styles"
7
+ require "mxit_rails/controller_extensions"
8
+ require "mxit_rails/validations"
9
+ require "mxit_rails/router"
10
+ require "mxit_rails/page"
11
+
12
+ module MxitRails
13
+ end
@@ -0,0 +1,8 @@
1
+ module MxitRails
2
+ module ControllerExtensions
3
+ def mxit_style name, content
4
+ MxitRails::Styles.add name, content
5
+ end
6
+ end
7
+ end
8
+ ActionController::Base.extend(MxitRails::ControllerExtensions)
@@ -0,0 +1,54 @@
1
+ module MxitRails
2
+ class Descriptor
3
+ def self.descr_accessor variable
4
+ # Custom accessor macro that will look in a parent descriptor if a value isn't found (i.e. is nil)
5
+ attr_writer variable
6
+ define_method "#{variable}" do
7
+ value = instance_variable_get("@#{variable}")
8
+ if value.nil? && !parent_descriptor.nil?
9
+ value = parent_descriptor.send("#{variable}")
10
+ end
11
+ value
12
+ end
13
+ end
14
+
15
+ attr_accessor :parent_descriptor
16
+
17
+ attr_accessor :name
18
+ attr_accessor :type
19
+
20
+ descr_accessor :proceed
21
+
22
+ attr_accessor :input
23
+ attr_accessor :input_label
24
+
25
+ attr_accessor :validations
26
+
27
+ def initialize name, parent=nil
28
+ @parent_descriptor = parent
29
+ self.name = name.to_sym
30
+ @validations = []
31
+ @steps = []
32
+ end
33
+
34
+ def add_validation type, message, parameter
35
+ @validations << {type: type, message: message, parameter: parameter}
36
+ end
37
+
38
+ def url
39
+ MxitRails::Router.url name
40
+ end
41
+
42
+ def view
43
+ view = MxitRails::Router.url name
44
+ unless step.nil?
45
+ view += "/#{step}"
46
+ end
47
+ view
48
+ end
49
+
50
+ def form?
51
+ type == :form
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,4 @@
1
+ module MxitRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module MxitRails
2
+ class Exception < Exception
3
+ attr_reader :message
4
+ attr_reader :code
5
+ def initialize message, code
6
+ @message = message
7
+ @code = code
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,187 @@
1
+ module MxitRails
2
+ module Page
3
+ extend ActiveSupport::Concern
4
+
5
+ def mxit_params
6
+ @_mxit_params
7
+ end
8
+
9
+ def set_descriptor name, parent_name=:default
10
+ @descriptors ||= {}
11
+ @descriptors[name] ||= MxitRails::Descriptor.new controller_name, @descriptors[parent_name]
12
+ @descriptor_name = name
13
+ end
14
+ def descriptor
15
+ @descriptors[@descriptor_name]
16
+ end
17
+
18
+ included do
19
+ if self.ancestors.include? ApplicationController
20
+ send :rescue_from, MxitRails::Exception, :with => :handle_mxit_exception
21
+ send :layout, 'mxit'
22
+ send :before_filter, :setup
23
+ end
24
+ end
25
+
26
+ def redirect! route
27
+ exception = MxitRails::RedirectException.new('', :redirect)
28
+ exception.route = route
29
+ raise exception
30
+ end
31
+
32
+ def validate! input
33
+ descriptor.validations.each do |validation|
34
+ method = validation[:type].to_s + '?' #All validations are defined with a trailing question mark
35
+ parameter = validation[:parameter]
36
+ # Call with/out a parameter, depending on whether one is specified
37
+ valid = parameter ? MxitRails::Validations.send(method, input, parameter) : MxitRails::Validations.send(method, input)
38
+ if !valid
39
+ @_mxit_validated = false
40
+ @_mxit_validation_messages << validation[:message]
41
+ end
42
+ end
43
+ end
44
+
45
+ def get_mxit_header_field key
46
+ request.headers[key] || cookies[key.downcase]
47
+ end
48
+
49
+ def get_mxit_info
50
+ @_mxit_params = {}
51
+ @_mxit_params[:m_id] = get_mxit_header_field 'X-Mxit-UserId-R'
52
+ @_mxit_params[:username] = get_mxit_header_field 'x-mxit-login'
53
+
54
+ device_info = get_mxit_header_field('X-Mxit-Device-Info')
55
+ unless device_info.blank?
56
+ device_info.split(',')
57
+ @_mxit_params[:distribution_code] = device_info.first
58
+ @_mxit_params[:mobile_number] = device_info[1] if device_info.length == 2
59
+ end
60
+ end
61
+
62
+
63
+ # Rails controller stuff
64
+ #========================
65
+
66
+ def setup
67
+ set_descriptor :default
68
+
69
+ get_mxit_info
70
+
71
+ @_mxit = descriptor
72
+ @_mxit_validated = true
73
+ @_mxit_validation_messages = []
74
+
75
+ clean_session
76
+ end
77
+
78
+ def clean_session
79
+ # Drop all mxit items from session if the page doesn't match the current one
80
+ if session[:_mxit_rails_page] != "#{controller_name}##{action_name}"
81
+ session.each do |key, value|
82
+ if key.to_s.match(/_mxit_rails_/)
83
+ session[key] = nil
84
+ end
85
+ end
86
+ session[:_mxit_rails_page] = "#{controller_name}##{action_name}"
87
+ end
88
+ end
89
+
90
+ def handle_mxit_exception exception
91
+ if exception.kind_of? MxitRails::RedirectException
92
+ redirect_to(exception.route) and return
93
+ end
94
+ end
95
+
96
+ def input input_name, input_label
97
+ descriptor.input = input_name
98
+ descriptor.input_label = input_label
99
+ end
100
+ def proceed label
101
+ descriptor.proceed = label
102
+ end
103
+
104
+ def validate *arguments
105
+ type = arguments[0]
106
+ message = arguments[-1]
107
+ parameter = arguments[1..-2][0] # Will return nil if there isn't an argument
108
+ descriptor.add_validation type, message, parameter
109
+ end
110
+
111
+ def submit &block
112
+ set_descriptor :default
113
+
114
+ if descriptor.form? && next_step?
115
+ instance_eval &block
116
+
117
+ elsif params.include?(:_mxit_rails_submit)
118
+ unless descriptor.input.nil?
119
+ input = descriptor.input.to_sym
120
+ validate! params[input]
121
+ end
122
+
123
+ instance_eval &block if @_mxit_validated
124
+ end
125
+ end
126
+
127
+
128
+ def current_step
129
+ return nil if session[:_mxit_rails_step].nil?
130
+ session[:_mxit_rails_step].to_sym
131
+ end
132
+ def current_step= new_step
133
+ session[:_mxit_rails_step] = new_step.to_sym
134
+ end
135
+ def next_step?
136
+ @next_step
137
+ end
138
+
139
+ def step step_name, &block
140
+ # Is the current step blank
141
+ if next_step?
142
+ self.current_step = step_name
143
+ @next_step = false
144
+ end
145
+
146
+ set_descriptor step_name
147
+ instance_eval &block
148
+
149
+ # Process the form if it is the current step
150
+ if current_step == step_name
151
+ if params.include?(:_mxit_rails_submit)
152
+ # Validate the current input if present
153
+ unless descriptor.input.nil?
154
+ input = descriptor.input.to_sym
155
+ validate! params[input]
156
+ session[:_mxit_rails_params][input] = params[input] if @_mxit_validated
157
+ end
158
+
159
+ if @_mxit_validated
160
+ params.delete :_mxit_rails_submit
161
+ @next_step = true
162
+ return
163
+ end
164
+ end
165
+
166
+ # Render the form if appropriate
167
+ @_mxit = descriptor
168
+ render "#{controller_name}/#{action_name}/#{current_step}"
169
+ end
170
+ end
171
+
172
+ def form &block
173
+ descriptor.type = :form
174
+ session[:_mxit_rails_params] ||= {}
175
+
176
+ # Ensure previous inputs are in the params hash
177
+ session[:_mxit_rails_params].each do |key, value|
178
+ params[key.to_sym] = value
179
+ end
180
+
181
+ # Proceed to the (first) step if no step is in the session
182
+ @next_step = true if session[:_mxit_rails_step].nil?
183
+
184
+ instance_eval &block
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,5 @@
1
+ module MxitRails
2
+ class Railtie < Rails::Railtie
3
+ config.mxit_root = 'mxit'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module MxitRails
2
+ class RedirectException < MxitRails::Exception
3
+ attr_accessor :route
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module MxitRails
2
+ class Router
3
+ def self.url route
4
+ path = []
5
+ root = Rails.application.config.mxit_root
6
+ path << root unless root.blank?
7
+ path << route.to_s
8
+ path = '/' + path.join('/')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ module MxitRails
2
+ module Styles
3
+
4
+ # Not sure whether a Constant is the neatest/nicest way of storing these?
5
+ StyleList = {}
6
+
7
+ def self.get name
8
+ StyleList[name.to_sym]
9
+ end
10
+
11
+ def self.add name, content
12
+ content.strip!
13
+ if content[-1] != ';'
14
+ content += ';'
15
+ end
16
+ StyleList[name.to_sym] = content
17
+ end
18
+
19
+ # Default styles
20
+ add :left, 'text-align:left;'
21
+ add :center, 'text-align:center;'
22
+ add :right, 'text-align:right;'
23
+
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module MxitRails
2
+ class Validations
3
+
4
+ def self.not_blank? input
5
+ return !input.blank?
6
+ end
7
+
8
+ def self.numeric? input
9
+ return !input.blank? && input.match(/^[0-9]+$/)
10
+ end
11
+
12
+ def self.min_length? input, max
13
+ return !input.blank? && (input.length >= max)
14
+ end
15
+
16
+ def self.max_length? input, max
17
+ return input.blank? || (input.length <= max)
18
+ end
19
+
20
+ end
21
+ end