Skip to content

Commit

Permalink
Replace jquery.serializeObject with new implementation
Browse files Browse the repository at this point in the history
The old serializeObject function serialized checked checkboxes as an array which was not correct and with
strong_parameters enabled it triggered a `UnpermittedParameters` error.

In the AgentEditPage javascript we only need to initialize `select2` when then `#agent_type` field is a select
box (trying to call `select2` on normal text fields caused a javascript error in the feature specs)
  • Loading branch information
dsander committed Sep 21, 2016
1 parent 2e4c851 commit 517e42c
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 37 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/pages/agent-edit-page.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class @AgentEditPage
@handleTypeChange(true)

# Update the dropdown to match agent description as well as agent name
$('#agent_type').select2
$('select#agent_type').select2
width: 'resolve'
formatResult: formatAgentForSelect
escapeMarkup: (m) ->
Expand Down
10 changes: 10 additions & 0 deletions spec/features/form_configurable_feature_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'capybara_helper'

describe "form configuring agents", js: true do
it 'completes fields with predefined array values' do
login_as(users(:bob))
visit edit_agent_path(agents(:bob_csv_agent))
check('Propagate immediately')
select2("serialize", from: "Mode")
end
end
6 changes: 6 additions & 0 deletions spec/fixtures/agents.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ bob_basecamp_agent:
service: generic
guid: <%= SecureRandom.hex %>

bob_csv_agent:
type: Agents::CsvAgent
user: bob
name: "Bob's CsvAgent"
guid: <%= SecureRandom.hex %>

jane_basecamp_agent:
type: Agents::BasecampAgent
user: jane
Expand Down
178 changes: 142 additions & 36 deletions vendor/assets/javascripts/jquery.serializeObject.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,146 @@
//
// Use internal $.serializeArray to get list of form elements which is
// consistent with $.serialize
//
// From version 2.0.0, $.serializeObject will stop converting [name] values
// to camelCase format. This is *consistent* with other serialize methods:
//
// - $.serialize
// - $.serializeArray
//
// If you require camel casing, you can either download version 1.0.4 or map
// them yourself.
//

(function($){
$.fn.serializeObject = function () {
"use strict";

var result = {};
var extend = function (i, element) {
var node = result[element.name];

// If node with same name exists already, need to convert it to an array as it
// is a multi-value field (i.e., checkboxes)

if ('undefined' !== typeof node && node !== null) {
if ($.isArray(node)) {
node.push(element.value);
} else {
result[element.name] = [node, element.value];
/**
* jQuery serializeObject
* @copyright 2014, macek <paulmacek@gmail.com>
* @link https://github.com/macek/jquery-serialize-object
* @license BSD
* @version 2.5.0
*/
(function(root, factory) {

// AMD
if (typeof define === "function" && define.amd) {
define(["exports", "jquery"], function(exports, $) {
return factory(exports, $);
});
}

// CommonJS
else if (typeof exports !== "undefined") {
var $ = require("jquery");
factory(exports, $);
}

// Browser
else {
factory(root, (root.jQuery || root.Zepto || root.ender || root.$));
}

}(this, function(exports, $) {

var patterns = {
validate: /^[a-z_][a-z0-9_]*(?:\[(?:\d*|[a-z0-9_]+)\])*$/i,
key: /[a-z0-9_]+|(?=\[\])/gi,
push: /^$/,
fixed: /^\d+$/,
named: /^[a-z0-9_]+$/i
};

function FormSerializer(helper, $form) {

// private variables
var data = {},
pushes = {};

// private API
function build(base, key, value) {
base[key] = value;
return base;
}

function makeObject(root, value) {

var keys = root.match(patterns.key), k;

// nest, nest, ..., nest
while ((k = keys.pop()) !== undefined) {
// foo[]
if (patterns.push.test(k)) {
var idx = incrementPush(root.replace(/\[\]$/, ''));
value = build([], idx, value);
}

// foo[n]
else if (patterns.fixed.test(k)) {
value = build([], k, value);
}

// foo; foo[bar]
else if (patterns.named.test(k)) {
value = build({}, k, value);
}
} else {
result[element.name] = element.value;
}
};

$.each(this.serializeArray(), extend);
return result;
return value;
}

function incrementPush(key) {
if (pushes[key] === undefined) {
pushes[key] = 0;
}
return pushes[key]++;
}

function encode(pair) {
switch ($('[name="' + pair.name + '"]', $form).attr("type")) {
case "checkbox":
return pair.value === "on" ? true : pair.value;
default:
return pair.value;
}
}

function addPair(pair) {
if (!patterns.validate.test(pair.name)) return this;
var obj = makeObject(pair.name, encode(pair));
data = helper.extend(true, data, obj);
return this;
}

function addPairs(pairs) {
if (!helper.isArray(pairs)) {
throw new Error("formSerializer.addPairs expects an Array");
}
for (var i=0, len=pairs.length; i<len; i++) {
this.addPair(pairs[i]);
}
return this;
}

function serialize() {
return data;
}

function serializeJSON() {
return JSON.stringify(serialize());
}

// public API
this.addPair = addPair;
this.addPairs = addPairs;
this.serialize = serialize;
this.serializeJSON = serializeJSON;
}

FormSerializer.patterns = patterns;

FormSerializer.serializeObject = function serializeObject() {
return new FormSerializer($, this).
addPairs(this.serializeArray()).
serialize();
};

FormSerializer.serializeJSON = function serializeJSON() {
return new FormSerializer($, this).
addPairs(this.serializeArray()).
serializeJSON();
};
})(jQuery);

if (typeof $.fn !== "undefined") {
$.fn.serializeObject = FormSerializer.serializeObject;
$.fn.serializeJSON = FormSerializer.serializeJSON;
}

exports.FormSerializer = FormSerializer;

return FormSerializer;
}));

0 comments on commit 517e42c

Please sign in to comment.