-
Notifications
You must be signed in to change notification settings - Fork 362
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
DataSource juggler is adding the model property with its default value in response #1692
Comments
@sharathmuthu6 you are modifying the source code and expecting it to behave in a certain way, which is not a valid issue in terms of the user API. I can help you achieve what you want to achieve, if you can describe your requirements with the use of the API exposed to the user. |
I have added the testcase in loopback-sandbox repo |
Hi @sharathmuthu6 you are overwriting the behavior of the connector with your own implementation. Memory.prototype.all = function all(model, data, options, callback) {
callback(null, [{'name': 'john'}]);
}; This code will have many other side effects, by the way. If you really intent to re-write the memory connector to your liking, you should go all the way and modifying everything to suite your needs and make it work for you. We can't help you with that. If you want to make the
to:
|
@sharathmuthu6 IIUC, you would like to define a model property that is filled with a default value when the model data is coming from the user (e.g. from incoming HTTP request body), but that is not applied to data coming from your backend service/database via connector. First of all, I think the current behavior is intentional. Even if it was not, we cannot easily change it - it would be a huge breaking change for existing LB applications. I don't have bandwidth to debug through our codebase, but I suspect the problem is caused by the following.
|
@sharathmuthu6 I think @hacksparrow may be correct that the problem is in your model definition. First of all, how can the backend datasource return model instances with a missing As for applying the default value. I see how the current behavior, where the default value is applied both on data coming from the clients but also on the data coming from the database, can be problematic. As I am thinking about it, it would seem more natural to me if the To preserve backwards compatibility, the new behavior must be implemented via a new feature flag that's disabled by default. I think that implementation wise, the easiest option is to introduce the flag in model settings: {
"name": "MyModel",
"properties": {
"age": {
"type": "number",
"required": false,
"default": 42,
},
"applyDefaultsOnReads": false,
}
} Example implementation in function buildResult(data, callback) {
const ctorOpts = {
fields: query.fields,
applySetters: false,
persisted: true,
};
if (Model.settings. applyDefaultsOnReads === false) {
ctorOpts.applyDefaultValues = false;
}
let obj;
try {
obj = new Model(data, ctorOpts);
} catch (err) {
return callback(err);
} Thoughts? |
As a temporary workaround, can you try to rework your model as follows?
|
Possibly related - notice the commit is more than 4 years old: |
I mostly agree with @hacksparrow 's comment in #1692 (comment), and still trying to understand what is the problem @sharathmuthu6 has... |
If your model property has a default value, e.g. If you want to exclude certain properties(fields) from the GET endpoints, you can use filter, see https://loopback.io/doc/en/lb3/Fields-filter.html |
We have further discussed this issue with Nagarjuna (@snarjuna). In their project, they are using PersistedModel to access a datasource that's not a database. As a result, the model is describing values that are not always returned back by the connector. While this may seem like they are using PersistedModel incorrectly, there are actually use cases where LoopBack's current behavior is problematic for databases too:
I'll go ahead and implement a solution based on #1692 (comment) and #1692 (comment) |
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing.
Proposed fix: #1704 |
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are fixing DAO operations like `find` and `findOrCreate` so that they do NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods were already not applying default values on database data as long as the connector provided native implementation of the operation.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are fixing DAO operations like `find` and `findOrCreate` so that they do NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods were already not applying default values on database data as long as the connector provided native implementation of the operation.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing. Also note that default values are applied only on properties with `undefined` values. The value `null` does not trigger application of default values. This is important because SQL connectors return `null` for properties with no value set.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing. Also note that default values are applied only on properties with `undefined` values. The value `null` does not trigger application of default values. This is important because SQL connectors return `null` for properties with no value set.
Before this change, when a property was configured with a default value at LoopBack side and the database was returned a record with a missing value for such property, then we would supply use the configured default. This behavior is problematic for reasons explained in #1692. In this commit, we are introducing a new model-level setting called `applyDefaultsOnReads`, which is enabled by default for backwards compatibility. When this setting is set to `false`, operations like `find` and `findOrCreate` will NOT apply default property values on data returned by the database (connector). Please note that most of the other CRUD methods did not apply default values on database data as long as the connector provided native implementation of the operation, that aspect is not changing. Also note that default values are applied only on properties with `undefined` values. The value `null` does not trigger application of default values. This is important because SQL connectors return `null` for properties with no value set.
Done. The fix is available in the following juggler versions: |
Description/Steps to reproduce
I created a simple loopback application with model name
testDefault
with its model defintion as below :DataSource of
testDefault
is as follows :Since it is an in-memory connector, i changed the
.all
method of memory connector (https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/connectors/memory.js#L504)to return
callback(null,[{"name":"john"}])
Once i start the app and do a GET on /testDefaults, i am getting the following response :
Link to reproduction sandbox
Expected result
My connector response(from endpoint) doesn't have age property, so i am expecting an output as below
In dao.js, https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/dao.js#L1637
A new model is being created, thats where i could see that
age
property is getting added.Additional information
Task list
master
(4.x): fix: do not apply default values on data from database #1704, Improve tests for empty vs. default values #17073.x
: Do not apply default values on data from database [3.x] #17052.x
: Do not apply default values on data from database [2.x] #1706The text was updated successfully, but these errors were encountered: