redis_monitor 0.2.1 → 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +1 -1
  4. data/README.md +7 -9
  5. data/Rakefile +4 -0
  6. data/lib/engine/app/controllers/content_controller.rb +1 -1
  7. data/lib/engine/app/controllers/notifications_controller.rb +19 -0
  8. data/lib/engine/app/controllers/tasks_controller.rb +47 -0
  9. data/lib/engine/app/helpers/application_helper.rb +13 -3
  10. data/lib/engine/app/lib/commands/retrieve_key.rb +5 -0
  11. data/lib/engine/app/lib/commands/{search_key.rb → search_keys.rb} +1 -1
  12. data/lib/engine/app/lib/jobs/background_task_job.rb +42 -0
  13. data/lib/engine/app/models/notification.rb +7 -0
  14. data/lib/engine/app/models/task.rb +34 -0
  15. data/lib/engine/app/models/watch_key_task.rb +22 -0
  16. data/lib/engine/app/models/watch_query_task.rb +24 -0
  17. data/lib/engine/app/views/content/_search_form.haml +2 -2
  18. data/lib/engine/app/views/layouts/application.haml +1 -0
  19. data/lib/engine/app/views/notifications/_notification.haml +9 -0
  20. data/lib/engine/app/views/notifications/index.haml +14 -0
  21. data/lib/engine/app/views/tasks/_form.haml +32 -0
  22. data/lib/engine/app/views/tasks/_task.haml +14 -0
  23. data/lib/engine/app/views/tasks/edit.haml +3 -0
  24. data/lib/engine/app/views/tasks/index.haml +21 -0
  25. data/lib/engine/app/views/tasks/new.haml +3 -0
  26. data/lib/engine/bin/delayed_job +5 -0
  27. data/lib/engine/config/database.yml +2 -2
  28. data/lib/engine/config/initializers/delayed_job.rb +3 -0
  29. data/lib/engine/config/routes.rb +3 -0
  30. data/lib/engine/db/migrate/20140112162911_create_tasks.rb +15 -0
  31. data/lib/engine/db/migrate/20140118155310_create_delayed_jobs.rb +22 -0
  32. data/lib/engine/db/migrate/20140118183403_create_notifications.rb +10 -0
  33. data/lib/engine/db/schema.rb +51 -0
  34. data/lib/engine/public/javascripts/jquery_ujs.js +394 -0
  35. data/lib/engine/public/stylesheets/custom.css +4 -0
  36. data/lib/engine/spec/controllers/content_controller_spec.rb +1 -1
  37. data/lib/engine/spec/controllers/notifications_controller_spec.rb +39 -0
  38. data/lib/engine/spec/controllers/tasks_controller_spec.rb +109 -0
  39. data/lib/engine/spec/lib/commands/retrieve_key_spec.rb +15 -0
  40. data/lib/engine/spec/lib/commands/search_key_spec.rb +2 -2
  41. data/lib/engine/spec/lib/jobs/background_task_job_spec.rb +55 -0
  42. data/lib/engine/spec/models/notification_spec.rb +9 -0
  43. data/lib/engine/spec/models/task_spec.rb +23 -0
  44. data/lib/engine/spec/models/watch_key_task_spec.rb +13 -0
  45. data/lib/engine/spec/models/watch_query_task_spec.rb +13 -0
  46. data/lib/redis_monitor.rb +7 -1
  47. data/lib/version.rb +1 -1
  48. data/redis_monitor.gemspec +2 -0
  49. metadata +61 -10
  50. data/lib/engine/test/controllers/.keep +0 -0
  51. data/lib/engine/test/fixtures/.keep +0 -0
  52. data/lib/engine/test/helpers/.keep +0 -0
  53. data/lib/engine/test/integration/.keep +0 -0
  54. data/lib/engine/test/mailers/.keep +0 -0
  55. data/lib/engine/test/models/.keep +0 -0
  56. data/lib/engine/test/test_helper.rb +0 -15
@@ -0,0 +1,3 @@
1
+ %h2
2
+ New task
3
+ = render 'form'
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4
+ require 'delayed/command'
5
+ Delayed::Command.new(ARGV).daemonize
@@ -5,7 +5,7 @@
5
5
  # gem 'sqlite3'
6
6
  development:
7
7
  adapter: sqlite3
8
- database: db/development.sqlite3
8
+ database: db/db.sqlite3
9
9
  pool: 5
10
10
  timeout: 5000
11
11
 
@@ -20,6 +20,6 @@ test:
20
20
 
21
21
  production:
22
22
  adapter: sqlite3
23
- database: db/production.sqlite3
23
+ database: db/db.sqlite3
24
24
  pool: 5
25
25
  timeout: 5000
@@ -0,0 +1,3 @@
1
+ require 'delayed_job'
2
+ Delayed::Worker.backend = :active_record
3
+ BackgroundTaskJob.reset_all_queues rescue nil
@@ -16,6 +16,9 @@ Engine::Application.routes.draw do
16
16
  end
17
17
  end
18
18
 
19
+ resources :tasks
20
+ resources :notifications
21
+
19
22
  # The priority is based upon order of creation: first created -> highest priority.
20
23
  # See how all your routes lay out with "rake routes".
21
24
 
@@ -0,0 +1,15 @@
1
+ class CreateTasks < ActiveRecord::Migration
2
+ def change
3
+ create_table :tasks do |t|
4
+ t.string :name
5
+ t.string :type
6
+ t.string :trigger
7
+ t.integer :database, default: 0
8
+ t.integer :every
9
+ t.string :status, default: ''
10
+ t.text :data
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ class CreateDelayedJobs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :delayed_jobs, :force => true do |table|
4
+ table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
5
+ table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
6
+ table.text :handler, :null => false # YAML-encoded string of the object that will do work
7
+ table.text :last_error # reason for last failure (See Note below)
8
+ table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
9
+ table.datetime :locked_at # Set when a client is working on this object
10
+ table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11
+ table.string :locked_by # Who is working on this object (if locked)
12
+ table.string :queue # The name of the queue this job is in
13
+ table.timestamps
14
+ end
15
+
16
+ add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
17
+ end
18
+
19
+ def self.down
20
+ drop_table :delayed_jobs
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ class CreateNotifications < ActiveRecord::Migration
2
+ def change
3
+ create_table :notifications do |t|
4
+ t.string :reporter, default: ''
5
+ t.text :message, default: ''
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20140118183403) do
15
+
16
+ create_table "delayed_jobs", force: true do |t|
17
+ t.integer "priority", default: 0, null: false
18
+ t.integer "attempts", default: 0, null: false
19
+ t.text "handler", null: false
20
+ t.text "last_error"
21
+ t.datetime "run_at"
22
+ t.datetime "locked_at"
23
+ t.datetime "failed_at"
24
+ t.string "locked_by"
25
+ t.string "queue"
26
+ t.datetime "created_at"
27
+ t.datetime "updated_at"
28
+ end
29
+
30
+ add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority"
31
+
32
+ create_table "notifications", force: true do |t|
33
+ t.string "reporter", default: ""
34
+ t.text "message", default: ""
35
+ t.datetime "created_at"
36
+ t.datetime "updated_at"
37
+ end
38
+
39
+ create_table "tasks", force: true do |t|
40
+ t.string "name"
41
+ t.string "type"
42
+ t.string "trigger"
43
+ t.integer "database", default: 0
44
+ t.integer "every"
45
+ t.string "status", default: ""
46
+ t.text "data"
47
+ t.datetime "created_at"
48
+ t.datetime "updated_at"
49
+ end
50
+
51
+ end
@@ -0,0 +1,394 @@
1
+ (function($, undefined) {
2
+
3
+ /**
4
+ * Unobtrusive scripting adapter for jQuery
5
+ * https://github.com/rails/jquery-ujs
6
+ *
7
+ * Requires jQuery 1.7.0 or later.
8
+ *
9
+ * Released under the MIT license
10
+ *
11
+ */
12
+
13
+ // Cut down on the number of issues from people inadvertently including jquery_ujs twice
14
+ // by detecting and raising an error when it happens.
15
+ if ( $.rails !== undefined ) {
16
+ $.error('jquery-ujs has already been loaded!');
17
+ }
18
+
19
+ // Shorthand to make it a little easier to call public rails functions from within rails.js
20
+ var rails;
21
+ var $document = $(document);
22
+
23
+ $.rails = rails = {
24
+ // Link elements bound by jquery-ujs
25
+ linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',
26
+
27
+ // Button elements boud jquery-ujs
28
+ buttonClickSelector: 'button[data-remote]',
29
+
30
+ // Select elements bound by jquery-ujs
31
+ inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
32
+
33
+ // Form elements bound by jquery-ujs
34
+ formSubmitSelector: 'form',
35
+
36
+ // Form input elements bound by jquery-ujs
37
+ formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])',
38
+
39
+ // Form input elements disabled during form submission
40
+ disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]',
41
+
42
+ // Form input elements re-enabled after form submission
43
+ enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled',
44
+
45
+ // Form required input elements
46
+ requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',
47
+
48
+ // Form file input elements
49
+ fileInputSelector: 'input[type=file]',
50
+
51
+ // Link onClick disable selector with possible reenable after remote submission
52
+ linkDisableSelector: 'a[data-disable-with]',
53
+
54
+ // Make sure that every Ajax request sends the CSRF token
55
+ CSRFProtection: function(xhr) {
56
+ var token = $('meta[name="csrf-token"]').attr('content');
57
+ if (token) xhr.setRequestHeader('X-CSRF-Token', token);
58
+ },
59
+
60
+ // Triggers an event on an element and returns false if the event result is false
61
+ fire: function(obj, name, data) {
62
+ var event = $.Event(name);
63
+ obj.trigger(event, data);
64
+ return event.result !== false;
65
+ },
66
+
67
+ // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
68
+ confirm: function(message) {
69
+ return confirm(message);
70
+ },
71
+
72
+ // Default ajax function, may be overridden with custom function in $.rails.ajax
73
+ ajax: function(options) {
74
+ return $.ajax(options);
75
+ },
76
+
77
+ // Default way to get an element's href. May be overridden at $.rails.href.
78
+ href: function(element) {
79
+ return element.attr('href');
80
+ },
81
+
82
+ // Submits "remote" forms and links with ajax
83
+ handleRemote: function(element) {
84
+ var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options;
85
+
86
+ if (rails.fire(element, 'ajax:before')) {
87
+ elCrossDomain = element.data('cross-domain');
88
+ crossDomain = elCrossDomain === undefined ? null : elCrossDomain;
89
+ withCredentials = element.data('with-credentials') || null;
90
+ dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
91
+
92
+ if (element.is('form')) {
93
+ method = element.attr('method');
94
+ url = element.attr('action');
95
+ data = element.serializeArray();
96
+ // memoized value from clicked submit button
97
+ var button = element.data('ujs:submit-button');
98
+ if (button) {
99
+ data.push(button);
100
+ element.data('ujs:submit-button', null);
101
+ }
102
+ } else if (element.is(rails.inputChangeSelector)) {
103
+ method = element.data('method');
104
+ url = element.data('url');
105
+ data = element.serialize();
106
+ if (element.data('params')) data = data + "&" + element.data('params');
107
+ } else if (element.is(rails.buttonClickSelector)) {
108
+ method = element.data('method') || 'get';
109
+ url = element.data('url');
110
+ data = element.serialize();
111
+ if (element.data('params')) data = data + "&" + element.data('params');
112
+ } else {
113
+ method = element.data('method');
114
+ url = rails.href(element);
115
+ data = element.data('params') || null;
116
+ }
117
+
118
+ options = {
119
+ type: method || 'GET', data: data, dataType: dataType,
120
+ // stopping the "ajax:beforeSend" event will cancel the ajax request
121
+ beforeSend: function(xhr, settings) {
122
+ if (settings.dataType === undefined) {
123
+ xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
124
+ }
125
+ return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
126
+ },
127
+ success: function(data, status, xhr) {
128
+ element.trigger('ajax:success', [data, status, xhr]);
129
+ },
130
+ complete: function(xhr, status) {
131
+ element.trigger('ajax:complete', [xhr, status]);
132
+ },
133
+ error: function(xhr, status, error) {
134
+ element.trigger('ajax:error', [xhr, status, error]);
135
+ },
136
+ crossDomain: crossDomain
137
+ };
138
+
139
+ // There is no withCredentials for IE6-8 when
140
+ // "Enable native XMLHTTP support" is disabled
141
+ if (withCredentials) {
142
+ options.xhrFields = {
143
+ withCredentials: withCredentials
144
+ };
145
+ }
146
+
147
+ // Only pass url to `ajax` options if not blank
148
+ if (url) { options.url = url; }
149
+
150
+ var jqxhr = rails.ajax(options);
151
+ element.trigger('ajax:send', jqxhr);
152
+ return jqxhr;
153
+ } else {
154
+ return false;
155
+ }
156
+ },
157
+
158
+ // Handles "data-method" on links such as:
159
+ // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
160
+ handleMethod: function(link) {
161
+ var href = rails.href(link),
162
+ method = link.data('method'),
163
+ target = link.attr('target'),
164
+ csrf_token = $('meta[name=csrf-token]').attr('content'),
165
+ csrf_param = $('meta[name=csrf-param]').attr('content'),
166
+ form = $('<form method="post" action="' + href + '"></form>'),
167
+ metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';
168
+
169
+ if (csrf_param !== undefined && csrf_token !== undefined) {
170
+ metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
171
+ }
172
+
173
+ if (target) { form.attr('target', target); }
174
+
175
+ form.hide().append(metadata_input).appendTo('body');
176
+ form.submit();
177
+ },
178
+
179
+ /* Disables form elements:
180
+ - Caches element value in 'ujs:enable-with' data store
181
+ - Replaces element text with value of 'data-disable-with' attribute
182
+ - Sets disabled property to true
183
+ */
184
+ disableFormElements: function(form) {
185
+ form.find(rails.disableSelector).each(function() {
186
+ var element = $(this), method = element.is('button') ? 'html' : 'val';
187
+ element.data('ujs:enable-with', element[method]());
188
+ element[method](element.data('disable-with'));
189
+ element.prop('disabled', true);
190
+ });
191
+ },
192
+
193
+ /* Re-enables disabled form elements:
194
+ - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
195
+ - Sets disabled property to false
196
+ */
197
+ enableFormElements: function(form) {
198
+ form.find(rails.enableSelector).each(function() {
199
+ var element = $(this), method = element.is('button') ? 'html' : 'val';
200
+ if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
201
+ element.prop('disabled', false);
202
+ });
203
+ },
204
+
205
+ /* For 'data-confirm' attribute:
206
+ - Fires `confirm` event
207
+ - Shows the confirmation dialog
208
+ - Fires the `confirm:complete` event
209
+
210
+ Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
211
+ Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
212
+ Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
213
+ return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
214
+ */
215
+ allowAction: function(element) {
216
+ var message = element.data('confirm'),
217
+ answer = false, callback;
218
+ if (!message) { return true; }
219
+
220
+ if (rails.fire(element, 'confirm')) {
221
+ answer = rails.confirm(message);
222
+ callback = rails.fire(element, 'confirm:complete', [answer]);
223
+ }
224
+ return answer && callback;
225
+ },
226
+
227
+ // Helper function which checks for blank inputs in a form that match the specified CSS selector
228
+ blankInputs: function(form, specifiedSelector, nonBlank) {
229
+ var inputs = $(), input, valueToCheck,
230
+ selector = specifiedSelector || 'input,textarea',
231
+ allInputs = form.find(selector);
232
+
233
+ allInputs.each(function() {
234
+ input = $(this);
235
+ valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val();
236
+ // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey
237
+ if (!valueToCheck === !nonBlank) {
238
+
239
+ // Don't count unchecked required radio if other radio with same name is checked
240
+ if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) {
241
+ return true; // Skip to next input
242
+ }
243
+
244
+ inputs = inputs.add(input);
245
+ }
246
+ });
247
+ return inputs.length ? inputs : false;
248
+ },
249
+
250
+ // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
251
+ nonBlankInputs: function(form, specifiedSelector) {
252
+ return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
253
+ },
254
+
255
+ // Helper function, needed to provide consistent behavior in IE
256
+ stopEverything: function(e) {
257
+ $(e.target).trigger('ujs:everythingStopped');
258
+ e.stopImmediatePropagation();
259
+ return false;
260
+ },
261
+
262
+ // replace element's html with the 'data-disable-with' after storing original html
263
+ // and prevent clicking on it
264
+ disableElement: function(element) {
265
+ element.data('ujs:enable-with', element.html()); // store enabled state
266
+ element.html(element.data('disable-with')); // set to disabled state
267
+ element.bind('click.railsDisable', function(e) { // prevent further clicking
268
+ return rails.stopEverything(e);
269
+ });
270
+ },
271
+
272
+ // restore element to its original state which was disabled by 'disableElement' above
273
+ enableElement: function(element) {
274
+ if (element.data('ujs:enable-with') !== undefined) {
275
+ element.html(element.data('ujs:enable-with')); // set to old enabled state
276
+ element.removeData('ujs:enable-with'); // clean up cache
277
+ }
278
+ element.unbind('click.railsDisable'); // enable element
279
+ }
280
+
281
+ };
282
+
283
+ if (rails.fire($document, 'rails:attachBindings')) {
284
+
285
+ $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
286
+
287
+ $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() {
288
+ rails.enableElement($(this));
289
+ });
290
+
291
+ $document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
292
+ var link = $(this), method = link.data('method'), data = link.data('params');
293
+ if (!rails.allowAction(link)) return rails.stopEverything(e);
294
+
295
+ if (link.is(rails.linkDisableSelector)) rails.disableElement(link);
296
+
297
+ if (link.data('remote') !== undefined) {
298
+ if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; }
299
+
300
+ var handleRemote = rails.handleRemote(link);
301
+ // response from rails.handleRemote() will either be false or a deferred object promise.
302
+ if (handleRemote === false) {
303
+ rails.enableElement(link);
304
+ } else {
305
+ handleRemote.error( function() { rails.enableElement(link); } );
306
+ }
307
+ return false;
308
+
309
+ } else if (link.data('method')) {
310
+ rails.handleMethod(link);
311
+ return false;
312
+ }
313
+ });
314
+
315
+ $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) {
316
+ var button = $(this);
317
+ if (!rails.allowAction(button)) return rails.stopEverything(e);
318
+
319
+ rails.handleRemote(button);
320
+ return false;
321
+ });
322
+
323
+ $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) {
324
+ var link = $(this);
325
+ if (!rails.allowAction(link)) return rails.stopEverything(e);
326
+
327
+ rails.handleRemote(link);
328
+ return false;
329
+ });
330
+
331
+ $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
332
+ var form = $(this),
333
+ remote = form.data('remote') !== undefined,
334
+ blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
335
+ nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
336
+
337
+ if (!rails.allowAction(form)) return rails.stopEverything(e);
338
+
339
+ // skip other logic when required values are missing or file upload is present
340
+ if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
341
+ return rails.stopEverything(e);
342
+ }
343
+
344
+ if (remote) {
345
+ if (nonBlankFileInputs) {
346
+ // slight timeout so that the submit button gets properly serialized
347
+ // (make it easy for event handler to serialize form without disabled values)
348
+ setTimeout(function(){ rails.disableFormElements(form); }, 13);
349
+ var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
350
+
351
+ // re-enable form elements if event bindings return false (canceling normal form submission)
352
+ if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
353
+
354
+ return aborted;
355
+ }
356
+
357
+ rails.handleRemote(form);
358
+ return false;
359
+
360
+ } else {
361
+ // slight timeout so that the submit button gets properly serialized
362
+ setTimeout(function(){ rails.disableFormElements(form); }, 13);
363
+ }
364
+ });
365
+
366
+ $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) {
367
+ var button = $(this);
368
+
369
+ if (!rails.allowAction(button)) return rails.stopEverything(event);
370
+
371
+ // register the pressed submit button
372
+ var name = button.attr('name'),
373
+ data = name ? {name:name, value:button.val()} : null;
374
+
375
+ button.closest('form').data('ujs:submit-button', data);
376
+ });
377
+
378
+ $document.delegate(rails.formSubmitSelector, 'ajax:beforeSend.rails', function(event) {
379
+ if (this == event.target) rails.disableFormElements($(this));
380
+ });
381
+
382
+ $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
383
+ if (this == event.target) rails.enableFormElements($(this));
384
+ });
385
+
386
+ $(function(){
387
+ // making sure that all forms have actual up-to-date token(cached forms contain old one)
388
+ var csrf_token = $('meta[name=csrf-token]').attr('content');
389
+ var csrf_param = $('meta[name=csrf-param]').attr('content');
390
+ $('form input[name="' + csrf_param + '"]').val(csrf_token);
391
+ });
392
+ }
393
+
394
+ })( jQuery );