o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1357328631.182183: @value"?{I" class:EFI"BundledAsset;FI"logical_path;FI"resourcy_spec.js;FI" pathname;FI"M/Users/jejacks0n/Projects/resourcy/spec/javascripts/resourcy_spec.coffee;FI"content_type;FI"application/javascript;FI" mtime;FI"2013-01-04T12:43:47-07:00;FI" length;Fi=I" digest;F"%a6efc02f29edca94662620a4cc88d706I" source;FI"= /*! Resourcy v1.1.0 Resourcy is an unobtrusive RESTful adapter for jquery-ujs and Rails. Documentation and other useful information can be found at https://github.com/jejacks0n/resourcy Copyright (c) 2012 Jeremy Jackson https://raw.github.com/jejacks0n/resourcy/master/LICENSE */ (function() { var actions, addCallback, createResource, descriptions, determineCallback, handleRequest, methods, parseUrl, resources, _ref, _this = this; resources = {}; methods = ['get', 'put', 'post', 'delete']; actions = ['index', 'create', 'new', 'edit', 'show', 'update', 'delete']; descriptions = { plural: [['get', ''], ['post', ''], ['get', '/new'], ['get', '/:id/edit'], ['get', '/:id'], ['put', '/:id'], ['delete', '/:id']], singular: [null, ['post', ''], ['get', '/new'], ['get', '/edit'], ['get', ''], ['put', ''], ['delete', '']] }; parseUrl = function(url) { var path, _ref; url = url.match(/^((http[s]?|ftp):\/\/)?(((.+)@)?([^:\/\?#\s]+)(:(\d+))?)?(\/?[^\?#\.]+)?(\.([^\?#]+))?(\?([^#]*))?(#(.*))?$/i) || []; path = ((_ref = url[9]) != null ? _ref.match(/(\/.*)\/+(\w+)$/i) : void 0) || []; return { scheme: url[2], credentials: url[5], host: url[6], port: url[8], path: url[9], action: path[2] || '', format: url[11], query: url[13], hash: url[15] }; }; createResource = function(path, singular, defaults) { if (singular == null) { singular = false; } if (defaults == null) { defaults = {}; } if (resources[path]) { return resources[path]; } return resources[path] = { path: new RegExp("^" + ((path[0] === '/' ? path : "/" + path).replace(/:\w+/ig, '(\\w+)')) + "/?(\\w+)?/?(\\w+)?/?($|\\?|\\.|#)", 'i'), pathvars: (path.match(/:(\w+)/ig) || []).join('|').replace(/:/g, '').split('|'), actions: {}, defaults: defaults, singular: singular, name: path.substr(path.lastIndexOf('/') + 1), options: function(defaults) { if (defaults == null) { defaults = {}; } this.defaults = defaults; return this; }, add: function(action, callback) { var method, object, _ref; object = {}; if (typeof action === 'string') { object[action] = callback; } else { object = action; } for (action in object) { callback = object[action]; _ref = action.split(':'), method = _ref[0], action = _ref[1]; addCallback.call(this, method, action, callback); } return this; }, remove: function(action) { var method, _ref; _ref = action.split(':'), method = _ref[0], action = _ref[1]; if (action) { delete this.actions[method][action]; } else { delete this.actions[method]; } return this; }, removeAll: function() { this.actions = {}; return this; }, describe: function() { var action, desc, i, method, routes, start, _i, _j, _len, _ref, _ref1; routes = []; for (_i = 0, _len = methods.length; _i < _len; _i++) { method = methods[_i]; for (action in this.actions[method]) { routes.push("" + path + "/" + action + " " + (method.toUpperCase()) + " => " + this.name + "#" + action); } } _ref = this.singular ? [1, descriptions.singular] : [0, descriptions.plural], start = _ref[0], desc = _ref[1]; for (i = _j = start, _ref1 = actions.length - 1; start <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = start <= _ref1 ? ++_j : --_j) { if (this.actions[actions[i]]) { routes.push("" + path + desc[i][1] + " " + (desc[i][0].toUpperCase()) + " => " + this.name + "#" + actions[i]); } } return routes; } }; }; addCallback = function(method, action, callback) { var errorMsg, _base; errorMsg = "The " + ([method, action].join(':').replace(/:$/, '')) + " action already exists on the '" + this.name + "' resource. Try removing it first."; if (action) { (_base = this.actions)[method] || (_base[method] = {}); if (this.actions[method][action]) { throw errorMsg; } return this.actions[method][action] = callback; } else { if (this.actions[method]) { throw errorMsg; } if (this.singular && method === 'index') { throw "Adding index to '" + this.name + "' isn't possible (singular resource)."; } return this.actions[method] = callback; } }; handleRequest = function(method, url, options, original, optionsHandler) { var action, callback, defaults, index, key, matches, path, pathvar, proceed, proceeded, resource, result, urlParts, vars, _i, _len, _ref, _ref1; method = method.toLowerCase(); _ref = urlParts = parseUrl(url), path = _ref.path, action = _ref.action; defaults = {}; proceeded = false; proceed = function(opts) { proceeded = true; return original(url, optionsHandler(options || {}, opts || {}, defaults)); }; for (key in resources) { resource = resources[key]; if (!(matches = path.match(resource.path))) { continue; } if (callback = determineCallback(resource, action, method, matches[matches.length - 2], matches[matches.length - 3])) { defaults = resource.defaults; vars = {}; _ref1 = resource.pathvars; for (index = _i = 0, _len = _ref1.length; _i < _len; index = ++_i) { pathvar = _ref1[index]; vars[pathvar] = matches[index + 1]; } result = callback(proceed, vars, urlParts); } if (result !== false && !proceeded) { return proceed(result); } return; } return original(url, options); }; determineCallback = function(resource, action, method, matchAction, matchIdOrAction) { var _ref, _ref1, _ref2, _ref3; switch (method) { case 'get': if ((_ref = resource.actions.get) != null ? _ref[action] : void 0) { return resource.actions.get[action]; } switch ((matchIdOrAction ? action : '')) { case '': return (resource.singular ? resource.actions.show : resource.actions.index); case 'new': return resource.actions["new"]; case 'edit': return resource.actions.edit; default: if (!matchAction) { return resource.actions.show; } } break; case 'put': return ((_ref1 = resource.actions.put) != null ? _ref1[action] : void 0) || (!matchAction ? resource.actions.update : void 0); case 'post': return ((_ref2 = resource.actions.post) != null ? _ref2[action] : void 0) || (!matchIdOrAction ? resource.actions.create : void 0); case 'delete': return ((_ref3 = resource.actions["delete"]) != null ? _ref3[action] : void 0) || (!matchAction ? resource.actions.destroy : void 0); } }; this.Resourcy = { removeAll: function() { return resources = {}; }, handleRequest: handleRequest, noConflict: ((_ref = this.Resourcy) != null ? _ref.noConflict : void 0) || function() { return delete Resourcy; }, resources: function(path, defaults, actions) { if (defaults == null) { defaults = {}; } if (actions == null) { actions = {}; } return createResource(path, false, defaults).add(actions); }, resource: function(path, defaults, actions) { if (defaults == null) { defaults = {}; } if (actions == null) { actions = {}; } return createResource(path, true, defaults).add(actions); }, routes: function() { var path, resource, routes; routes = {}; for (path in resources) { resource = resources[path]; routes[resource.name] = resource.describe(); } return routes; } }; }).call(this); (function() { describe("Resourcy", function() { beforeEach(function() { return Resourcy.removeAll(); }); describe(".resources (creating a plural resource)", function() { beforeEach(function() { return this.resource = Resourcy.resources('blogs/:blog_id/posts'); }); it("returns a resource", function() { return expect(typeof this.resource).toBe('object'); }); it("sets information on the resource", function() { expect(this.resource.pathvars).toEqual(['blog_id']); expect(this.resource.actions).toEqual({}); expect(this.resource.singular).toBe(false); return expect(this.resource.name).toBe('posts'); }); it("has an add, remove, and describe method", function() { expect(typeof this.resource.add).toBe('function'); expect(typeof this.resource.remove).toBe('function'); return expect(typeof this.resource.describe).toBe('function'); }); return it("can find an existing resource and return it", function() { var r2; r2 = Resourcy.resources('blogs/:blog_id/posts'); return expect(r2).toBe(this.resource); }); }); describe(".resource (creating a singular resource)", function() { beforeEach(function() { return this.resource = Resourcy.resource('blogs/:blog_id/owner'); }); it("returns a resource", function() { return expect(typeof this.resource).toBe('object'); }); it("sets information on the resource", function() { expect(this.resource.pathvars).toEqual(['blog_id']); expect(this.resource.actions).toEqual({}); expect(this.resource.singular).toBe(true); return expect(this.resource.name).toBe('owner'); }); it("has an add, remove, and describe method", function() { expect(typeof this.resource.add).toBe('function'); expect(typeof this.resource.remove).toBe('function'); return expect(typeof this.resource.describe).toBe('function'); }); return it("can find an existing resource and return it", function() { var r2; r2 = Resourcy.resource('blogs/:blog_id/owner'); return expect(r2).toBe(this.resource); }); }); describe(".routes", function() { beforeEach(function() { Resourcy.resources('blogs/:blog_id/posts'); return Resourcy.resource('blogs/:blog_id/owner'); }); it("returns an object of registered resources", function() { return expect(Resourcy.routes()).toEqual({ owner: [], posts: [] }); }); return it("calls describe on all the resources", function() { spyOn(Resourcy.resources('blogs/:blog_id/posts'), 'describe').andCallFake(function() { return ['posts => foo']; }); spyOn(Resourcy.resources('blogs/:blog_id/owner'), 'describe').andCallFake(function() { return ['owner => foo']; }); return expect(Resourcy.routes()).toEqual({ owner: ['owner => foo'], posts: ['posts => foo'] }); }); }); describe(".noConflict", function() { return it("removes Resourcy", function() { Resourcy.noConflict(); expect(window.Resourcy).toBeUndefined(); return window.Resourcy = window.R; }); }); describe("plural resources", function() { beforeEach(function() { this.resource = Resourcy.resources('blogs/:blog_id/posts'); return this.callback = function() { return 'callback'; }; }); describe("#add", function() { it("accepts an object, and adds to the actions", function() { this.resource.add({ index: this.callback }); return expect(this.resource.actions.index).toBe(this.callback); }); it("accepts an string and callback, and adds to the actions", function() { this.resource.add('put:activate', this.callback); return expect(this.resource.actions.put['activate']).toBe(this.callback); }); it("doesn't allow adding the same action more than once", function() { var _this = this; this.resource.add({ index: this.callback }); return expect(function() { return _this.resource.add({ index: _this.callback }); }).toThrow("The index action already exists on the 'posts' resource. Try removing it first."); }); return it("returns itself for chaining", function() { return expect(this.resource.add('put:activate', this.callback)).toBe(this.resource); }); }); describe("#remove", function() { beforeEach(function() { this.resource.add('index', this.callback); return this.resource.add('put:activate', this.callback); }); it("removes the action", function() { expect(this.resource.actions.index).toBe(this.callback); expect(this.resource.actions.put['activate']).toBe(this.callback); this.resource.remove('index'); this.resource.remove('put:activate'); expect(this.resource.actions.index).toBeUndefined(); return expect(this.resource.actions.put['activate']).toBeUndefined(); }); return it("returns itself for chaining", function() { return expect(this.resource.remove('index')).toBe(this.resource); }); }); describe("#removeAll", function() { beforeEach(function() { this.resource.add('index', this.callback); return this.resource.add('put:activate', this.callback); }); it("clears all actions", function() { expect(this.resource.actions.index).toBe(this.callback); expect(this.resource.actions.put['activate']).toBe(this.callback); this.resource.removeAll(); return expect(this.resource.actions).toEqual({}); }); return it("returns itself for chaining", function() { return expect(this.resource.removeAll()).toBe(this.resource); }); }); return describe("#describe", function() { beforeEach(function() { this.resource.add('index', this.callback); return this.resource.add('put:activate', this.callback); }); return it("returns an array describing the resource actions", function() { return expect(this.resource.describe()).toEqual(['blogs/:blog_id/posts/activate PUT => posts#activate', 'blogs/:blog_id/posts GET => posts#index']); }); }); }); return describe("singular resources", function() { beforeEach(function() { this.resource = Resourcy.resource('blogs/:blog_id/owner'); return this.callback = function() { return 'callback'; }; }); describe("#add", function() { return it("doesn't allow adding the index action", function() { var _this = this; return expect(function() { return _this.resource.add('index'); }).toThrow("Adding index to 'owner' isn't possible (singular resource)."); }); }); return describe("#describe", function() { beforeEach(function() { this.resource.add('show', this.callback); return this.resource.add('put:activate', this.callback); }); return it("returns an array describing the resource actions", function() { return expect(this.resource.describe()).toEqual(['blogs/:blog_id/owner/activate PUT => owner#activate', 'blogs/:blog_id/owner GET => owner#show']); }); }); }); }); }).call(this); ;FI"required_assets_digest;F"%252e6a29d91234a8c0968d12ab6e64a5I" _version;F"%9f3b95dd7ea3030dc35985c0a8020862