I have to validate value by value instead of passing in a whole schema for multiple values. Based on the docs for single value validation from here
https://hapi.dev/module/joi/
and this sample code
const validator: AnySchema = Joi.string().valid('foo', 'bar').required();
const validationResult: ValidationResult = validator.validate('invalid');
const validationError: ValidationError = validationResult.error;
if (validationError) {
throw validationError;
}
The code will throw an error with the following error message
ValidationError: "value" must be one of [foo, bar]
Is there an easy way I can replace "value" with a specific name? So when I want to validate environment the error message could be
ValidationError: "environment" must be one of [development, production,
test]
or is that only possible when validating multiple values at once?
There is the any.label(name) method that you can use and set a custom label that will be displayed in error messages as well:
any.label(name)
Overrides the key name in error messages.
name - the name of the key.
const schema = {
first_name: Joi.string().label('First Name')
};
You can simply do:
const validator: AnySchema = Joi
.string()
.label('Foo/Bar') // Change tha label using label method
.valid('foo', 'bar')
.required();
const validationResult: ValidationResult = validator.validate('invalid');
const validationError: ValidationError = validationResult.error;
if (validationError) {
throw validationError;
}
will output:
ValidationError: "Foo/Bar" must be one of [foo, bar]
Related
Using EF core 6.0.1, I'm following the example shown here for configuring the join table for a many-to-many relationship in a migration, but I can't get past this error:
The seed entity for entity type 'Classifier' cannot be added because
no value was provided for the required property 'Id'.
modelBuilder.Entity<Classifier>().HasData(
new Classifier
{
Id = 1,
Name = "Concerto",
}
);
modelBuilder.Entity<Composition>()
.HasData(
new Composition
{
Id = -1,
Name = "First Composition",
CreatorId = -1,
LastModifierId = -1,
CreatedDate = DateTime.Parse("01/01/2019"),
LastModifiedDate = DateTime.Parse("01/01/2019"),
Summary = "Lorem ipsum",
}
);
modelBuilder.Entity<Classifier>()
.HasMany(cl => cl.Compositions)
.WithMany(cm => cm.Classifiers)
.UsingEntity(j => j.ToTable("ClassifierCompositions")
)
.HasData(
new { ClassifiersId = 1, CompositionsId = -1, },
);
I've verified that the names used in the anonymous type used to configure the join match the autogenerated column names from EF. I suspect the error message is a poor representation of the real error, since clearly the Classifier.Id is provided. Why is this error being thrown?
Fwiw, the Composition table exists already as created by a previous migration and this migration is adding the Classifier table and join table.
I suspect the error message is a poor representation of the real error, since clearly the Classifier.Id is provided. Why is this error being thrown?
Actually the error is correct. It's because here
modelBuilder.Entity<Classifier>()
.HasMany(cl => cl.Compositions)
.WithMany(cm => cm.Classifiers)
.UsingEntity(j => j.ToTable("ClassifierCompositions")
) // <-- the problem
.HasData(
new { ClassifiersId = 1, CompositionsId = -1, },
);
you are executing the UsingEntity call, which returns EntityTypeBuilder<Classifier>, so the next HasData call is actually defining more Classifier data entries via anonymous type which of course has no Id property, hence the error message.
The correct action of course is to define the seed data for the join entity, using its entity builder inside the UsingEntity call, i.e.
modelBuilder.Entity<Classifier>()
.HasMany(cl => cl.Compositions)
.WithMany(cm => cm.Classifiers)
.UsingEntity(j => j
.ToTable("ClassifierCompositions")
.HasData(
new { ClassifiersId = 1, CompositionsId = -1, },
)
);
I have a map like this:
map = {
'container_1':0,
'container_2':0,
'container_3':0,
}
That's being created from an iterable like this:
map=Map.fromIterable(containerList, key: (e)=>e, value: (e)=>0);
But when I try to add this key and value, I get an error:
map['user']='User Name';
The error I get is:
Expected a value of type 'int', but got one of type 'String'
How do I add a key value to a map that has a different value type than what's already in it?
The type of the map variable is Map<String, int>, so you couldn't add a String value to it. If you can change map type to Map<String, Object> then you will be able to add String value to it. Like this:
final map = <String, Object>{
'container_1': 0,
'container_2': 0,
'container_3': 0,
};
map['user'] = 'User Name';
I'd prefer to initialize the map to have The key as String and the value as dynamic
Because the dynamic makes your variable type to be determined at the run type with any errors
final map = <String, dynamic>{
'container_1': 0,
'container_2': 0,
'container_3': 0,
};
map['user'] = 'User Name';
How should I get the password field value inside the when to compare the label value with the current value, so that I can strip the field?
*password: string().trim()
.notRequired()
.when(['$config', '$test', 'authenticationMethodType'],
(config: TestConfig, test: SyntheticPropertiesState,
authenticationMethodType: AuthenticationMethodType, schema: StringSchema):
StringSchema => {
const passwordPlaceholderCheck =
test?.authentication?.password !== Localize.PasswordPlaceholder;
if (passwordPlaceholderCheck) {
return schema.label(Localize.Password).required();
}
return schema.strip(true);
})
.max(63)
,*
I want to update only those fields in mongo document that have values in the POJO. How do I do this?
I have a User collection with the following document:
{
_id: ObjectId("someId"),
name: "Foo",
age: 20,
gender: "male"
}
Now I want to update only the age to 22 so, I have a User pojo with age = 22 and _id = ObjectId("someId").
I don't want to use Updates.set("age",22) because then I'll have to handle every field. The field to be populated may be something other than age.
So, I used reflection to make a generic method to get the list of Update.sets for the pojo
classMembers = User::class.memberProperties
// get hashmap from pojo
val fieldsMap: HashMap<String, Any> =
mapper.convertValue(pojo, object : TypeReference<HashMap<String, Any>>() {}) ?:
throw CustomException( HttpStatus.BAD_REQUEST, "Could not parse request" )
// get hashmap from default/empty pojo
val defaultMap: HashMap<String, Any> =
mapper.convertValue(emptyPojo, object : TypeReference<HashMap<String, Any>>() {}) ?:
throw CustomException( HttpStatus.BAD_REQUEST, "Could not parse request" )
for (member in classMembers) {
val name = member.name
val value = fieldsMap[name]
//add to list only if the current value is not null or default and current value is different
if (value != null && defaultMap[member.name] != value && member.getter.annotations.isNotEmpty()) {
val field = (member.getter.annotations[0] as BsonProperty).value
setList.add(Updates.set(field, value))
}
}
This works. But I wanted to know if theres a better way to do it? A default way to do this via mongoClient or mongoTemplate or mongoRepository?
I've got the REST API working with the user table provided in the base migration. I can "GET /users" just fine, but according to the docs, I should also be able to "GET /users?fields=id" and receive a response limited to the id fields.
But instead I get the full result set.
Under the topic Fields in Yii2 Guide it says;
// only returns field id and email, provided they are declared in fields()
http://localhost/users?fields=id,email
so you have to override the fields() function to get the expected result.
// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
return [
// field name is the same as the attribute name
'id',
// field name is "email", the corresponding attribute name is "email_address"
'email' => 'email_address',
// field name is "name", its value is defined by a PHP callback
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
];
}