controll 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +19 -0
  4. data/Gemfile.lock +134 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +320 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/controll.gemspec +184 -0
  10. data/lib/controll.rb +14 -0
  11. data/lib/controll/assistant.rb +19 -0
  12. data/lib/controll/command.rb +24 -0
  13. data/lib/controll/commander.rb +24 -0
  14. data/lib/controll/errors.rb +1 -0
  15. data/lib/controll/executor.rb +6 -0
  16. data/lib/controll/executor/base.rb +16 -0
  17. data/lib/controll/executor/notificator.rb +12 -0
  18. data/lib/controll/flow_handler.rb +11 -0
  19. data/lib/controll/flow_handler/base.rb +19 -0
  20. data/lib/controll/flow_handler/control.rb +85 -0
  21. data/lib/controll/flow_handler/errors.rb +5 -0
  22. data/lib/controll/flow_handler/event_helper.rb +18 -0
  23. data/lib/controll/flow_handler/redirect.rb +51 -0
  24. data/lib/controll/flow_handler/redirect/action.rb +45 -0
  25. data/lib/controll/flow_handler/redirect/mapper.rb +41 -0
  26. data/lib/controll/flow_handler/render.rb +51 -0
  27. data/lib/controll/helper.rb +101 -0
  28. data/lib/controll/helper/event_matcher.rb +21 -0
  29. data/lib/controll/helper/hash_access.rb +26 -0
  30. data/lib/controll/helper/notify.rb +74 -0
  31. data/lib/controll/helper/params.rb +20 -0
  32. data/lib/controll/helper/path_resolver.rb +45 -0
  33. data/lib/controll/helper/session.rb +20 -0
  34. data/lib/controll/notify.rb +7 -0
  35. data/lib/controll/notify/base.rb +75 -0
  36. data/lib/controll/notify/flash.rb +52 -0
  37. data/lib/controll/notify/typed.rb +39 -0
  38. data/spec/acceptance/app_test.rb +156 -0
  39. data/spec/app/.gitignore +15 -0
  40. data/spec/app/Gemfile +6 -0
  41. data/spec/app/Gemfile.lock +108 -0
  42. data/spec/app/README.rdoc +261 -0
  43. data/spec/app/Rakefile +7 -0
  44. data/spec/app/app/controllers/application_controller.rb +6 -0
  45. data/spec/app/app/controllers/posts_controller.rb +52 -0
  46. data/spec/app/app/models/.gitkeep +0 -0
  47. data/spec/app/app/models/post.rb +88 -0
  48. data/spec/app/app/views/layouts/application.html.erb +13 -0
  49. data/spec/app/app/views/posts/_form.html.erb +31 -0
  50. data/spec/app/app/views/posts/edit.html.erb +6 -0
  51. data/spec/app/app/views/posts/index.html.erb +23 -0
  52. data/spec/app/app/views/posts/new.html.erb +5 -0
  53. data/spec/app/app/views/posts/show.html.erb +8 -0
  54. data/spec/app/config.ru +4 -0
  55. data/spec/app/config/application.rb +16 -0
  56. data/spec/app/config/boot.rb +6 -0
  57. data/spec/app/config/environment.rb +5 -0
  58. data/spec/app/config/environments/development.rb +21 -0
  59. data/spec/app/config/environments/test.rb +29 -0
  60. data/spec/app/config/initializers/backtrace_silencers.rb +7 -0
  61. data/spec/app/config/initializers/inflections.rb +15 -0
  62. data/spec/app/config/initializers/mime_types.rb +5 -0
  63. data/spec/app/config/initializers/secret_token.rb +7 -0
  64. data/spec/app/config/initializers/session_store.rb +8 -0
  65. data/spec/app/config/locales/en.yml +5 -0
  66. data/spec/app/config/routes.rb +62 -0
  67. data/spec/app/db/seeds.rb +7 -0
  68. data/spec/app/lib/assets/.gitkeep +0 -0
  69. data/spec/app/lib/tasks/.gitkeep +0 -0
  70. data/spec/app/log/.gitkeep +0 -0
  71. data/spec/app/public/404.html +26 -0
  72. data/spec/app/public/422.html +26 -0
  73. data/spec/app/public/500.html +25 -0
  74. data/spec/app/public/favicon.ico +0 -0
  75. data/spec/app/public/index.html +241 -0
  76. data/spec/app/public/javascripts/application.js +9663 -0
  77. data/spec/app/public/robots.txt +5 -0
  78. data/spec/app/public/stylesheets/application.css +83 -0
  79. data/spec/app/script/rails +6 -0
  80. data/spec/app/spec/controllers/posts_controller_spec.rb +59 -0
  81. data/spec/app/spec/isolated_spec_helper.rb +6 -0
  82. data/spec/app/spec/spec_helper.rb +5 -0
  83. data/spec/app/spec/unit/controllers/posts_controller_isolated_spec.rb +63 -0
  84. data/spec/app/spec/unit/controllers/posts_controller_spec.rb +59 -0
  85. data/spec/app/test/functional/.gitkeep +0 -0
  86. data/spec/app/test/functional/posts_controller_test.rb +67 -0
  87. data/spec/app/test/isolated_test_helper.rb +7 -0
  88. data/spec/app/test/test_helper.rb +6 -0
  89. data/spec/app/test/unit/.gitkeep +0 -0
  90. data/spec/app/test/unit/controllers/posts_controller_isolated_test.rb +71 -0
  91. data/spec/app/test/unit/controllers/posts_controller_test.rb +67 -0
  92. data/spec/app/vendor/assets/javascripts/.gitkeep +0 -0
  93. data/spec/app/vendor/assets/stylesheets/.gitkeep +0 -0
  94. data/spec/app/vendor/plugins/.gitkeep +0 -0
  95. data/spec/controll/asssistant_spec.rb +5 -0
  96. data/spec/controll/command_spec.rb +56 -0
  97. data/spec/controll/commander_spec.rb +68 -0
  98. data/spec/controll/executor/notificator_spec.rb +27 -0
  99. data/spec/controll/flow_handler/control_spec.rb +159 -0
  100. data/spec/controll/flow_handler/redirect/action_spec.rb +48 -0
  101. data/spec/controll/flow_handler/redirect/mapper_spec.rb +69 -0
  102. data/spec/controll/flow_handler/redirect_spec.rb +93 -0
  103. data/spec/controll/flow_handler/render_spec.rb +110 -0
  104. data/spec/controll/helper/event_matcher_spec.rb +21 -0
  105. data/spec/controll/helper/hash_access_spec.rb +25 -0
  106. data/spec/controll/helper/notify_spec.rb +48 -0
  107. data/spec/controll/helper/params_spec.rb +28 -0
  108. data/spec/controll/helper/path_resolver_spec.rb +49 -0
  109. data/spec/controll/helper/session_spec.rb +28 -0
  110. data/spec/controll/helper_spec.rb +108 -0
  111. data/spec/controll/notify/base_spec.rb +123 -0
  112. data/spec/controll/notify/flash_spec.rb +27 -0
  113. data/spec/controll/notify/message_handler.rb +72 -0
  114. data/spec/controll/notify/typed_spec.rb +28 -0
  115. data/spec/functional_test_helper.rb +25 -0
  116. data/spec/helper.rb +33 -0
  117. data/spec/rspec_controller_class.rb +15 -0
  118. data/spec/rspec_functional_helper.rb +25 -0
  119. data/spec/rspec_helper.rb +42 -0
  120. data/spec/spec_helper.rb +11 -0
  121. data/spec/test_helper.rb +183 -0
  122. data/spec/unit/functional_test_helper_test.rb +65 -0
  123. data/spec/unit/macros_test.rb +43 -0
  124. data/spec/unit/mixin_test.rb +147 -0
  125. data/spec/unit/rspec_functional_helper.rb +42 -0
  126. data/spec/unit/rspec_helper_test.rb +91 -0
  127. data/spec/unit/test_helper_test.rb +235 -0
  128. metadata +289 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source :rubygems
2
+
3
+ gem 'hashie', '~> 1.2'
4
+ gem 'liquid'
5
+
6
+ group :test do
7
+ gem 'i18n', '>= 0.6'
8
+ gem 'rails', '~> 3'
9
+ gem 'imperator-ext', '~> 0.2.0' #, path: '/Users/kmandrup/private/repos/imperator-ext' #, :git => 'git://github.com/kristianmandrup/imperator-ext.git'
10
+ gem 'focused_controller', :git => 'git://github.com/kristianmandrup/focused_controller.git'
11
+ end
12
+
13
+ group :development do
14
+ gem "rspec", ">= 2.8.0"
15
+ gem "rdoc", ">= 3.12"
16
+ gem "bundler", ">= 1.0.0"
17
+ gem "jeweler", ">= 1.8.4"
18
+ gem "simplecov",">= 0.5"
19
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,134 @@
1
+ GIT
2
+ remote: git://github.com/kristianmandrup/focused_controller.git
3
+ revision: 729d753a62abf4eadcfd76123f643973392bec3a
4
+ specs:
5
+ focused_controller (0.1.0)
6
+ actionpack (~> 3.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionmailer (3.2.7)
12
+ actionpack (= 3.2.7)
13
+ mail (~> 2.4.4)
14
+ actionpack (3.2.7)
15
+ activemodel (= 3.2.7)
16
+ activesupport (= 3.2.7)
17
+ builder (~> 3.0.0)
18
+ erubis (~> 2.7.0)
19
+ journey (~> 1.0.4)
20
+ rack (~> 1.4.0)
21
+ rack-cache (~> 1.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.1.3)
24
+ activemodel (3.2.7)
25
+ activesupport (= 3.2.7)
26
+ builder (~> 3.0.0)
27
+ activerecord (3.2.7)
28
+ activemodel (= 3.2.7)
29
+ activesupport (= 3.2.7)
30
+ arel (~> 3.0.2)
31
+ tzinfo (~> 0.3.29)
32
+ activeresource (3.2.7)
33
+ activemodel (= 3.2.7)
34
+ activesupport (= 3.2.7)
35
+ activesupport (3.2.7)
36
+ i18n (~> 0.6)
37
+ multi_json (~> 1.0)
38
+ arel (3.0.2)
39
+ backports (2.6.3)
40
+ builder (3.0.0)
41
+ diff-lcs (1.1.3)
42
+ erubis (2.7.0)
43
+ git (1.2.5)
44
+ hashie (1.2.0)
45
+ hike (1.2.1)
46
+ i18n (0.6.0)
47
+ imperator (0.2.0)
48
+ activemodel
49
+ uuidtools
50
+ virtus
51
+ imperator-ext (0.2.1)
52
+ imperator
53
+ virtus
54
+ jeweler (1.8.4)
55
+ bundler (~> 1.0)
56
+ git (>= 1.2.5)
57
+ rake
58
+ rdoc
59
+ journey (1.0.4)
60
+ json (1.7.4)
61
+ liquid (2.3.0)
62
+ mail (2.4.4)
63
+ i18n (>= 0.4.0)
64
+ mime-types (~> 1.16)
65
+ treetop (~> 1.4.8)
66
+ mime-types (1.19)
67
+ multi_json (1.3.6)
68
+ polyglot (0.3.3)
69
+ rack (1.4.1)
70
+ rack-cache (1.2)
71
+ rack (>= 0.4)
72
+ rack-ssl (1.3.2)
73
+ rack
74
+ rack-test (0.6.1)
75
+ rack (>= 1.0)
76
+ rails (3.2.7)
77
+ actionmailer (= 3.2.7)
78
+ actionpack (= 3.2.7)
79
+ activerecord (= 3.2.7)
80
+ activeresource (= 3.2.7)
81
+ activesupport (= 3.2.7)
82
+ bundler (~> 1.0)
83
+ railties (= 3.2.7)
84
+ railties (3.2.7)
85
+ actionpack (= 3.2.7)
86
+ activesupport (= 3.2.7)
87
+ rack-ssl (~> 1.3.2)
88
+ rake (>= 0.8.7)
89
+ rdoc (~> 3.4)
90
+ thor (>= 0.14.6, < 2.0)
91
+ rake (0.9.2.2)
92
+ rdoc (3.12)
93
+ json (~> 1.4)
94
+ rspec (2.11.0)
95
+ rspec-core (~> 2.11.0)
96
+ rspec-expectations (~> 2.11.0)
97
+ rspec-mocks (~> 2.11.0)
98
+ rspec-core (2.11.1)
99
+ rspec-expectations (2.11.2)
100
+ diff-lcs (~> 1.1.3)
101
+ rspec-mocks (2.11.1)
102
+ simplecov (0.6.4)
103
+ multi_json (~> 1.0)
104
+ simplecov-html (~> 0.5.3)
105
+ simplecov-html (0.5.3)
106
+ sprockets (2.1.3)
107
+ hike (~> 1.2)
108
+ rack (~> 1.0)
109
+ tilt (~> 1.1, != 1.3.0)
110
+ thor (0.15.4)
111
+ tilt (1.3.3)
112
+ treetop (1.4.10)
113
+ polyglot
114
+ polyglot (>= 0.3.1)
115
+ tzinfo (0.3.33)
116
+ uuidtools (2.1.3)
117
+ virtus (0.5.1)
118
+ backports (~> 2.6.1)
119
+
120
+ PLATFORMS
121
+ ruby
122
+
123
+ DEPENDENCIES
124
+ bundler (>= 1.0.0)
125
+ focused_controller!
126
+ hashie (~> 1.2)
127
+ i18n (>= 0.6)
128
+ imperator-ext (~> 0.2.0)
129
+ jeweler (>= 1.8.4)
130
+ liquid
131
+ rails (~> 3)
132
+ rdoc (>= 3.12)
133
+ rspec (>= 2.8.0)
134
+ simplecov (>= 0.5)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Kristian Mandrup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # Controll
2
+
3
+ Some nice and nifty utilities to help you manage complex controller logic.
4
+
5
+ ## Background
6
+
7
+ This gem contains logic extracted from my `oauth_assist` gem/engine which again was a response to this article [oauth pure tutorial](http://www.communityguides.eu/articles/16).
8
+
9
+ ## Justification
10
+
11
+ As you can see, the following `#create` REST action is a nightmare of complexity and flow control leading to various different flash messages and redirect/render depending on various outcomes... there MUST be a better way!
12
+
13
+ ```ruby
14
+ def create
15
+ # get the service parameter from the Rails router
16
+ params[:service] ? service_route = params[:service] : service_route = 'No service recognized (invalid callback)'
17
+
18
+ # get the full hash from omniauth
19
+ omniauth = request.env['omniauth.auth']
20
+
21
+ # continue only if hash and parameter exist
22
+ if omniauth and params[:service]
23
+
24
+ # map the returned hashes to our variables first - the hashes differs for every service
25
+
26
+ # create a new hash
27
+ @authhash = Hash.new
28
+
29
+ extract_auth_data!
30
+
31
+ if unknown_auth?
32
+ # debug to output the hash that has been returned when adding new services
33
+ render :text => omniauth.to_yaml
34
+ return
35
+ end
36
+
37
+ if @authhash[:uid] != '' and @authhash[:provider] != ''
38
+
39
+ auth = Service.find_by_provider_and_uid(@authhash[:provider], @authhash[:uid])
40
+
41
+ # if the user is currently signed in, he/she might want to add another account to signin
42
+ if user_signed_in?
43
+ if auth
44
+ flash[:notice] = 'Your account at ' + @authhash[:provider].capitalize + ' is already connected with this site.'
45
+ redirect_to services_path
46
+ else
47
+ current_user.services.create!(:provider => @authhash[:provider], :uid => @authhash[:uid], :uname => @authhash[:name], :uemail => @authhash[:email])
48
+ flash[:notice] = 'Your ' + @authhash[:provider].capitalize + ' account has been added for signing in at this site.'
49
+ redirect_to services_path
50
+ end
51
+ else
52
+ if auth
53
+ # signin existing user
54
+ # in the session his user id and the service id used for signing in is stored
55
+ session[:user_id] = auth.user.id
56
+ session[:service_id] = auth.id
57
+
58
+ flash[:notice] = 'Signed in successfully via ' + @authhash[:provider].capitalize + '.'
59
+ redirect_to root_url
60
+ else
61
+ # this is a new user; show signup; @authhash is available to the view and stored in the sesssion for creation of a new user
62
+ session[:authhash] = @authhash
63
+ render signup_services_path
64
+ end
65
+ end
66
+ else
67
+ flash[:error] = 'Error while authenticating via ' + service_route + '/' + @authhash[:provider].capitalize + '. The service returned invalid data for the user id.'
68
+ redirect_to signin_path
69
+ end
70
+ else
71
+ flash[:error] = 'Error while authenticating via ' + service_route.capitalize + '. The service did not return valid data.'
72
+ redirect_to signin_path
73
+ end
74
+ end
75
+ ```
76
+
77
+ Using the tools contained in `controll` the above logic can be encapsulated like this:
78
+
79
+ ```ruby
80
+ def create
81
+ FlowHandler::CreateService.new(self).execute
82
+ end
83
+ ```
84
+
85
+ A `FlowHandler` can use Executors to encapsulate execution logic, which again can execute Commands that encapsulate business logic related to the user Session or models (data).
86
+
87
+ The FlowHandler can manage Redirect, Render and Notifications in a standardized, much more Object Oriented fashion, which adheres to the Single Responsibility pattern.
88
+
89
+ Controll has built in notification management which work both for flash messages (or other types of notifications) and as return codes for use in flow-control logic.
90
+
91
+ Using the `controll` helpers, you can avoid the typical Rails anti-pattern of Thick controllers, without bloating your Models with unrelated model logic or pulling in various Helper modules which pollute the space of the Controller anyhow!
92
+
93
+ ## Usage
94
+
95
+ In your controller include the `Controll::Helper` helper module.
96
+
97
+ ```ruby
98
+ class ServicesController < ApplicationController
99
+ before_filter :authenticate_user!, :except => accessible_actions
100
+ protect_from_forgery :except => :create
101
+
102
+ # see 'controll' gem
103
+ include Controll::Helper
104
+ end
105
+ ```
106
+
107
+ Better yet, to make it available for all controllers, include it in your ApplicationController or any base controller of your choice.
108
+
109
+ ```ruby
110
+ class ApplicationController
111
+ include Controll::Helper
112
+ end
113
+ ```
114
+
115
+ In your Controller you should define a MessageHandler and Commander to be used.
116
+
117
+ ```ruby
118
+ class ServicesController < ApplicationController
119
+ include Controll::Helper
120
+
121
+ ...
122
+
123
+ protected
124
+
125
+ message_handler :services
126
+ commander :services
127
+ end
128
+ ```
129
+
130
+ The Commander is where you register a set of related commands, typically for a specific controller.
131
+
132
+ ```ruby
133
+ class ServicesCommander < Controll::Commander
134
+
135
+ # register commands with controller
136
+ commands :cancel_commit, :create_account, :signout
137
+
138
+ def sign_in_command
139
+ @sign_in_command ||= SignInCommand.new auth_hash: auth_hash, user_id: user_id, service_id: service_id, service_hash: service_hash, initiator: self
140
+ end
141
+
142
+ # delegations
143
+ controller_methods :auth_hash, :user_id, :service_id, :service_hash
144
+ end
145
+ ```
146
+
147
+ The `#commands` class macro can be used to create command methods that only take the initiator (in this case the controller) as argument.
148
+
149
+ For how to implement the commands, see the `imperator` gem, or see the `oauth_assist` engine for a full example.
150
+
151
+ We will implement this MessageHandler later when we know which notifications and errors we want to use/issue.
152
+
153
+ For Controller actions that require complex flow control, use a FlowHandler:
154
+
155
+ ```ruby
156
+ module Controll::FlowHandler
157
+ class CreateService < Control
158
+ protected
159
+
160
+ # use for more advanced render/redirect logic (fx when using paths with arguments)
161
+ def use_alternatives
162
+ end
163
+
164
+ def use_fallback
165
+ event == :no_auth ? do_render(:text => omniauth.to_yaml) : fallback_action
166
+ end
167
+
168
+ def action_handlers
169
+ [Redirect, Render]
170
+ end
171
+
172
+ def event
173
+ @event ||= authentication
174
+ end
175
+
176
+ def authentication
177
+ @authentication ||= Authenticator.new(controller).execute
178
+ end
179
+
180
+ class Render < Controll::FlowHandler::Render
181
+ def self.default_path
182
+ :signup_services_path
183
+ end
184
+
185
+ def self.events
186
+ [:signed_in_new_user]
187
+ end
188
+ end
189
+
190
+ class Redirect < Controll::FlowHandler::Render
191
+ def self.redirections
192
+ {
193
+ signup_services_path: :signed_in_new_user
194
+ services_path: [:signed_in_connect, :signed_in_new_connect]
195
+ root_url: [:signed_in_user, :other]
196
+ }
197
+ end
198
+
199
+ def self.error_redirections
200
+ {
201
+ signin_path: [:error, :invalid, :auth_error]
202
+ }
203
+ end
204
+ end
205
+ end
206
+ end
207
+ ```
208
+
209
+ In the `Redirect` class we are setting up a mapping for various path, specifying which notifications/event should cause a redirect to that path.
210
+
211
+ If you are rendering or redirecting to paths that take arguments, you can either extend the `#action` class method of your Redirect or Render class implementation or you can define a `#use_alternatives` method in your `FlowHandler` that contains this particular flow logic. You can also use the `#use_fallback` method for this purpose.
212
+
213
+ ## The Authenticator Executor
214
+
215
+ The `Authenticator` inherits from `Executor::Notificator` which uses `#method_missing` in order to delegate any missing method back to the initiator of the Executor, in this case the FlowHandler. The `#result` call at the end of `#execute` ensures that the last notification event is returned, to be used for deciding what to render or where to redirect (see FlowHandler).
216
+
217
+ ```ruby
218
+ module Controll::Executor
219
+ class Authenticator < Notificator
220
+ def execute
221
+ # creates an error notification named :error
222
+ error and return unless valid_params?
223
+
224
+ # creates an error notification named :auth_invalid
225
+ error(:auth_invalid) and return unless auth_valid?
226
+
227
+ command! :sign_in
228
+ result
229
+ end
230
+
231
+ protected
232
+
233
+ def valid_params?
234
+ omniauth and service and auth_hash
235
+ end
236
+ end
237
+ end
238
+ ```
239
+
240
+ To encapsulate more complex busines logic affecting the user Session or Model data, we execute an the Imperator Command (see `imperator` gem) called :sign_in that we registered in the Commander of the Controller.
241
+
242
+ ## Notifier
243
+
244
+ Now we are finally ready to define the message handler for each notification event we have defined (this should ideally be done as you define each event!).
245
+
246
+ The example below demonstrates several different ways you can define messages for events:
247
+
248
+ * using the `#messages` method to return a hash of mappings.
249
+ * define a method for the event name that returns a String (w argument replacement)
250
+ * i18n locale mapping [msghandler name].[notification type].[event name].
251
+
252
+ ```ruby
253
+ module Controll::Notify
254
+ class Services < Typed
255
+ class ErrorMsg < Controll::Notify::Base
256
+ type :error
257
+
258
+ def messages
259
+ {
260
+ must_sign_in: 'You need to sign in before accessing this page!',
261
+
262
+ auth_service_error: %q{There was an error at the remote authentication service.
263
+ You have not been signed in.},
264
+
265
+ cant_delete_current_account: 'You are currently signed in with this account!',
266
+ user_save_error: 'This is embarrassing! There was an error while creating your account from which we were not able to recover.',
267
+ }
268
+ end
269
+
270
+ def auth_error!
271
+ 'Error while authenticating via ' + service_name + '. The service did not return valid data.'
272
+ end
273
+
274
+ def auth_invalid!
275
+ 'Error while authenticating via {{full_route}}. The service returned invalid data for the user id.'
276
+ end
277
+ end
278
+
279
+
280
+ class NoticeMsg < Controll::Notify::Base
281
+ type :notice
282
+
283
+ # for :signed_in and :signed_out - defined in locale file under:
284
+
285
+ # services:
286
+ # notice:
287
+ # signed_in: 'Your account has been created and you have been signed in!'
288
+ # signed_out: 'You have been signed out!'
289
+
290
+ def already_connected
291
+ 'Your account at {{provider_name}} is already connected with this site.'
292
+ end
293
+
294
+ def account_added
295
+ 'Your {{provider_name}} account has been added for signing in at this site.'
296
+ end
297
+
298
+ def sign_in_success
299
+ 'Signed in successfully via {{provider_name}}.'
300
+ end
301
+ end
302
+ end
303
+ end
304
+ ```
305
+
306
+ ## Contributing to controll
307
+
308
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
309
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
310
+ * Fork the project.
311
+ * Start a feature/bugfix branch.
312
+ * Commit and push until you are happy with your contribution.
313
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
314
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
315
+
316
+ == Copyright
317
+
318
+ Copyright (c) 2012 Kristian Mandrup. See LICENSE.txt for
319
+ further details.
320
+