├── .bowerrc ├── .editorconfig ├── .ember-cli ├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── addon ├── .gitkeep ├── mixins │ ├── adapter.js │ ├── base-serializer.js │ ├── jsonapi-serializer.js │ ├── rest-serializer.js │ └── store.js └── utils │ ├── model.js │ └── serializer-partial-model-handler.js ├── app ├── .gitkeep ├── adapters │ └── application.js ├── serializers │ └── application.js └── services │ └── store.js ├── bower.json ├── config ├── ember-try.js └── environment.js ├── ember-cli-build.js ├── index.js ├── package.json ├── testem.json ├── tests ├── .jshintrc ├── acceptance │ ├── rentals-test.js │ └── users-test.js ├── dummy │ ├── app │ │ ├── adapters │ │ │ └── application.js │ │ ├── app.js │ │ ├── components │ │ │ └── .gitkeep │ │ ├── controllers │ │ │ ├── .gitkeep │ │ │ ├── rentals.js │ │ │ ├── rentals │ │ │ │ ├── new.js │ │ │ │ └── rental.js │ │ │ ├── users.js │ │ │ └── users │ │ │ │ ├── new.js │ │ │ │ └── user.js │ │ ├── helpers │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── mirage │ │ │ ├── config.js │ │ │ ├── factories │ │ │ │ ├── client.js │ │ │ │ ├── rental.js │ │ │ │ ├── rental_extended.js │ │ │ │ ├── user.js │ │ │ │ └── user_extended.js │ │ │ └── fixtures │ │ │ │ ├── rental_extendeds.js │ │ │ │ ├── rentals.js │ │ │ │ ├── user_extendeds.js │ │ │ │ └── users.js │ │ ├── models │ │ │ ├── .gitkeep │ │ │ ├── client.js │ │ │ ├── rental.js │ │ │ └── user.js │ │ ├── router.js │ │ ├── routes │ │ │ ├── .gitkeep │ │ │ ├── rentals.js │ │ │ ├── rentals │ │ │ │ ├── new.js │ │ │ │ └── rental.js │ │ │ ├── users.js │ │ │ └── users │ │ │ │ ├── new.js │ │ │ │ └── user.js │ │ ├── serializers │ │ │ ├── client.js │ │ │ └── user.js │ │ ├── styles │ │ │ └── app.css │ │ └── templates │ │ │ ├── application.hbs │ │ │ ├── components │ │ │ └── .gitkeep │ │ │ ├── rentals.hbs │ │ │ ├── rentals │ │ │ ├── new.hbs │ │ │ └── rental.hbs │ │ │ ├── users.hbs │ │ │ └── users │ │ │ ├── new.hbs │ │ │ └── user.hbs │ ├── config │ │ └── environment.js │ └── public │ │ ├── crossdomain.xml │ │ └── robots.txt ├── helpers │ ├── resolver.js │ └── start-app.js ├── index.html ├── test-helper.js └── unit │ ├── .gitkeep │ ├── adapter-test.js │ ├── jsonapi-serializer-test.js │ ├── rest-serializer-test.js │ ├── store-test.js │ └── utils │ ├── model-test.js │ └── serializer-partial-model-handler-test.js └── vendor └── .gitkeep /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "analytics": false 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.js] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.hbs] 21 | insert_final_newline = false 22 | indent_style = space 23 | indent_size = 2 24 | 25 | [*.css] 26 | indent_style = space 27 | indent_size = 2 28 | 29 | [*.html] 30 | indent_style = space 31 | indent_size = 2 32 | 33 | [*.{diff,md}] 34 | trim_trailing_whitespace = false 35 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # misc 12 | /.sass-cache 13 | /connect.lock 14 | /coverage/* 15 | /libpeerconnection.log 16 | npm-debug.log 17 | testem.log 18 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "server", 4 | "document", 5 | "window", 6 | "-Promise" 7 | ], 8 | "browser": true, 9 | "boss": true, 10 | "curly": true, 11 | "debug": false, 12 | "devel": true, 13 | "eqeqeq": true, 14 | "evil": true, 15 | "forin": false, 16 | "immed": false, 17 | "laxbreak": false, 18 | "newcap": true, 19 | "noarg": true, 20 | "noempty": false, 21 | "nonew": false, 22 | "nomen": false, 23 | "onevar": false, 24 | "plusplus": false, 25 | "regexp": false, 26 | "undef": true, 27 | "sub": true, 28 | "strict": false, 29 | "white": false, 30 | "eqnull": true, 31 | "esnext": true, 32 | "unused": true 33 | } 34 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | tests/ 3 | tmp/ 4 | dist/ 5 | 6 | .bowerrc 7 | .editorconfig 8 | .ember-cli 9 | .travis.yml 10 | .npmignore 11 | **/.gitkeep 12 | bower.json 13 | Brocfile.js 14 | testem.json 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - "0.12" 5 | 6 | sudo: false 7 | 8 | cache: 9 | directories: 10 | - node_modules 11 | 12 | env: 13 | - EMBER_TRY_SCENARIO=2.0 14 | - EMBER_TRY_SCENARIO=2.1 15 | - EMBER_TRY_SCENARIO=2.2 16 | - EMBER_TRY_SCENARIO=2.3 17 | - EMBER_TRY_SCENARIO=2.4 18 | - EMBER_TRY_SCENARIO=2.5 19 | - EMBER_TRY_SCENARIO=2.6 20 | - EMBER_TRY_SCENARIO=2.7 21 | - EMBER_TRY_SCENARIO=default 22 | - EMBER_TRY_SCENARIO=ember-release 23 | - EMBER_TRY_SCENARIO=ember-beta 24 | - EMBER_TRY_SCENARIO=ember-canary 25 | 26 | matrix: 27 | fast_finish: true 28 | allow_failures: 29 | - env: EMBER_TRY_SCENARIO=ember-canary 30 | 31 | before_install: 32 | - npm config set spin false 33 | - npm install -g bower 34 | - npm install phantomjs-prebuilt 35 | 36 | install: 37 | - npm install 38 | - bower install 39 | 40 | script: 41 | # Usually, it's ok to finish the test scenario without reverting 42 | # to the addon's original dependency state, skipping "cleanup". 43 | - ember try $EMBER_TRY_SCENARIO test --skip-cleanup 44 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp"] 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ember-data-partial-model Changelog 2 | 3 | ## master 4 | 5 | ## 0.4.0 6 | 7 | Update notes: 8 | 9 | - None 10 | 11 | Changes: 12 | - [FEATURE] #27 make partial serializers configurable from outside by @Azdaroth 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ember-data-partial-model [](https://travis-ci.org/BookingSync/ember-data-partial-model.svg) [](https://badge.fury.io/js/ember-data-partial-model.svg) [](https://emberobserver.com/addons/ember-data-partial-model) 2 | 3 | This addon adds support for partial records to Ember Data. Let's say your api for 4 | `/users` returns a shallow model like: 5 | ```js 6 | [{id:1, name: 'BMac'}, {id:2, name:'Seb'}] 7 | ``` 8 | 9 | but `/users/1` returns a detailed model 10 | 11 | ```js 12 | { 13 | id:1, 14 | name: 'BMac' 15 | twitter: 'seb' 16 | } 17 | ``` 18 | 19 | You can use this addon to define your User model as: 20 | ```js 21 | // app/models/user.js 22 | 23 | import { PartialModel, partial } from 'ember-data-partial-model/utils/model'; 24 | const { attr } = DS; 25 | 26 | export default PartialModel.extend({ 27 | name: attr(), 28 | extended: partial('user', 'extended', { 29 | twitter: attr() 30 | }) 31 | }); 32 | ``` 33 | 34 | This addon will modify your application adapter/serializer, so that accessing `user.get('extended')` 35 | or any of the extended properties will trigger a request for the detailed model. 36 | For example: 37 | 38 | ```js 39 | let users = await store.findAll('user'); // goes to /users 40 | let user = users.objectAt(1); 41 | 42 | user.get('extended') //goes to /users/1, returns a promise 43 | user.get('twitter') //goes to /users/1, but is just an alias, so returns null initially, should not do in app code 44 | ``` 45 | 46 | Thus you are safe from race conditions when rendering users, even if you have not loaded the full user 47 | In your template you can do 48 | ```js 49 | {{user.twitter}} 50 | ``` 51 | and it will populate once the full user is loaded 52 | 53 | ## Introduction Video 54 | 55 | [](https://vimeo.com/162329720) 56 | 57 | ## How to use 58 | If you haven't customized any of your adapters, serializers or store, the addon will work out of the box. By default it uses JSONAPISerializer and JSONAPIAdapter. 59 | 60 | If you made any customization, you will need to include proper mixins. For adapter: 61 | 62 | ```js 63 | // app/adapters/application.js 64 | 65 | import DS from 'ember-data'; 66 | import PartialModelAdapter from 'ember-data-partial-model/mixins/adapter'; 67 | const { JSONAPIAdapter } = DS; 68 | 69 | export default JSONAPIAdapter.extend(PartialModelAdapter); 70 | 71 | ``` 72 | 73 | For serializer (both JSONAPISerializer and RESTSerializer are available): 74 | 75 | 76 | ```js 77 | // app/serializers/application.js 78 | 79 | import DS from 'ember-data'; 80 | import PartialModelJSONAPISerializer from 'ember-data-partial-model/mixins/jsonapi-serializer'; 81 | const { JSONAPISerializer } = DS; 82 | 83 | export default JSONAPISerializer.extend(PartialModelJSONAPISerializer); 84 | ``` 85 | 86 | or 87 | 88 | ```js 89 | // app/serializers/application.js 90 | 91 | import DS from 'ember-data'; 92 | import PartialModelRESTSerializer from 'ember-data-partial-model/mixins/rest-serializer'; 93 | const { RESTSerializer } = DS; 94 | 95 | export default RESTSerializer.extend(PartialModelRESTSerializer); 96 | ``` 97 | 98 | 99 | For store: 100 | 101 | ```js 102 | // app/services/store.js 103 | 104 | import DS from 'ember-data'; 105 | import PartialModelStore from 'ember-data-partial-model/mixins/store'; 106 | const { Store } = DS; 107 | 108 | export default Store.extend(PartialModelStore, {}); 109 | ``` 110 | 111 | ## Supporting custom serializers 112 | If you are using different serializer than REST or JSONAPI, you can create custom mixin to support it, you will just need to provide some functions for handling logic specific to your serializer. The basic layout is the following: 113 | 114 | ```js 115 | import Ember from 'ember'; 116 | import baseSerializerMixin from 'ember-data-partial-model/mixins/base-serializer'; 117 | const { Mixin } = Ember; 118 | 119 | export default Mixin.create(baseSerializerMixin, { 120 | _normalizePartialRelationship: function(modelClass, resourceHash, descriptor) { 121 | // add this function to handle normalization of partial extension as a relationship. 122 | }, 123 | 124 | _copyAttributesFromPartialToParent: function(serializedHash, partialHash) { 125 | // add this function to handle copying attributes from partial extension to top-level hash. 126 | }, 127 | }); 128 | ``` 129 | 130 | ## Extending partial serializers 131 | You can provide extensions and list of mixins to be applied for partial serializers. If you defined `extended` partial in `user` model like this: 132 | 133 | ``` js 134 | // app/models/user.js 135 | 136 | import { PartialModel, partial } from 'ember-data-partial-model/utils/model'; 137 | const { attr } = DS; 138 | 139 | export default PartialModel.extend({ 140 | name: attr(), 141 | extended: partial('user', 'extended', { 142 | twitter: attr(), 143 | clients: hasMany('client', { async: false }) 144 | }) 145 | }); 146 | ``` 147 | 148 | add you want to make `clients` relationship embedded and serialize all `clients` records when serializing `user` model, you could customize `user` serializer the following way: 149 | 150 | ``` js 151 | // app/serializers/user.js 152 | 153 | import Ember from 'ember'; 154 | import DS from 'ember-data'; 155 | import ApplicationSerializer from './application'; 156 | 157 | const { EmbeddedRecordsMixin } = DS; 158 | const { Mixin } = Ember; 159 | 160 | export default ApplicationSerializer.extend({ 161 | partialSerializersExtensions: { 162 | extended: { 163 | attrs: { 164 | clients: { embedded: 'always' } 165 | } 166 | } 167 | }, 168 | 169 | partialSerializersMixins: { 170 | extended: [EmbeddedRecordsMixin] 171 | } 172 | }); 173 | ``` 174 | 175 | All extensions defined inside `partialSerializersExtensions` will be copied for given partial and all mixins defined in `partialSerializersMixins` will be used when defining partial serializer. 176 | 177 | ## Installation 178 | 179 | * `git clone` this repository 180 | * `npm install` 181 | * `bower install` 182 | 183 | ## Running 184 | 185 | * `ember server` 186 | * Visit your app at http://localhost:4200. 187 | 188 | ## Running Tests 189 | 190 | * `ember test` 191 | * `ember test --server` 192 | 193 | ## Building 194 | 195 | * `ember build` 196 | 197 | For more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/). 198 | -------------------------------------------------------------------------------- /addon/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BookingSync/ember-data-partial-model/423fca5037cc8d2aa6ef401ddc4a5c34adc1cf4a/addon/.gitkeep -------------------------------------------------------------------------------- /addon/mixins/adapter.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | const { Mixin } = Ember; 3 | 4 | export default Mixin.create({ 5 | buildURL: function(modelName, id, snapshot, requestType, query) { 6 | if (snapshot) { 7 | let extendPartialModel = snapshot.type._extendPartialModel; 8 | if (extendPartialModel) { 9 | modelName = extendPartialModel; 10 | } 11 | } 12 | 13 | return this._super(modelName, id, snapshot, requestType, query); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /addon/mixins/base-serializer.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import partialModelHandler from 'ember-data-partial-model/utils/serializer-partial-model-handler'; 3 | const { Mixin } = Ember; 4 | const { normalizeEachPartialRelationship, serializeEachPartialRelationship } = partialModelHandler; 5 | 6 | export default Mixin.create({ 7 | normalize: function(modelClass, resourceHash, prop) { 8 | normalizeEachPartialRelationship(modelClass, resourceHash, this, this._normalizePartialRelationship); 9 | return this._super(modelClass, resourceHash, prop); 10 | }, 11 | 12 | serialize: function(snapshot /*, options */) { 13 | let serializedHash = this._super(...arguments); 14 | serializeEachPartialRelationship(snapshot, serializedHash, this, this._copyAttributesFromPartialToParent); 15 | 16 | return serializedHash; 17 | }, 18 | 19 | serializeBelongsTo: function(snapshot, json, relationship) { 20 | if (relationship.options.isPartialExtension) { 21 | return null; 22 | } else { 23 | return this._super(...arguments); 24 | } 25 | }, 26 | 27 | _normalizePartialRelationship: function(/* modelClass, resourceHash, descriptor */) { 28 | }, 29 | 30 | _copyAttributesFromPartialToParent: function(/* serializedHash, partialHash */) { 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /addon/mixins/jsonapi-serializer.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import baseSerializerMixin from 'ember-data-partial-model/mixins/base-serializer'; 3 | const { Mixin } = Ember; 4 | 5 | export default Mixin.create(baseSerializerMixin, { 6 | _normalizePartialRelationship: function(modelClass, resourceHash, descriptor) { 7 | resourceHash.relationships = resourceHash.relationships || {}; 8 | resourceHash.relationships[descriptor.key] = { 9 | data: { 10 | type: descriptor.type, 11 | id: this.extractId(modelClass, resourceHash) 12 | } 13 | }; 14 | }, 15 | 16 | _copyAttributesFromPartialToParent: function(serializedHash, partialHash) { 17 | Ember.merge(serializedHash.data.attributes, partialHash.data.attributes); 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /addon/mixins/rest-serializer.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import baseSerializerMixin from 'ember-data-partial-model/mixins/base-serializer'; 3 | const { Mixin } = Ember; 4 | 5 | export default Mixin.create(baseSerializerMixin, { 6 | _normalizePartialRelationship: function(modelClass, resourceHash, descriptor) { 7 | resourceHash[descriptor.key] = resourceHash.id; 8 | }, 9 | 10 | _copyAttributesFromPartialToParent: function(serializedHash, partialHash) { 11 | Ember.merge(serializedHash, partialHash); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /addon/mixins/store.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import DS from 'ember-data'; 3 | const { Mixin, merge } = Ember; 4 | const { Model } = DS; 5 | 6 | export default Mixin.create({ 7 | modelFor(key) { 8 | let factory = this._super(key); 9 | if (factory._isPartialModel === true) { 10 | this._generatePartialExtensionModel(key, factory); 11 | this._generatePartialExtensionSerializer(key, factory); 12 | } 13 | return factory; 14 | }, 15 | 16 | createRecord(modelName, inputProperties) { 17 | inputProperties = inputProperties || {}; 18 | let factory = this.modelFor(modelName); 19 | let relationshipsToBeAssigned = {}; 20 | let attributesFromPartialModels = []; 21 | 22 | if (factory._isPartialModel) { 23 | factory.eachRelationship((relationshipKey, descriptor) => { 24 | if (descriptor.options.isPartialExtension === true) { 25 | let partialModelName = `${modelName}-${relationshipKey}`; 26 | let partialProperties = descriptor.options.classHash; 27 | let attributesFromPartialModel = Object.keys(partialProperties); 28 | let propertiesForPartialModel = this._extractPropertiesForPartialModel( 29 | inputProperties, attributesFromPartialModel, partialProperties); 30 | let partialModel = this._super(partialModelName, propertiesForPartialModel); 31 | 32 | attributesFromPartialModels = attributesFromPartialModels.concat(attributesFromPartialModel); 33 | relationshipsToBeAssigned[relationshipKey] = partialModel; 34 | } 35 | }); 36 | } 37 | 38 | let propertiesForModel = this._extractPropertiesForModel(inputProperties, attributesFromPartialModels); 39 | let newRecord = this._super(modelName, propertiesForModel); 40 | 41 | for (let relationshipKey in relationshipsToBeAssigned) { 42 | newRecord.set(relationshipKey, relationshipsToBeAssigned[relationshipKey]); 43 | } 44 | return newRecord; 45 | }, 46 | 47 | _extractPropertiesForModel(inputProperties, attributesFromPartialModels) { 48 | let propertiesForModel = {}; 49 | for (let prop in inputProperties) { 50 | if (attributesFromPartialModels.indexOf(prop) === -1) { 51 | propertiesForModel[prop] = inputProperties[prop]; 52 | } 53 | } 54 | return propertiesForModel; 55 | }, 56 | 57 | _extractPropertiesForPartialModel(inputProperties, attributesFromPartialModel) { 58 | let propertiesForPartialModel = {}; 59 | attributesFromPartialModel 60 | .filter((prop) => inputProperties.hasOwnProperty(prop)) 61 | .forEach((prop) => { 62 | propertiesForPartialModel[prop] = inputProperties[prop]; 63 | }); 64 | return propertiesForPartialModel; 65 | }, 66 | 67 | _generatePartialExtensionModel(factoryName, factory) { 68 | factory.eachRelationship((relationshipKey, descriptor) => { 69 | let partialExtensionModelName = `${factoryName}-${relationshipKey}`; 70 | let dependencyName = `model:${partialExtensionModelName}`; 71 | if (descriptor.options.isPartialExtension === true) { 72 | if (!_isDependencyRegistered(this, dependencyName)) { 73 | let partialExtensionModel = Model.extend(descriptor.options.classHash) 74 | .reopenClass({ _extendPartialModel: factoryName }); 75 | _registerDependency(this, dependencyName, partialExtensionModel); 76 | } 77 | } 78 | }); 79 | }, 80 | 81 | _generatePartialExtensionSerializer(factoryName, factory) { 82 | factory.eachRelationship((partialName, descriptor) => { 83 | let partialExtensionSerializerName = `${factoryName}-${partialName}`; 84 | let dependencyName = `serializer:${partialExtensionSerializerName}`; 85 | if (descriptor.options.isPartialExtension === true) { 86 | if (!_isDependencyRegistered(this, dependencyName)) { 87 | let parentSerializer = this.serializerFor(factoryName); 88 | let parentSerializerConstructor = parentSerializer.constructor; 89 | let serializerOverrides = this._overridesForPartialSerializer(parentSerializer, 90 | partialName, partialExtensionSerializerName); 91 | let mixins = this._mixinsForPartialSerializer(parentSerializer, partialName); 92 | let partialExtensionSerializer = parentSerializerConstructor.extend(...mixins, 93 | serializerOverrides); 94 | _registerDependency(this, dependencyName, partialExtensionSerializer); 95 | } 96 | } 97 | }); 98 | }, 99 | 100 | _overridesForPartialSerializer(parentSerializer, partialName, partialExtensionSerializerName) { 101 | let serializerOverrides = {}; 102 | let externalOverrides = parentSerializer.partialSerializersExtensions && 103 | parentSerializer.partialSerializersExtensions[partialName] || {}; 104 | merge(serializerOverrides, externalOverrides); 105 | merge(serializerOverrides, { 106 | modelNameFromPayloadKey() { 107 | return this._super(partialExtensionSerializerName); 108 | } 109 | }); 110 | return serializerOverrides; 111 | }, 112 | 113 | _mixinsForPartialSerializer(parentSerializer, partialName) { 114 | return parentSerializer.partialSerializersMixins && 115 | parentSerializer.partialSerializersMixins[partialName] || []; 116 | } 117 | }); 118 | 119 | function _isDependencyRegistered(store, dependencyName) { 120 | if (Ember.getOwner) { 121 | return Ember.getOwner(store).hasRegistration(dependencyName); 122 | } else if (store.container.registry) { 123 | // support Ember 2.1 - 2.2 124 | return store.container.registry.has(dependencyName); 125 | } else { 126 | // fallback to Ember < 2.1 127 | return store.container._registry.has(dependencyName); 128 | } 129 | } 130 | 131 | function _registerDependency(store, dependencyName, dependency) { 132 | if (Ember.getOwner) { 133 | Ember.getOwner(store).register(dependencyName, dependency); 134 | } else if (store.container.registry) { 135 | // support Ember 2.1 - 2.2 136 | store.container.registry.register(dependencyName, dependency); 137 | } else { 138 | // fallback to Ember < 2.1 139 | store.container._registry.register(dependencyName, dependency); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /addon/utils/model.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | import Ember from 'ember'; 3 | const { computed, on, A: emberA, RSVP: { hash } } = Ember; 4 | const { alias } = computed; 5 | const { Model, belongsTo, PromiseObject } = DS; 6 | 7 | function partial(modelName, prop, hash) { 8 | return belongsTo(`${modelName}-${prop}`, { 9 | async: true, isPartialExtension: true, classHash: hash 10 | }); 11 | } 12 | 13 | var PartialModel = Model.extend({ 14 | _partialDescriptors() { 15 | return this.constructor._partialDescriptors(); 16 | }, 17 | 18 | _setupAliasesForPartials: on('init', function() { 19 | this._partialDescriptors().forEach(descriptor => { 20 | Object.keys(descriptor.options.classHash).forEach(attr => { 21 | Ember.defineProperty(this, attr, alias(`${descriptor.key}.${attr}`)); 22 | }); 23 | }); 24 | }), 25 | 26 | loadPartials() { 27 | return new hash(this.getProperties(...this._partialDescriptors().mapBy('key'))).then(() => { 28 | return this; 29 | }); 30 | }, 31 | 32 | save() { 33 | var model = this; 34 | if (model.constructor._isPartialModel) { 35 | return model.loadPartials().then(() => { 36 | // Why this._super() doesn't work here? 37 | return PromiseObject.create({ 38 | promise: model._internalModel.save().then(function() { 39 | return model; 40 | }) 41 | }); 42 | }); 43 | } else { 44 | return this._super(...arguments); 45 | } 46 | } 47 | }); 48 | 49 | PartialModel.reopenClass({ 50 | _partialDescriptors: function() { 51 | let descriptors = emberA(); 52 | this.eachRelationship((relationshipKey, descriptor) => { 53 | if (descriptor.options.isPartialExtension) { 54 | descriptors.push(descriptor); 55 | } 56 | }); 57 | return descriptors; 58 | }, 59 | _isPartialModel: true 60 | }); 61 | 62 | export { PartialModel, partial }; 63 | -------------------------------------------------------------------------------- /addon/utils/serializer-partial-model-handler.js: -------------------------------------------------------------------------------- 1 | export default { 2 | normalizeEachPartialRelationship: function(modelClass, resourceHash, context, normalizePartialRelationshipStrategy) { 3 | partialDescriptors(modelClass).forEach(descriptor => { 4 | normalizePartialRelationshipStrategy.call(context, modelClass, resourceHash, descriptor); 5 | }); 6 | }, 7 | 8 | serializeEachPartialRelationship: function(snapshot, serializedHash, context, copyAttributesFromPartialToParentStrategy) { 9 | partialDescriptors(snapshot).forEach(descriptor => { 10 | let partial = snapshot.belongsTo(descriptor.key); 11 | 12 | if (partial) { 13 | let partialHash = partial.record.serialize(); 14 | copyAttributesFromPartialToParentStrategy.call(context, serializedHash, partialHash); 15 | } 16 | }); 17 | } 18 | }; 19 | 20 | function partialDescriptors(modelClass) { 21 | if (modelClass._partialDescriptors) { 22 | return modelClass._partialDescriptors(); 23 | } else if(modelClass.type && modelClass.type._partialDescriptors) { 24 | return modelClass.type._partialDescriptors(); 25 | } else { 26 | return []; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BookingSync/ember-data-partial-model/423fca5037cc8d2aa6ef401ddc4a5c34adc1cf4a/app/.gitkeep -------------------------------------------------------------------------------- /app/adapters/application.js: -------------------------------------------------------------------------------- 1 | import PartialModelAdapter from 'ember-data-partial-model/mixins/adapter'; 2 | import JSONAPIAdapter from 'ember-data/adapters/json-api'; 3 | 4 | export default JSONAPIAdapter.extend(PartialModelAdapter); 5 | -------------------------------------------------------------------------------- /app/serializers/application.js: -------------------------------------------------------------------------------- 1 | import PartialModelJSONAPISerializer from 'ember-data-partial-model/mixins/jsonapi-serializer'; 2 | import JSONAPISerializer from 'ember-data/serializers/json-api'; 3 | 4 | export default JSONAPISerializer.extend(PartialModelJSONAPISerializer); 5 | -------------------------------------------------------------------------------- /app/services/store.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | import PartialModelStore from 'ember-data-partial-model/mixins/store'; 3 | const { Store } = DS; 4 | 5 | export default Store.extend(PartialModelStore, {}); 6 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-data-partial-model", 3 | "dependencies": { 4 | "ember": "2.3.1", 5 | "ember-cli-shims": "0.1.0", 6 | "ember-cli-test-loader": "ember-cli-test-loader#0.1.3", 7 | "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.4", 8 | "ember-qunit": "0.3.3", 9 | "ember-qunit-notifications": "0.0.7", 10 | "ember-resolver": "~0.1.15", 11 | "jquery": "1.11.3", 12 | "loader.js": "ember-cli/loader.js#3.2.0", 13 | "qunit": "~1.17.1", 14 | "pretender": "~0.6.0", 15 | "ember-inflector": "~1.3.1", 16 | "lodash": "~3.7.0", 17 | "Faker": "~2.1.5", 18 | "es5-shim": "^4.0.5" 19 | }, 20 | "resolutions": { 21 | "ember": "2.3.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/ember-try.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | scenarios: [ 3 | { 4 | name: '2.0', 5 | dependencies: { 6 | 'ember': '2.0.3', 7 | 'ember-data': '2.0.1', 8 | "ember-cli-shims": "0.0.6", 9 | } 10 | }, 11 | { 12 | name: '2.1', 13 | dependencies: { 14 | 'ember': '2.1.2', 15 | 'ember-data': '2.1.0', 16 | "ember-cli-shims": "0.0.6", 17 | } 18 | }, 19 | { 20 | name: '2.2', 21 | dependencies: { 22 | 'ember': '2.2.2', 23 | 'ember-data': '2.2.1', 24 | "ember-cli-shims": "0.0.6", 25 | } 26 | }, 27 | { 28 | name: '2.3', 29 | dependencies: { 30 | 'ember': '2.3.2', 31 | 'ember-data': '2.3.3', 32 | "ember-cli-shims": "0.1.0", 33 | } 34 | }, 35 | { 36 | name: '2.4', 37 | dependencies: { 38 | 'ember': '2.4.6', 39 | 'ember-data': '2.4.3', 40 | "ember-cli-shims": "0.1.0", 41 | } 42 | }, 43 | { 44 | name: '2.5', 45 | dependencies: { 46 | 'ember': '2.5.1', 47 | 'ember-data': '2.5.3', 48 | "ember-cli-shims": "0.1.0", 49 | } 50 | }, 51 | { 52 | name: '2.6', 53 | dependencies: { 54 | 'ember': '2.6.2', 55 | 'ember-data': '2.6.1', 56 | "ember-cli-shims": "0.1.0", 57 | } 58 | }, 59 | { 60 | name: '2.7', 61 | dependencies: { 62 | 'ember': '2.7.0', 63 | 'ember-data': '2.7.0', 64 | "ember-cli-shims": "0.1.0", 65 | } 66 | }, 67 | { 68 | name: 'default', 69 | dependencies: { 70 | 71 | } 72 | }, 73 | { 74 | name: 'ember-release', 75 | dependencies: { 76 | 'ember': 'components/ember#release' 77 | }, 78 | resolutions: { 79 | 'ember': 'release' 80 | } 81 | }, 82 | { 83 | name: 'ember-beta', 84 | dependencies: { 85 | 'ember': 'components/ember#beta' 86 | }, 87 | resolutions: { 88 | 'ember': 'beta' 89 | } 90 | }, 91 | { 92 | name: 'ember-canary', 93 | dependencies: { 94 | 'ember': 'components/ember#canary' 95 | }, 96 | resolutions: { 97 | 'ember': 'canary' 98 | } 99 | } 100 | ] 101 | }; 102 | -------------------------------------------------------------------------------- /config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(/* environment, appConfig */) { 4 | return { }; 5 | }; 6 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | /* global require, module */ 3 | 4 | var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); 5 | 6 | /* 7 | This Brocfile specifes the options for the dummy test app of this 8 | addon, located in `/tests/dummy` 9 | 10 | This Brocfile does *not* influence how the addon or the app using it 11 | behave. You most likely want to be modifying `./index.js` or app's Brocfile 12 | */ 13 | 14 | module.exports = function(defaults) { 15 | var app = new EmberAddon(defaults, {}); 16 | 17 | return app.toTree(); 18 | }; 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 'use strict'; 3 | 4 | module.exports = { 5 | name: 'ember-data-partial-model' 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-data-partial-model", 3 | "version": "0.4.0", 4 | "description": "Add support for partial models to Ember Data.", 5 | "directories": { 6 | "doc": "doc", 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "start": "ember server", 11 | "build": "ember build", 12 | "test": "ember try:testall" 13 | }, 14 | "repository": "https://github.com/BookingSync/ember-data-partial-model", 15 | "engines": { 16 | "node": ">= 0.10.0" 17 | }, 18 | "author": "Sebastien Grosjean", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "broccoli-asset-rev": "^2.0.2", 22 | "ember-cli": "1.13.8", 23 | "ember-cli-app-version": "1.0.0", 24 | "ember-cli-content-security-policy": "0.4.0", 25 | "ember-cli-dependency-checker": "^1.0.0", 26 | "ember-cli-es5-shim": "^0.1.1", 27 | "ember-cli-htmlbars": "1.0.1", 28 | "ember-cli-ic-ajax": "0.1.1", 29 | "ember-cli-inject-live-reload": "^1.3.0", 30 | "ember-cli-mirage": "^0.1.11", 31 | "ember-cli-pretender": "0.5.0", 32 | "ember-cli-qunit": "0.3.13", 33 | "ember-cli-uglify": "^1.0.1", 34 | "ember-data": "2.3.3", 35 | "ember-disable-prototype-extensions": "^1.0.0", 36 | "ember-disable-proxy-controllers": "^1.0.0", 37 | "ember-export-application-global": "^1.0.2", 38 | "ember-try": "0.0.4" 39 | }, 40 | "keywords": [ 41 | "ember-addon", 42 | "ember-data", 43 | "model", 44 | "partial" 45 | ], 46 | "dependencies": { 47 | "ember-cli-babel": "^5.0.0" 48 | }, 49 | "ember-addon": { 50 | "configPath": "tests/dummy/config" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /testem.json: -------------------------------------------------------------------------------- 1 | { 2 | "framework": "qunit", 3 | "test_page": "tests/index.html?hidepassed", 4 | "disable_watching": true, 5 | "launch_in_ci": [ 6 | "PhantomJS" 7 | ], 8 | "launch_in_dev": [ 9 | "PhantomJS", 10 | "Chrome" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "server", 4 | "document", 5 | "window", 6 | "location", 7 | "setTimeout", 8 | "$", 9 | "-Promise", 10 | "define", 11 | "console", 12 | "visit", 13 | "exists", 14 | "fillIn", 15 | "click", 16 | "keyEvent", 17 | "triggerEvent", 18 | "find", 19 | "findWithAssert", 20 | "wait", 21 | "DS", 22 | "andThen", 23 | "currentURL", 24 | "currentPath", 25 | "currentRouteName" 26 | ], 27 | "node": false, 28 | "browser": false, 29 | "boss": true, 30 | "curly": false, 31 | "debug": false, 32 | "devel": false, 33 | "eqeqeq": true, 34 | "evil": true, 35 | "forin": false, 36 | "immed": false, 37 | "laxbreak": false, 38 | "newcap": true, 39 | "noarg": true, 40 | "noempty": false, 41 | "nonew": false, 42 | "nomen": false, 43 | "onevar": false, 44 | "plusplus": false, 45 | "regexp": false, 46 | "undef": true, 47 | "sub": true, 48 | "strict": false, 49 | "white": false, 50 | "eqnull": true, 51 | "esnext": true 52 | } 53 | -------------------------------------------------------------------------------- /tests/acceptance/rentals-test.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import { module, test } from 'qunit'; 3 | import startApp from '../helpers/start-app'; 4 | 5 | var app; 6 | var rentals; 7 | var rentalExtended; 8 | 9 | module('Acceptance: Rentals using JSONAPI serializer', { 10 | beforeEach: function() { 11 | app = startApp(); 12 | rentals = server.createList('rental', 2); 13 | rentalExtended = server.create('rental_extended'); 14 | }, 15 | 16 | afterEach: function() { 17 | Ember.run(app, 'destroy'); 18 | } 19 | }); 20 | 21 | test("I can view all rentals", function(assert) { 22 | visit('/rentals'); 23 | 24 | andThen(function() { 25 | assert.equal(currentRouteName(), 'rentals.index'); 26 | assert.equal(find('li').length, 2); 27 | }); 28 | }); 29 | 30 | test("I can view a rental with partial model loaded", function(assert) { 31 | visit('/rentals/1'); 32 | 33 | andThen(function() { 34 | assert.equal(currentRouteName(), 'rentals.rental'); 35 | assert.equal(find('.name').val(), "Rental 0"); 36 | assert.equal(find('.description').val(), "Awesome Villa-0"); 37 | }); 38 | }); 39 | 40 | test("I can create a new rental and it's partial model values", function(assert) { 41 | visit('/rentals/new'); 42 | 43 | fillIn('.name', 'VillasThalassa'); 44 | fillIn('.description', 'Awesome villas'); 45 | click('.save-btn'); 46 | 47 | andThen(function() { 48 | assert.equal(currentRouteName(), 'rentals.rental'); 49 | assert.equal(find('.name').val(), "VillasThalassa"); 50 | assert.equal(find('.description').val(), "Awesome villas"); 51 | }); 52 | }); 53 | 54 | test("I can edit an existing rental and it's partial model values", function(assert) { 55 | visit('/rentals/1'); 56 | 57 | fillIn('.name', 'Villa Sivota'); 58 | fillIn('.description', 'Awesome villa in Greece'); 59 | click('.save-btn'); 60 | 61 | andThen(function() { 62 | assert.equal(currentRouteName(), 'rentals.rental'); 63 | assert.equal(find('.name').val(), "Villa Sivota"); 64 | assert.equal(find('.description').val(), "Awesome villa in Greece"); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /tests/acceptance/users-test.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import { module, test } from 'qunit'; 3 | import startApp from '../helpers/start-app'; 4 | 5 | var app; 6 | var users; 7 | var userExtended; 8 | 9 | module('Acceptance: Users using REST serializer', { 10 | beforeEach: function() { 11 | app = startApp(); 12 | users = server.createList('user', 2); 13 | userExtended = server.create('user_extended'); 14 | }, 15 | 16 | afterEach: function() { 17 | Ember.run(app, 'destroy'); 18 | } 19 | }); 20 | 21 | test("I can view all users", function(assert) { 22 | visit('/'); 23 | 24 | andThen(function() { 25 | assert.equal(currentRouteName(), 'users.index'); 26 | assert.equal(find('li').length, 2); 27 | }); 28 | }); 29 | 30 | test("I can view a user with partial model loaded", function(assert) { 31 | visit('/users/1'); 32 | 33 | andThen(function() { 34 | assert.equal(currentRouteName(), 'users.user'); 35 | assert.equal(find('.name').val(), "User 0"); 36 | assert.equal(find('.twitter-handle').val(), "@user-0"); 37 | }); 38 | }); 39 | 40 | test("I can create a new user and it's partial model values", function(assert) { 41 | visit('/users/new'); 42 | 43 | fillIn('.name', 'Seb'); 44 | fillIn('.twitter-handle', '@sebgrosjean'); 45 | click('.save-btn'); 46 | 47 | andThen(function() { 48 | assert.equal(currentRouteName(), 'users.user'); 49 | assert.equal(find('.name').val(), "Seb"); 50 | assert.equal(find('.twitter-handle').val(), "@sebgrosjean"); 51 | }); 52 | }); 53 | 54 | test("I can edit an existing user and it's partial model values", function(assert) { 55 | visit('/users/1'); 56 | 57 | fillIn('.name', 'Karol'); 58 | fillIn('.twitter-handle', '@Azdaroth'); 59 | click('.save-btn'); 60 | 61 | andThen(function() { 62 | assert.equal(currentRouteName(), 'users.user'); 63 | assert.equal(find('.name').val(), "Karol"); 64 | assert.equal(find('.twitter-handle').val(), "@Azdaroth"); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /tests/dummy/app/adapters/application.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import DS from 'ember-data'; 3 | import PartialModelAdapter from 'ember-data-partial-model/mixins/adapter'; 4 | const { RESTAdapter } = DS; 5 | 6 | export default RESTAdapter.extend(PartialModelAdapter, { 7 | namespace: 'api' 8 | }); 9 | -------------------------------------------------------------------------------- /tests/dummy/app/app.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import Resolver from 'ember/resolver'; 3 | import loadInitializers from 'ember/load-initializers'; 4 | import config from './config/environment'; 5 | 6 | var App; 7 | 8 | Ember.MODEL_FACTORY_INJECTIONS = true; 9 | 10 | App = Ember.Application.extend({ 11 | modulePrefix: config.modulePrefix, 12 | podModulePrefix: config.podModulePrefix, 13 | Resolver: Resolver 14 | }); 15 | 16 | loadInitializers(App, config.modulePrefix); 17 | 18 | export default App; 19 | -------------------------------------------------------------------------------- /tests/dummy/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BookingSync/ember-data-partial-model/423fca5037cc8d2aa6ef401ddc4a5c34adc1cf4a/tests/dummy/app/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BookingSync/ember-data-partial-model/423fca5037cc8d2aa6ef401ddc4a5c34adc1cf4a/tests/dummy/app/controllers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/rentals.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(rental) { 6 | rental.save() 7 | .then(rental => { 8 | this.transitionToRoute('rentals.rental', rental); 9 | }) 10 | .catch(error => { 11 | console.log('TODO: handle errors'); 12 | }); 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/rentals/new.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(rental) { 6 | rental.save() 7 | .then(rental => { 8 | this.transitionToRoute('rentals.rental', rental); 9 | }) 10 | .catch(error => { 11 | console.log('TODO: handle errors'); 12 | }); 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/rentals/rental.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(rental) { 6 | rental.save().catch(error => { 7 | console.log('TODO: handle errors'); 8 | }); 9 | } 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/users.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(user) { 6 | user.save() 7 | .then(user => { 8 | this.transitionToRoute('users.user', user); 9 | }) 10 | .catch(error => { 11 | console.log('TODO: handle errors'); 12 | }); 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/users/new.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(user) { 6 | user.save() 7 | .then(user => { 8 | this.transitionToRoute('users.user', user); 9 | }) 10 | .catch(error => { 11 | console.log('TODO: handle errors'); 12 | }); 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/users/user.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | actions: { 5 | save(user) { 6 | user.save().catch(error => { 7 | console.log('TODO: handle errors'); 8 | }); 9 | } 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /tests/dummy/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BookingSync/ember-data-partial-model/423fca5037cc8d2aa6ef401ddc4a5c34adc1cf4a/tests/dummy/app/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |3 | Name: {{input value=model.name class="name"}} 4 |
5 |6 | Description: {{input value=model.description class="description"}} 7 |
8 | 9 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/rentals/rental.hbs: -------------------------------------------------------------------------------- 1 |3 | Name: {{input value=model.name class="name"}} 4 |
5 |6 | Description: {{input value=model.description class="description"}} 7 |
8 | 9 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/users.hbs: -------------------------------------------------------------------------------- 1 |3 | Name: {{input value=model.name class="name"}} 4 |
5 |6 | Twitter handle: {{input value=model.twitter class="twitter-handle"}} 7 |
8 | 9 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/users/user.hbs: -------------------------------------------------------------------------------- 1 |3 | Name: {{input value=model.name class="name"}} 4 |
5 |6 | Twitter handle: {{input value=model.twitter class="twitter-handle"}} 7 |
8 | 9 | -------------------------------------------------------------------------------- /tests/dummy/config/environment.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 3 | module.exports = function(environment) { 4 | var ENV = { 5 | modulePrefix: 'dummy', 6 | environment: environment, 7 | baseURL: '/', 8 | locationType: 'auto', 9 | EmberENV: { 10 | FEATURES: { 11 | // Here you can enable experimental features on an ember canary build 12 | // e.g. 'with-controller': true 13 | } 14 | }, 15 | 16 | APP: { 17 | // Here you can pass flags/options to your application instance 18 | // when it is created 19 | } 20 | }; 21 | 22 | if (environment === 'development') { 23 | // ENV.APP.LOG_RESOLVER = true; 24 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 25 | // ENV.APP.LOG_TRANSITIONS = true; 26 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 27 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 28 | } 29 | 30 | if (environment === 'test') { 31 | // Testem prefers this... 32 | ENV.baseURL = '/'; 33 | ENV.locationType = 'none'; 34 | 35 | // keep test console output quieter 36 | ENV.APP.LOG_ACTIVE_GENERATION = false; 37 | ENV.APP.LOG_VIEW_LOOKUPS = false; 38 | 39 | ENV.APP.rootElement = '#ember-testing'; 40 | } 41 | 42 | if (environment === 'production') { 43 | 44 | } 45 | 46 | return ENV; 47 | }; 48 | -------------------------------------------------------------------------------- /tests/dummy/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |