Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Configurable Serializer Function (Solves #153) #155

Merged
merged 1 commit into from
Jul 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/js_routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class JsRoutes
url_links: nil,
camel_case: false,
default_url_options: {},
compact: false
compact: false,
serializer: nil
}

NODE_TYPES = {
Expand Down Expand Up @@ -104,6 +105,7 @@ def generate
js.gsub!("DEFAULT_URL_OPTIONS", json(@options[:default_url_options].merge(deprecated_default_format)))
js.gsub!("PREFIX", @options[:prefix] || "")
js.gsub!("NODE_TYPES", json(NODE_TYPES))
js.gsub!("SERIALIZER", @options[:serializer] || "null")
js.gsub!("ROUTES", js_routes)
end

Expand Down
21 changes: 13 additions & 8 deletions lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ Based on Rails routes of APP_CLASS
NodeTypes = NODE_TYPES;

Utils = {
serialize: function(object, prefix) {
var element, i, j, key, len, prop, result, s;
default_serializer: function(object, prefix) {
var element, i, j, key, len, prop, s;
if (prefix == null) {
prefix = null;
}
Expand All @@ -34,16 +34,12 @@ Based on Rails routes of APP_CLASS
if (!prefix && !(this.get_object_type(object) === "object")) {
throw new Error("Url parameters should be a javascript hash");
}
if (root.jQuery) {
result = root.jQuery.param(object);
return (!result ? "" : result);
}
s = [];
switch (this.get_object_type(object)) {
case "array":
for (i = j = 0, len = object.length; j < len; i = ++j) {
element = object[i];
s.push(this.serialize(element, prefix + "[]"));
s.push(this.default_serializer(element, prefix + "[]"));
}
break;
case "object":
Expand All @@ -56,7 +52,7 @@ Based on Rails routes of APP_CLASS
if (prefix != null) {
key = prefix + "[" + key + "]";
}
s.push(this.serialize(prop, key));
s.push(this.default_serializer(prop, key));
}
break;
default:
Expand All @@ -69,6 +65,15 @@ Based on Rails routes of APP_CLASS
}
return s.join("&");
},
serialize: function(object) {
var custom_serializer;
custom_serializer = SERIALIZER;
if (custom_serializer) {
return custom_serializer(object);
} else {
return this.default_serializer(object);
}
},
clean_path: function(path) {
var last_index;
path = path.split("://");
Expand Down
17 changes: 10 additions & 7 deletions lib/routes.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,34 @@ NodeTypes = NODE_TYPES

Utils =

serialize: (object, prefix = null) ->
default_serializer: (object, prefix = null) ->
return "" unless object
if !prefix and !(@get_object_type(object) is "object")
throw new Error("Url parameters should be a javascript hash")

if root.jQuery
result = root.jQuery.param(object)
return (if not result then "" else result)

s = []
switch @get_object_type(object)
when "array"
for element, i in object
s.push @serialize(element, prefix + "[]")
s.push @default_serializer(element, prefix + "[]")
when "object"
for own key, prop of object when prop?
key = "#{prefix}[#{key}]" if prefix?
s.push @serialize(prop, key)
s.push @default_serializer(prop, key)
else
if object
s.push "#{encodeURIComponent(prefix.toString())}=#{encodeURIComponent(object.toString())}"

return "" unless s.length
s.join("&")

serialize: (object) ->
custom_serializer = SERIALIZER
if custom_serializer
custom_serializer(object)
else
@default_serializer(object)

clean_path: (path) ->
path = path.split("://")
last_index = path.length - 1
Expand Down
4 changes: 4 additions & 0 deletions spec/js_routes/generated_javascript_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
describe "generated js" do
subject { JsRoutes.generate }

it "should set the default serializer when none is configured" do
is_expected.to match(%r(serialize: function\(object\) {\s+var custom_serializer;\s+custom_serializer = null;\s+if \(custom_serializer\) {\s+return custom_serializer\(object\);\s+} else {\s+return this.default_serializer\(object\);\s+}\s+},))
end

it "should include a comment in the header" do
app_class = "App"

Expand Down
27 changes: 21 additions & 6 deletions spec/js_routes/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@
let(:_options) { {} }
let(:_warnings) { true }

context "when serializer is specified" do
let(:_options) { {:serializer => "myCustomSerializer"} }

it "should set configurable serializer" do
# define custom serializer
# this is a nonsense serializer, which always returns foo=bar
# for all inputs
evaljs(%q(function myCustomSerializer(object, prefix) { return "foo=bar"; }))

# expect the nonsense serializer above to have appened foo=bar
# to the end of the path
expect(evaljs(%q(Routes.inboxes_path()))).to eql("/inboxes?foo=bar")
end
end

context "when exclude is specified" do

let(:_options) { {:exclude => /^admin_/} }
Expand Down Expand Up @@ -292,11 +307,11 @@

context "when only host option is specified" do
let(:_options) { { :url_links => true, :default_url_options => {:host => "example.com"} } }

it "uses the specified host, defaults protocol to http, defaults port to 80 (leaving it blank)" do
expect(evaljs("Routes.inbox_url(1)")).to eq("http://example.com#{routes.inbox_path(1)}")
end

it "does not override protocol when specified in route" do
expect(evaljs("Routes.new_session_url()")).to eq("https://example.com#{routes.new_session_path}")
end
Expand All @@ -316,7 +331,7 @@
it "uses the specified protocol and host, defaults port to 80 (leaving it blank)" do
expect(evaljs("Routes.inbox_url(1)")).to eq("ftp://example.com#{routes.inbox_path(1)}")
end

it "does not override protocol when specified in route" do
expect(evaljs("Routes.new_session_url()")).to eq("https://example.com#{routes.new_session_path}")
end
Expand All @@ -340,11 +355,11 @@
it "does not override protocol when specified in route" do
expect(evaljs("Routes.new_session_url()")).to eq("https://example.com:3000#{routes.new_session_path}")
end

it "does not override host, protocol, or port when host is specified in route" do
expect(evaljs("Routes.sso_url()")).to eq(routes.sso_url)
end

it "does not override port when specified in route" do
expect(evaljs("Routes.portals_url()")).to eq("http://example.com:8080#{routes.portals_path}")
end
Expand Down Expand Up @@ -397,7 +412,7 @@
example.run
end
end

let(:_options) { { :compact => true, :url_links => "http://localhost" } }
it "should not strip urls" do
expect(evaljs("Routes.inbox(1)")).to eq(routes.inbox_path(1))
Expand Down
39 changes: 0 additions & 39 deletions spec/js_routes/rails_routes_compatibility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,45 +147,6 @@
end
end

context "when jQuery is present" do
before do
evaljs("window.jQuery = {};")
jscontext[:parameterizeFunc] = lambda {|object| _value.to_param}
evaljs("window.jQuery.param = parameterizeFunc")
end

shared_examples_for "serialization" do
it "should support serialization of objects" do
expect(evaljs("window.jQuery.param(#{_value.to_json})")).to eq(_value.to_param)
expect(evaljs("Routes.inboxes_path(#{_value.to_json})")).to eq(routes.inboxes_path(_value))
expect(evaljs("Routes.inbox_path(1, #{_value.to_json})")).to eq(routes.inbox_path(1, _value))
end
end
context "when parameters is a hash" do
let(:_value) do
{:a => {:b => 'c'}, :q => [1,2]}
end
it_should_behave_like 'serialization'
end
context "when parameters is null" do
let(:_value) do
{:hello => {world: nil}}
end
it_should_behave_like 'serialization'
end
context "when parameters is null" do
let(:_value) do
nil
end

before do
pending("This test is invalid for nil/null and jruby #{JRUBY_VERSION}") if defined?(JRUBY_VERSION) && '1.7.13' == JRUBY_VERSION
end

it_should_behave_like 'serialization'
end
end

context "using optional path fragments" do
context "including not optional parts" do
it "should include everything that is not optional" do
Expand Down