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

Failing test for ember data model. #406

Merged
merged 3 commits into from
Jan 15, 2020
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
15 changes: 13 additions & 2 deletions addon/utils/merge-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,19 @@ function propertyIsOnObject(object: any, property: any) {
}
}

// Ember Data models don't respond as expected to foo.hasOwnProperty, so we do a special check
function hasEmberDataProperty(target: any, key: string, options: Options): Boolean {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, this should have the lowercase boolean as the return type, but I tried to follow the conventions that were already here.

let fields: Map<string, any> | null = options.safeGet(target, 'constructor.fields');

return fields instanceof Map && fields.has(key);
}

// Protects from prototype poisoning and unexpected merging up the prototype chain.
function propertyIsUnsafe(target: any, key: string): Boolean {
function propertyIsUnsafe(target: any, key: string, options: Options): Boolean {
if(hasEmberDataProperty(target, key, options)) {
return false;
}

return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
&& Object.propertyIsEnumerable.call(target, key)); // and also unsafe if they're nonenumerable.
Expand Down Expand Up @@ -78,7 +89,7 @@ function buildPathToValue(source: any, options: Options, kv: Record<string, any>
function mergeTargetAndSource(target: any, source: any, options: Options): any {
getKeys(source).forEach(key => {
// proto poisoning. So can set by nested key path 'person.name'
if (propertyIsUnsafe(target, key)) {
if (propertyIsUnsafe(target, key, options)) {
// if safeSet, we will find keys leading up to value and set
if (options.safeSet) {
const kv: Record<string, any> = buildPathToValue(source, options, {}, []);
Expand Down
4 changes: 4 additions & 0 deletions tests/dummy/app/models/profile.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import DS from 'ember-data';
import attr from 'ember-data/attr';
import { belongsTo } from 'ember-data/relationships';


export default DS.Model.extend({
firstName: attr('string', { defaultValue: 'Bob' }),
lastName: attr('string', { defaultValue: 'Ross' }),

pet: belongsTo('dog'),
});
17 changes: 17 additions & 0 deletions tests/integration/main-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,21 @@ module('Integration | main', function(hooks) {
dogs = changeset.get('dogs');
assert.equal(dogs.length, 2, 'changeset has 2 dogs');
});

test("can save ember data model with multiple attributes", async function (assert) {
assert.expect(1);

let save = () => {
assert.ok(true, "user save was called");
};
let profile = this.store.createRecord("profile", { save });
let pet = this.store.createRecord('dog')
let profileChangeset = new Changeset(profile);

profileChangeset.set("firstName", "bo");
profileChangeset.set("lastName", "jackson");
profileChangeset.set('pet', pet)

profileChangeset.save();
});
});