dynamic datatype for field in mongoid? - mongoid

I have a model class as :-
class TestParam
include Mongoid::Document
include Mongoid::Timestamps
field :parameter_id, type: String
field :parameter_key, type: String
field :range_max, type: String
field :range_min, type: String
field :unit, type: String
field :multiple, type: Boolean
field :value, type: Array or String
embeds_in :test
end
Now my problem details is as:-
1) If field 'multiple' is true, then datatype for 'value' should be array, else if field 'multiple' is false, then datatype for 'value' field should be string. How can we solve this problem using mongoid (5.1.0) ? Thanks, Happy Coding.

Related

Define type based on value of keys in an object

I am adding one Select component that has the following structure.
type Option = {
value: string | number
label: string;
icon?: string
}
type SelectProps = {
labelKey?: string;
iconKey?: string;
valueKe?: string;
options: Option[]
}
function Select({
labelKey = 'label',
iconKey = 'icon',
valueKey= 'value',
groupBy = 'groupBy',
options// need to type Option
}: SelectProps) {
// some logic to render options
// options.map(option => (<li key={option[valueKey]}>{option[labelKey]}</li>))
}
Here, options is an array of options and I am trying to give flexibility to users to provide keys to use for labels, icons etc so the user doesn't need to map data all the time.
For now, the Option type has hardcode keys like label, value, icon but I want to create this type based on values passed to labelKey, valueKey, iconKey etc.
For example, if a user passes the labelKey="name" prop then the Option type should allow the following data:
[ {
name: 'Product',
value: 'product',
icon: 'product'
}]
So far I have tried the following implementation but it sets all keys' types to string.
type OptionKeys = {labelKey: string, valueKey: string, iconKey: string}
type Option<T extends OptionKeys> = {
[label in T["labelKey" | "valueKey" | "iconKey"]]: string // all the types are string
}
type SelectProps<T extends OptionKeys = {
labelKey: 'label',
valueKey: 'value',
iconKey: 'icon'
}> = {
labelKey?: string
valueKey?: string;
iconKey?: string;
options: Option<T>[]
}
Here, the Option's keys have value of type string but I want to define type based on key. For example, if the key is labelKey, I want its value to be number | string etc.
One option, I see here is to accept OptionType from outside by making the Select component generic but in that case, I need to refactor my component and want to avoid this refactoring at the moment.
How can I update my type to handle this scenario?
Using the FromEntries type from this blog post: https://dev.to/svehla/typescript-object-fromentries-389c,
Define the SelectProps type as follows:
type SelectProps<LK, VK, IK> = {
labelKey?: LK
valueKey?: VK
iconKey?: IK
options: FromEntries<[
[LK, string],
[VK, string | number],
[IK, string | undefined]
]>
}
We have three keys in the options, the label key (LK) which is a string, the value key (VK) which is a string | number and the icon key (IK) which is a string | undefined
Now we define the Select function as follows:
function Select<
LK extends string = 'label',
VK extends string = 'value',
IK extends string = 'icon'
>(props: SelectProps<LK, VK, IK>) {}
It is important to put the default key names on the function itself rather than the SelectProps type. I am not sure why.
Full playground link

Ext.data.Model Validator OR Empty?

How can one set a field validator only if the field is not empty?
Eg: I want a validator to check for a url only if there is a value (like empty is allowed).
In the lower example, website should be allowed to be empty OR be a url.
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'integer' },
{ name: 'website', type: 'string', validators: ['url'] }
...
You can define your own validator with a similar regex. Check https://docs.sencha.com/extjs/7.0.0/modern/src/Url.js.html for the original version.
Appending ^$| you allow empty string as well.
Have a look here: https://fiddle.sencha.com/#view/editor&fiddle/30o9

Restricting cell to enter only numeric values in ngHandsontable

How can I restrict user to enter only numeric values in cell in ngHandsontable?
you can set the type to numeric. Also, you can set a validation using validator property.
columns:[
{
data: 'level',
type: 'numeric', /* or */
validator: new RegExp('^\\d+$')
}
]

extjs textarea returns field value as an array

I'm quite puzzled by this.
When I get my field values from my extjs form, the value for a textarea is not a string, but an array. The first element in the array is empty, and the second element contains the text in the textarea.
I am just calling getFieldValues() from my form like so :
var fields = form.getFieldValues();
My UI decleration looks like this :
{
xtype: 'textarea',
cls: 'packagedialog-information-textArea',
name: 'description'
}
In my Ext.data.Model it looks like this :
{name: 'description', type: 'string'},
Is it supposed to work like that? I was expecting a string to be returned.

Indexing mongoid

I've read the mongoid docs, but don't feel confident I properly understand how to index embedded documents correctly. Please take a look at this tiny code snippet and let me know if I am on the right track!
Criteria
temp = Array.new
temp.push(BSON::ObjectId("some_bson_objecId"))
temp.push(BSON::ObjectId("some_other_bson_objecId"))
Game.any_of({'players.user_id' => #user.id},{:_id => temp})
Game model
embeds_many :players
index(
[
[ "players.user_id" ],
[ "players.user_name" ]
],
unique: true
)
Player model
embedded_in :game
field :user_id, :type => BSON::ObjectId
field :user_name, :type => String, :default => ""
index(
[
[ :user_id ],
[ :user_name ]
],
unique: true
)
From Mongoid's Docs -
class Person
include Mongoid::Document
embeds_many :addresses
index "addresses.street" => 1
end
so try
class Game
include Mongoid::Document
embeds_many :players
index "players.user_id" => 1
index "players.user_name" => 1
end
class Player
include Mongoid::Document
embedded_in :game
field :user_id
field :user_name
index({ user_id: 1, user_name: 1 })
end
There is a couple of things you're missing.
You need to specify the direction to index each field that you've chosen (the reason explained here.)
You're not passing in your arguments to the index method correctly. Instead, the first argument should be a hash of the fields you'd like to index and the second argument should be a hash of options.
The proper syntax for what your code is trying to achieve is this:
Game model
embeds_many :players
index({
"players.user_id" => 1,
"players.user_name" => 1
}, {
unique: true
})
Player model
embedded_in :game
field :user_id, :type => BSON::ObjectId
field :user_name, :type => String, :default => ""
index({
user_id: 1,
user_name: 1
}, {
unique: true
})
Also, it seems like you are trying to index more than you need to. If you're just going to be searching through the games collection then there is no need to be indexing any of the fields in the Player model.
You should instead just index on the fields that you are going to be querying. In order to properly index the information that you are querying for, your code should look like this:
Game model
embeds_many :players
# The field of the 'games' collection that you will be querying for
index({ "players.user_id" => 1 })
Player model
embedded_in :game
field :user_id, :type => BSON::ObjectId
field :user_name, :type => String, :default => ""
# No indexing necessary for your player model.
More indexing may help if you are performing other queries, but keep in mind that indexing is a trade off of query time for space. MongoDB's website has some guidelines to help you decide whether or not you should index something. Also, remember that you can always query the data without an index, it will just be slower ;).

Resources