foreign_office 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/javascripts/debug_logger.js +22 -0
  6. data/app/assets/javascripts/foreign_office.js +229 -0
  7. data/lib/foreign_office.rb +68 -0
  8. data/lib/foreign_office/busses/generic_bus.rb +4 -0
  9. data/lib/foreign_office/busses/pubnub_bus.rb +34 -0
  10. data/lib/foreign_office/busses/pusher_bus.rb +2 -0
  11. data/lib/foreign_office/version.rb +3 -0
  12. data/lib/tasks/foreign_office_tasks.rake +4 -0
  13. data/test/dummy/README.rdoc +28 -0
  14. data/test/dummy/Rakefile +6 -0
  15. data/test/dummy/app/assets/javascripts/application.js +13 -0
  16. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  17. data/test/dummy/app/controllers/application_controller.rb +5 -0
  18. data/test/dummy/app/helpers/application_helper.rb +2 -0
  19. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  20. data/test/dummy/bin/bundle +3 -0
  21. data/test/dummy/bin/rails +4 -0
  22. data/test/dummy/bin/rake +4 -0
  23. data/test/dummy/config.ru +4 -0
  24. data/test/dummy/config/application.rb +23 -0
  25. data/test/dummy/config/boot.rb +5 -0
  26. data/test/dummy/config/database.yml +25 -0
  27. data/test/dummy/config/environment.rb +5 -0
  28. data/test/dummy/config/environments/development.rb +37 -0
  29. data/test/dummy/config/environments/production.rb +82 -0
  30. data/test/dummy/config/environments/test.rb +39 -0
  31. data/test/dummy/config/initializers/assets.rb +8 -0
  32. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  34. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  35. data/test/dummy/config/initializers/inflections.rb +16 -0
  36. data/test/dummy/config/initializers/mime_types.rb +4 -0
  37. data/test/dummy/config/initializers/session_store.rb +3 -0
  38. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  39. data/test/dummy/config/locales/en.yml +23 -0
  40. data/test/dummy/config/routes.rb +56 -0
  41. data/test/dummy/config/secrets.yml +22 -0
  42. data/test/dummy/db/test.sqlite3 +0 -0
  43. data/test/dummy/log/test.log +288 -0
  44. data/test/dummy/public/404.html +67 -0
  45. data/test/dummy/public/422.html +67 -0
  46. data/test/dummy/public/500.html +66 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/foreign_office_test.rb +51 -0
  49. data/test/test_helper.rb +18 -0
  50. metadata +188 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4254304d99a94d05606529febec28a0f05aeae25
4
+ data.tar.gz: 48c9c8aaaffb9e772de1012ce13e646b12ce0231
5
+ SHA512:
6
+ metadata.gz: f31c46cf51b00ca4781404b15c401f8df3debbf228c808e649ea1e4f066b73a9909858f4a04b160cf75af6f38aabbc5791c606e60cca2fecaf3e30f6e2314b41
7
+ data.tar.gz: d59728edeb29b3d3e5af8ac3145d2c5852ada7194a153fa578a1324078c7de7abb634dc34d506f50ba3827d06feaa57fa62a6c06adf797a9ffd47aedbcacd7b4
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
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.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = ForeignOffice
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ForeignOffice'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.libs << 'test'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = false
29
+ end
30
+
31
+
32
+ task default: :test
@@ -0,0 +1,22 @@
1
+ // This is a bit heavy for what it does, but should be super-easy to extend/enhance
2
+ var DebugLogger = Class.extend({
3
+ init: function($debug_settings){
4
+ if($debug_settings.data('logging_on')){
5
+ this.logging_on = true;
6
+ } else {
7
+ this.logging_on = false;
8
+ }
9
+ },
10
+ log: function(msg){
11
+ if(this.logging_on){
12
+ console.log(msg)
13
+ }
14
+ }
15
+ })
16
+
17
+ $(document).ready(function(){
18
+ if($('[data-debug_logger]')){
19
+ jqobj = $('[data-debug_logger]');
20
+ debug_logger = new DebugLogger(jqobj);
21
+ }
22
+ })
@@ -0,0 +1,229 @@
1
+ //= require debug_logger
2
+ var ForeignOffice = Class.extend({
3
+ init: function(){
4
+ this.pubnub = PUBNUB.init({
5
+ publish_key : 'pub-c-1146120f-14f7-4649-9dee-3b21a519d573',
6
+ subscribe_key : 'sub-c-9d1b308c-a5f1-11e2-87b3-12313f022c90',
7
+ ssl : true
8
+ });
9
+ this.channels = [];
10
+ this.channels_by_name = [];
11
+ },
12
+ connection: function(){
13
+ return this.pubnub;
14
+ },
15
+ addListener: function($listener){
16
+ var listener_class = eval(getSubClass($listener.data('listener'),'ForeignOfficeListener'));
17
+ var listener = new listener_class($listener);
18
+ var this_channel;
19
+ if($.inArray(listener.channel,this.channelNames()) == -1){
20
+ this_channel = new ForeignOfficeChannel(listener.channel)
21
+ this.channels.push(this_channel);
22
+ this.channels_by_name[listener.channel] = this_channel;
23
+ } else {
24
+ var this_channel = this.channels_by_name[listener.channel];
25
+ }
26
+ this_channel.addListener(listener);
27
+ },
28
+ channelNames: function(){
29
+ return $.map(this.channels,function(channel){return channel.channel_name});
30
+ }
31
+ });
32
+
33
+ foreign_office = new ForeignOffice();
34
+
35
+ var ForeignOfficeChannel = Class.extend({
36
+ init: function(channel_name){
37
+ var foreign_office_channel = this;
38
+ foreign_office.connection().subscribe({
39
+ channel : channel_name,
40
+ backfill: true,
41
+ message : function(m){
42
+ debug_logger.log("Got a message: ");
43
+ debug_logger.log(m);
44
+ $.each(foreign_office_channel.listeners,function(i,listener){
45
+ debug_logger.log("sending message to listener: ");
46
+ debug_logger.log(listener);
47
+ listener.handleMessage(m);
48
+ });
49
+ }
50
+ });
51
+ this.channel_name = channel_name;
52
+ this.listeners = [];
53
+ },
54
+ addListener: function(listener){
55
+ this.listeners.push(listener);
56
+ }
57
+ });
58
+
59
+ var ForeignOfficeListener = Class.extend({
60
+ init: function($listener){
61
+ console.log("ForeignOfficeListener initializer:")
62
+ console.log($listener);
63
+ this.$listener = $listener;
64
+ this.endpoint = $listener.data('endpoint');
65
+ this.object_key = $listener.data('key');
66
+ this.delete_key = $listener.data('delete-key');
67
+ this.channel = $listener.data('channel');
68
+ if(this.$listener.data('progress-indicator')){
69
+ this.progress_indicator = new AjaxProgress(this.$listener);
70
+ }
71
+ },
72
+ handleMessage: function(m){
73
+ var $listener = this.$listener;
74
+ if(this.endpoint){
75
+ if (m.object[this.object_key] == true) {
76
+ $.get(this.endpoint, function(data){
77
+ $listener.html(data);
78
+ })
79
+ }
80
+ if (m.object[this.delete_key] == true) {
81
+ $listener.remove;
82
+ }
83
+ }else{
84
+ var new_value = m.object[this.object_key];
85
+ switch(this.$listener.get(0).nodeName.toLowerCase()){
86
+ case 'input': case 'select':
87
+ this.$listener.val(new_value);
88
+ break;
89
+
90
+ case 'a':
91
+ if(this.$listener.data('trigger-on-message')){
92
+ this.$listener.attr('href',new_value);
93
+ if(this.progress_indicator){
94
+ this.progress_indicator.stop();
95
+ }
96
+ if(this.$listener.data('ajax_link')){
97
+ this.$listener.trigger('click');
98
+ }else{
99
+ window.location = new_value;
100
+ }
101
+ }else{
102
+ this.$listener.html(new_value);
103
+ }
104
+ break;
105
+
106
+ case 'img':
107
+ this.$listener.prop('src',new_value);
108
+ break;
109
+
110
+ default:
111
+ this.$listener.html(new_value);
112
+ break;
113
+ }
114
+ }
115
+ this.getForeignOfficeProgressIndicator();
116
+ this.removeProgressIndicator();
117
+ },
118
+ getForeignOfficeProgressIndicator: function(){
119
+ var this_listener = this;
120
+ $('[data-foreign-office-progress-indicator="' + this.channel + '"]').each(function(){
121
+ this_listener.foreign_office_progress_indicator = $(this).data('foreign-office-progress-indicator-object');
122
+ console.log($(this).data());
123
+ this_listener.foreign_office_flash = $(this).data('ajax-foreign-office-flash').notice;
124
+ })
125
+ },
126
+ removeProgressIndicator: function(){
127
+ if(this.foreign_office_progress_indicator){
128
+ this.foreign_office_progress_indicator.stop();
129
+ if(this.foreign_office_flash){
130
+ new AjaxFlash('success',this.foreign_office_flash,this.$listener);
131
+ }
132
+ }
133
+ }
134
+ });
135
+
136
+ var ForeignNewListItems = ForeignOfficeListener.extend({
137
+ handleMessage: function(m){
138
+ var $listener = this.$listener;
139
+ $.get(m.object[this.object_key], function(data){
140
+ $listener.append(data);
141
+ })
142
+ }
143
+ });
144
+
145
+ var ForeignOfficeRevealer = ForeignOfficeListener.extend({
146
+ handleMessage: function(m){
147
+ var current_value = m.object[this.object_key];
148
+ if(!current_value || current_value == 'false' || current_value == 'hide'){
149
+ this.$listener.hide();
150
+ } else if(current_value == true || current_value == 'true' || current_value == 'show'){
151
+ this.$listener.removeClass('hidden');
152
+ this.$listener.show();
153
+ }
154
+ }
155
+ });
156
+
157
+ var ForeignOfficeColor = ForeignOfficeListener.extend({
158
+ handleMessage: function(m){
159
+ var new_value = m.object[this.object_key];
160
+ this.$listener.html(new_value);
161
+ if(new_value == "Yes") {
162
+ this.$listener.removeClass('red').addClass('green');
163
+ } else {
164
+ this.$listener.removeClass('green').addClass('red');
165
+ }
166
+ }
167
+ });
168
+
169
+ //Anytime loader, needs to be extracted into its own library
170
+
171
+ var AnyTimeManager = Class.extend({
172
+ init: function(){
173
+ this.loader_array = []
174
+ },
175
+ register: function(data_attribute,base_class,load_method){
176
+ this.loader_array.push({data_attribute: data_attribute, base_class: base_class, load_method: load_method});
177
+ },
178
+ instantiate: function(jq_obj, class_name){
179
+ if(!jq_obj.data('anytime_loaded')){
180
+ jq_obj.data('anytime_loaded',true);
181
+ var this_class = eval(class_name);
182
+ new this_class(jq_obj);
183
+ }
184
+ },
185
+ run: function (jq_obj, resource, method_name){
186
+ if(!jq_obj.data('anytime_run')){
187
+ jq_obj.data('anytime_run',true);
188
+ resource[method_name](jq_obj);
189
+ }
190
+ },
191
+ load: function(){
192
+ var any_time_manager = this;
193
+ $.each(any_time_manager.loader_array,function(){
194
+ var data_attribute = this['data_attribute'];
195
+ var base_class = this['base_class'];
196
+ var this_method = this['load_method'];
197
+ console.log(this_method);
198
+ $('[data-' + data_attribute + ']').each(function(){
199
+ if('instantiate' == this_method){
200
+ var declared_class = $(this).data(data_attribute);
201
+ var this_class = getSubClass(declared_class,base_class);
202
+ any_time_manager.instantiate($(this),this_class);
203
+ }else{
204
+ console.log('running...')
205
+ console.log(base_class);
206
+ any_time_manager.run($(this),base_class,this_method);
207
+ }
208
+
209
+ });
210
+ });
211
+ }
212
+ });
213
+ var AnytimeLoader = Class.extend({
214
+ init: function(jq_obj){
215
+ this.jq_obj = jq_obj;
216
+ jq_obj.data('anytime_loaded',true);
217
+ }
218
+ });
219
+ any_time_manager = new AnyTimeManager();
220
+ $(document).ajaxComplete(function(){
221
+ any_time_manager.load();
222
+ });
223
+ $(document).ready(function(){
224
+ any_time_manager.load();
225
+ });
226
+
227
+ // End AnyTime library
228
+
229
+ any_time_manager.register('listener',foreign_office,'addListener');
@@ -0,0 +1,68 @@
1
+ require 'request_store'
2
+ module ForeignOffice
3
+
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace ForeignOffice
6
+ end
7
+
8
+ def self.bus=(bus)
9
+ @bus = bus
10
+ end
11
+
12
+ def self.bus
13
+ @bus
14
+ end
15
+
16
+ def self.set_publish_method(&block)
17
+ @publish_method = block
18
+ end
19
+
20
+ def self.publish_method
21
+ @publish_method
22
+ end
23
+
24
+ def self.publish(message)
25
+ Rails.logger.debug("ForeignOffice.publish: #{message.inspect}")
26
+ if !!@cache_messages
27
+ RequestStore.store[:foreign_office_messages][message[:channel]] = message
28
+ else
29
+ self.handle_publish_request(message)
30
+ end
31
+ end
32
+
33
+ def self.cache_messages
34
+ @cache_messages = true
35
+ RequestStore.store[:foreign_office_messages] = {}
36
+ end
37
+
38
+ def self.publish_directly
39
+ @cache_messages = false
40
+ end
41
+
42
+ def self.flush_messages
43
+ messages = RequestStore.store[:foreign_office_messages].dup
44
+ RequestStore.store[:foreign_office_messages] = {}
45
+ messages.each do |channel,message|
46
+ self.handle_publish_request(message)
47
+ end
48
+ end
49
+
50
+ def self.handle_publish_request(message)
51
+ if self.publish_method
52
+ self.publish_method.call(message)
53
+ else
54
+ self.publish!(message)
55
+ end
56
+ end
57
+
58
+ def self.publish!(message, attempts = 0)
59
+ attempts += 1
60
+ Rails.logger.debug("ForeignOffice#publish! attempt: #{attempts} message: #{message.inspect}")
61
+ self.bus.publish(message)
62
+ end
63
+
64
+ module Busses
65
+ end
66
+ end
67
+ require 'foreign_office/busses/generic_bus'
68
+ require 'foreign_office/busses/pubnub_bus'
@@ -0,0 +1,4 @@
1
+ class ForeignOffice::Busses::GenericBus
2
+ def publish(message)
3
+ end
4
+ end
@@ -0,0 +1,34 @@
1
+ class ForeignOffice::Busses::PubnubBus < ForeignOffice::Busses::GenericBus
2
+
3
+ def self.settings
4
+ @settings ||= Sekrets.settings_for(Rails.root.join('config', 'pubnub.yml.enc'))
5
+ end
6
+
7
+ def self.connection
8
+ @pubnub ||= ::Pubnub.new(
9
+ publish_key: self.settings['PUBNUB_PUBLISH_KEY'], # publish_key only required if publishing.
10
+ subscribe_key: self.settings['PUBNUB_SUBSCRIBE_KEY'], # required
11
+ secret_key: self.settings['PUBNUB_SECRET_KEY'],
12
+ error_callback: lambda { |msg| Rails.logger.error( msg.inspect )}
13
+ )
14
+ end
15
+
16
+ def self.publish(message)
17
+ message.symbolize_keys!
18
+ self.connection.publish(
19
+ channel: message[:channel],
20
+ message: message,
21
+ http_sync: true,
22
+ callback: lambda{|response|
23
+ if 0 == JSON.parse(response.instance_variable_get(:@response)).first #pubnub publishing failed
24
+ if attempts <= 3
25
+ self.publish!(message, attempts) #retry if we failed
26
+ else
27
+ Rails.logger.debug("ForeignOffice#publish! failed after #{attempts} attempts. message: #{message.inspect}")
28
+ end
29
+ end
30
+ }
31
+ )
32
+ end
33
+
34
+ end
@@ -0,0 +1,2 @@
1
+ class PusherBus < GenericBus
2
+ end
@@ -0,0 +1,3 @@
1
+ module ForeignOffice
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :foreign_office do
3
+ # # Task goes here
4
+ # end