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

default values are being overwritten in upsert #616

Merged
merged 2 commits into from
Jul 14, 2015
Merged

default values are being overwritten in upsert #616

merged 2 commits into from
Jul 14, 2015

Conversation

clarkbw
Copy link
Contributor

@clarkbw clarkbw commented Jun 5, 2015

clarkbw/loopback-ds-timestamp-mixin#11 was filed and it appears to be an issue with the upsert coming from juggler.

This PR creates a test that fails and I believe I’ve tracked down the area of the code that causes the issue, wrapped in console.log statements currently.

When you run the test it will print the following information:

not instance { id: 1000, name: 'updated name' }
inst { id: 1000,
  name: 'updated name',
  createdAt: Fri Jun 05 2015 09:59:03 GMT-0700 (PDT) }
      1) should preserve default property values

As you can see in the debug output the createdAt field is being generated and then overwriting the existing createdAt field. We need to prevent the default fields from being generated or passed to the update because default functions that are not idempotent will always be storing new values.

I’m investigating a solution, any comments are appreciated.

@@ -415,7 +415,9 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
var update = data;
var inst = data;
if(!(data instanceof Model)) {
console.log('not instance', data);
inst = new Model(data);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the constructor should have an option to skip default value generation in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll look into adding another option here: https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/model.js#L42
With that value turned on we skip the default value and defaultFn generation blocks.

@clarkbw
Copy link
Contributor Author

clarkbw commented Jun 5, 2015

What problem do you try to solve? Is it related to the default value override?

The memory connector was returning incorrect values such that my tests were working with the proposed changes but failing because of the memory connector issue.

In this test I'm trying to compare a Date object to what was being returned as a date represented by a string.
https://github.com/clarkbw/loopback-datasource-juggler/commit/5fa09c9fda6bad481ab418d2fe5c752b787f2b8b#diff-404450f6fd92e7f3f2031232213c07c5R637

Again, I can pull the memory connector issue out into a separate PR because it should be fixed and is separate from the issue related to this PR but was in the way of fixing it.

@raymondfeng
Copy link
Contributor

I think you should call fromDb inside the save method.

@clarkbw What's your take on the suggestion above?

@clarkbw
Copy link
Contributor Author

clarkbw commented Jun 5, 2015

What's your take on the suggestion above?

Just ran it through the tests, its the right call. Likely fixes an issue in the updateAttributes method as well.

@clarkbw
Copy link
Contributor Author

clarkbw commented Jun 7, 2015

Need to finish with more tests specifically for the setDefaultValues option.

@clarkbw
Copy link
Contributor Author

clarkbw commented Jun 10, 2015

Changed the option name to applyDefaultValues to fit in better with other option naming and usage.

@raymondfeng raymondfeng self-assigned this Jun 15, 2015
@clarkbw
Copy link
Contributor Author

clarkbw commented Jun 18, 2015

Did another pass over this change and I don't think there's a need for more individual tests on the applyDefaultValues option. Let me know if you feel otherwise.

@raymondfeng I think this is ready for your review

callback(err, data, { isNewInstance: !modelData });
});
callback(err, this.fromDb(model, data), { isNewInstance: !modelData });
}.bind(this));
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use self instead of bind? bind is expensive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, sorry. Fixed.

clarkbw added 2 commits July 14, 2015 09:08
Changes the after `save` callback in the memory connector to use the
`fromDb` method to deserialize the data passed back to upsert and
updateAttributes methods.
Creates a new applyDefaultValues option on the Model constructor
defaulting to true, the current behaviour.

Updates the dao module to pass `{ applyDefaultValues: false }` to the
Model constructor during the updateOrCreate method when we assume an
update is happening.
@clarkbw
Copy link
Contributor Author

clarkbw commented Jul 14, 2015

@raymondfeng I updated the memory connector as you requested to use self = this instead of bind. The code has been rebased to the master branch and passes all tests. Let me know if there's anything else you'd like to see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants