{"id":18696481,"url":"https://github.com/hermanya/m","last_synced_at":"2025-04-12T07:31:22.697Z","repository":{"id":26091095,"uuid":"29535124","full_name":"Hermanya/m","owner":"Hermanya","description":"Singleton backbone models management","archived":false,"fork":false,"pushed_at":"2018-01-27T16:18:03.000Z","size":215,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-24T00:02:14.591Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hermanya.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-20T14:57:39.000Z","updated_at":"2021-11-09T19:47:11.000Z","dependencies_parsed_at":"2022-08-25T01:00:40.962Z","dependency_job_id":null,"html_url":"https://github.com/Hermanya/m","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hermanya%2Fm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hermanya%2Fm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hermanya%2Fm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hermanya%2Fm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hermanya","download_url":"https://codeload.github.com/Hermanya/m/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223502614,"owners_count":17156020,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T11:19:11.643Z","updated_at":"2024-11-07T11:19:12.267Z","avatar_url":"https://github.com/Hermanya.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Request for Comments\n----\n\n###This project solves problems of\n###### boilerplate\n```javascript\n// for example you have collection/users.js\nreturn Backbone.Collection.extend({\n  url: '/api/users',\n});\n\n// and collection/things.js\nreturn Backbone.Collection.extend({\n  url: '/api/things'\n});\n\n// and model/thing.js\nreturn Backbone.Model.extend({\n  url: '/api/thing'\n});\n\n// file-that-uses-things.js\nvar Things = require('./collection/things.js'),\n  things = new Things();\n  \n// file-that-uses-thing.js\nvar Things = require('./model/things.js'),\n  things = new Thing({\n    id: maybeId\n  });\n```\nYou get the idea, this is called boilerplate. This project simplifies your model layer at the cost of flexibility in terms of custom code.\n```javascript\n// api.js\nreturn new M({\n  prefix: '/api',\n  resources: {\n    user: 'any',\n    thing: 'any' // model/collection defenition\n  }\n})\n\n// file-that-uses-things.js\nvar api = require('./api.js'),\n  things = api.things().collection(); // returns an instance\n\n// file-that-uses-thing.js\nvar api = require('./api.js'),\n  things = api.thing(maybeId).model();\n\n```\n###### synchronisation and singleton management\n```javascript\n// usually you would have a manager kind of thing, that would keep track of your instances\n// manager.js\nvar Things = require('./collection/things.js'),\n  things = new Things();\nreturn {\n  things: things\n};\n// file-that-uses-things.js\nvar manager = require('./manager.js'),\n  things = manager.things;\n// file-that-uses-thing.js\nvar manager = require('./manager.js'),\n  things = manager.things,\n  thing = things.find(function (thing) {\n    return thing.id === maybeId;\n  }); \n```\nRegarding that last part, `things` may not be up to date and have no such item. If you create a separate model, but then there is again the sync question. It's a slippery slope. This project manages sigletons for you.\n```javascript\n// file-that-uses-things.js\nvar api = require('./api.js'),\n  things = api.things().collection();\n\n// file-that-uses-thing.js\nvar api = require('./api.js'),\n  thing = api.thing(maybeId).model();\n```\nIf `things` has an item with such id, then it would be the same reference. If `things` would then be fetched, and got the new thing, it would be the same reference. \n###### schema mappings\nIf you are uncofortable with your schema, because it involves\n- odd to javascript naming conventions `like_this` or\n- `it.is.very.unnecessary.deeply.nested` or\n- `it['com.this.like.gems.has']` or\n- it has `abbrs` instead of readable `abbreviations`\n```json\nGET /api/things/1\n[{\n  \"id\": 1,\n  \"integrated_services\": [],\n  \"details\": {\n    \"fullName\": \"thingie\",\n    \"prc\": 0.99\n  }\n}]\n```\nin Backbone you would\n```javascript\n// and model/thing.js\nreturn Backbone.Model.extend({\n  url: '/api/thing',\n  parse: function (object) {\n    return {\n      price: object.details.prc,\n      name: object.details.fullName,\n      integratedServices: object.integrated_services;\n    };\n  } // yet it does not solve the problem of converting it backwards for update\n});\n\n// and collection/things.js\nvar Thing = require('./model/thing.js');\nreturn Backbone.Collection.extend({\n  url: '/api/things',\n  model: Thing\n}); // now you have to mention your custom model, because it's not generic\n```\nOr you could just\n```javascript\n// api.js\nreturn new M({\n  prefix: '/api',\n  resources: {\n    user: {\n      _shortcutMappings: {\n        price: ['details', 'prc'],\n        name: ['details', 'name'],\n        integratedServices: ['integrated_services']\n      }\n    },\n    thing: 'any'\n  }\n})\n```\nThis will intercept all `get`s/`set`s and correct the keys.\n\n###Features\n\n- models with defined ids are singletons\n- once id changes (ex. *current* user is fetched) the model will be tied to an existing model with same id\n- collections also point to singleton models, thus sync is free\n- sort of type validation\n- adaptation to other (than backbone) framework's models is possible\n\n###How to Use\n\n```javascript\n// m-for-my-api.js\ndefine(['m-for-backbone'], function (m) {\n  return M({\n    prefix: '/rest/v37',\n    resources: {\n      account: 'any',\n      group: 'array of users',\n      user: {\n        id: 'number',\n        name: 'string',\n        email: 'email',\n        attributes: 'array of objects',\n        _attributeMappings: {\n          language: 'com.m.lang'\n        },\n        _shortcutMappings: {\n          isAdmin: ['association', 'flags', 'com.m.administrator']\n        }\n      }\n\n    }\n  });\n});\n\n```\n```javascript\n// current-group-mvwhaterver.js\nvar m = require('m-for-my-api.js');\nvar usersInMyGroup = m.group().users({limit: 10}).collection();\n```\n```javascript\n// selected-user-mvwhaterver.js\nvar m = require('m-for-my-api.js');\nvar user = m.user(selectedId).model();\n```\n```javascript\n// current-user-mvwhaterver.js\nvar m = require('m-for-my-api.js');\nvar me = m.user().model();\nme.set('language', 'ru')\nme.set('isAdmin', true)\n//  {\n//    id: 1,\n//    name: 'Herman Starikov',\n//    attributes: [{\n//      name: 'com.m.lang',\n//      value: 'ru'\n//    }],\n//    association: {\n//      flags: {\n//        'com.m.administrator': 'true'\n//      }\n//    }\n//  }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhermanya%2Fm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhermanya%2Fm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhermanya%2Fm/lists"}