pg-promise format default - not existing Property to null - javascript

I would like to be able to have the formatting.formatValue function convert undefined into null.
But there does not appear to be a way that I can set the default function from the initOptions given to pg-promise as pgFormatting is a boolean, format value wants it as an argument. But the library does not appear to pass it for normal queries.
vitaly-t wrote
But i'm not sure how much value it would add, since you do not have access to formatting options from query methods.
And that is true. But I kind of just want to set a default of null for all missing values being formatted into queries. Partial does not mater I don't use it?
Using coalesce to have "optional" values in some of the queries, to default not set variables anyway.
Example:
UPDATE sometable SET value = COALESCE(${value}, value)
How can I stop getting the "Property doesn't exist Error?
I think that I need a way to pass a value to this options for all calls to the format.
if ('default' in options) {
const d = options.default, value = typeof d === 'function' ? d.call(obj, v.name, obj) : d;
return formatValue(value, v.fm, obj);
}
Related issue that led to creation of options.default.
https://github.com/vitaly-t/pg-promise/issues/173
I can't over-ride the format value function as it is added as a non configurable read only property.
Do I just have to bite the bullet and put the variables in as null everywhere I want them to be optional...

I kind of just want to set a default of null for all missing values being formatted into queries...
Here's your formatting function for this, if you want to format queries manually:
function format(query, values) {
return pgp.as.format(query, values, {'default': null});
}
And for automatically generated queries within the helpers namespace, you would provide the value for property def, as per the Column API.
Other than that, the query methods make use of the format function on their own, so you cannot override that, neither you should, it is generally not needed, if you make the right use of the library's API, i.e. if you can give me a specific example of where you think you need it, then I can advise you of the better approach that avoids it.
One other approach - method helpers.concat can consume the formatting options, as it implements a specific case of joining queries.

Related

In Javascript/Typescript can I recursively deserialize a Protobuf object with nested fields while omitting optional fields which are not present?

I am using protocol buffers for sending changed state in a multiplayer game and I am wondering if there as a better way to unpack an object with nested fields that may or may not be present. I want non-present fields to be completely omitted, rather than listed as their default value.
Currently I am checking each field for presence by using the .hasField() methods on each property of the object. If that field exists and it has nested properties I have to use the .hasField() method of those properties, and so on. I leads me to write code like what is below, which I find to be verbose and error prone.
What I really want is something like the provided .toObject() method on the deserializedMessage, but with a slightly different behavior. The .toObject() includes all the fields (if they were not set they are the default values). I don't want optional fields which were not set to be shown because I only want fields which have changed so I can apply the changes to the client's game state.
Is there any built-in feature of protobuf or npm package that can accomplish this?
I am using proto3 and ts-protoc-gen to compile the .proto file into Typescript and Javascript
What I'm currently doing:
const playerProto = PlayerProto.deserializeBinary(binaryData)
const unpackedDeltas: IUnpackedPlayerDeltas = {};
const destination = playerProto.hasDestination() ? playerProto.getDestination() : null;
if (destination) unpackedDeltas.destination = new Point(destination.getX(),destination.getY());
if (playerProto.hasIsselected()) unpackedDeltas.isSelected = playerProto.getIsselected();
// etc for each property and their nested properties...
return unpackedDeltas;
What I would like:
const playerProto = PlayerProto.deserializeBinary(binaryData)
const unpackedDeltas = playerProto.toDeepObjectWithoutAbsentFields() // returns an object containing only the fields that were set on the server. does not include any default values for fields that were not set.

GraphQL optional Query Arguments

I know you can set arguments in a schema to default values but is it possible to make the argument limit argument completely optional in my GraphQL Schema?
Right now it seems like when I hit this without specifying a limit I think that's why I get Int cannot represent non-integer value: undefined
const schema = buildSchema(`
companies(limit: Int): [Company]
...)
I want to be able to skip the limit so that it gets all companies.
In JS, I call it like this:
query: `query {
companies(limit: ${limit}) {
...
but sometimes I don't want to specify a limit. So what is happening is the client is sending crafters(limit: undefined) and it's probably trying to convert that to Int. I'm not sure how to not send limit in and how to make that entire param optional.
(I also read that from the client I should be instead specifying the arguments as variables like query($limit: Int) { companies(limit: $limit) { I guess from my client, from JS? If so how would I send in my limit JS variable into that?
Arguments in GraphQL are nullable (i.e. optional) by default. So if your type definition looks like this:
companies(limit: Int): [Company]
there is nothing else you need to do to make limit optional -- it already is. If you wanted to make limit required, you would make it non-nullable by appending a ! to the type like this:
companies(limit: Int!): [Company]
The errors you are seeing are unrelated to the type of the limit argument. The issue is with the query that you're sending, which based on the error messages, looks something like this:
query ($limit: Int){
companies (limit: undefined) {
# ...
}
}
There's two issues here: One, you are defining a variable ($limit) that you never actually use inside the query (as indicated by the second error). Two, you are setting the limit to undefined, which isn't a valid literal in GraphQL.
Instead of using string interpolation, you should use variables to pass any dynamic values to your query. For example:
query ($limit: Int){
companies (limit: $limit) {
# ...
}
}
If the variable is nullable (notice we used Int instead of Int!), then it can be omitted from the request entirely, effectively making the value of the argument undefined server-side. It's unclear how you're sending your requests to the server, but assuming you're not using some client library, you can check the documentation here for how to structure your request. Otherwise, check your library's documentation for how to correctly use variables with your query.
Below is an example of how you could define a query on client and pass non-required argument. Not sure about your client-side config, but you may want to use a lib like graphql-tag to convert string to AST.
const GET_COMPANIES = gql`
query Companies($limit: Int) {
companies(limit: $limit) {
... // return fields
}
}
`;

What is the purpose of using getters and setters in angular2?

i am new to angular2 and when i was reviewing someone's code, one specific line got me confused
get formData() { return <FormArray>this.lienHolder.get('policyDetails'); }
why is the above line any different from this
formData() { return <FormArray>this.lienHolder.get('policyDetails'); }
I searched about this in google and found no actual results, can anyone help me to understand this.
UPDATE
what is the difference between this
var obj = { log: 0, get latest() { return this.log++; } };
and this
var obj = { log: 0, latest() { return this.log++; } };
both are giving me the updated value all the time i call them
obj.latest & obj.latest() -- returns updated result all the time then why use one over another?
get formData()
is called a getter accessor. It allows you get the property dynamically. It always should return a value.
https://www.typescriptlang.org/docs/handbook/classes.html
TypeScript supports getters/setters as a way of intercepting accesses
to a member of an object. This gives you a way of having finer-grained
control over how a member is accessed on each object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
Sometimes it is desirable to allow access to a property that returns a
dynamically computed value, or you may want to reflect the status of
an internal variable without requiring the use of explicit method
calls. In JavaScript, this can be accomplished with the use of a
getter.
In opposite to that, getFormDate() is a function, it can take arguments and not always returns values.
One of the cases, where I like to use a getter is when a property should be get from a service:
<p>{{dictionary.label1}}</p>
and then I get it from a service like this:
get dictionary(){
return this.myService.getDictionary();
}
this way when the service changed the data I dynamically can receive the value to my binding/model.
If I would have defined as the following:
dictionary: [];
ngOnInit(){
this.dictionary = this.myService.getDictionary();
}
then I would be 'stuck' with the old data while the service already received the new set of data. Of course, you can then set a change listener and trigger the update, but it's more code!
Think of getters as dynamic class properties.
UPDATE:
For the examples in your updated post, it's true, they give the same result, and it's a good thing! You can use both, but as they don't work similarly, you can have more options in some cases. It's not like only one or only the other, or which one is the best. In most of cases you can use both, it's where and for what you need to use them. Most of the times, it's a method which is used, as it has more comprehensive use: we use methods with or without parameters, to trigger actions on objects. But in some cases, again, it will not have the same flexibility as a getter. If you are hesitant which one to use, use the method first and when you see its limits, think if the getter would help you, as now you know what's its purpose, which is - a property, but dynamic!
An other example:
isShown:boolean; //is 'static', will return the same value unless you change it in some kind of a method
get isShown(){
return this.someCondition && this.someMethodResult() || this.anotherCondition
}
If someCondition and anotherCondition change and the result from someMethodResult had to come changed you don't have to request isShown value, it's done dynamically.
Opposite of that, you can have
setShown(){ //the method
this.isShow = !this.isShown;
}
Here setShown needs to be called so isShown could be updated.
Also, a getter can easily replace a method which only job is to return a class property value.
UPDATE2:
An other 'good' example for get. A case when a component needs to check if the user is logged to show/hide some buttons. Instead of subscribing to changes, you do:
HTML:
<button [hidden]="!isLogged">Log out</button>
Typescript:
get isLoggedIn(){
return this.authService.isLoggedIn();
}
And that's it! If the user is logged out the button will be disabled 'immediatly'. No nead for the heavy subscribe/unsubscribe...
with the get you can treat it like a var:
let something = formData;
otherwise you must invoke the function:
let something = formData();
You would use a get usually to format data as you retrieve it. for example:
let _number = '12';
get number(){
return parseInt(_number);
}

How to create an Ember computed property that adds 1 to a property?

I'm just learning Ember and I'm a bit confused about computed properties. Everything in the guides uses strings, like a computed property that creates a full name out of a first and last name, etc. Anyway, I'm confused about how to use integers because it seems like the syntax almost demands the use of strings.
As an example, I have a property on my controller called count.
import Ember from 'ember';
export default Ember.Controller.extend({
count: 0,
counter: Ember.computed('count', function() {
var num = `${this.get('count')}`;
var newNum = parseInt(num) + 1;
this.set('count', newNum);
return this.get('count');
})
});
I know this code is really bad, I'm just trying to illustrate what I'm trying to do and failing at. Why does Ember.computed take a string as its first parameter?
And why do I have to use a string in this.get and this.set when I'm working with an integer, not a string? I have to manually parse the int or else it returns a string, why is it converting my count property into a string?
Anyway, in the ember inspector when I run
$E.get('count')
it does successfully add 1, but fails to continue to add 1, which makes me think its not updating the actual count property.
Thanks very much. I appreciate the help.
I set up a Ember Twiddle based on your code. I'll try to address each of your questions:
You can think of an Ember.Object as a wrapper around {}. All Ember.Object keys are Strings, because {} keys are strings in Javascript.
For each property stored on an Ember.Object, that property is a value with some String as its key. To look up that value, you have to provide the "path" or "location" of the value, as given by the key (just like a hash table). This is why you need to specify a string in get and set.
Values can be any type in Javascript, not just strings. Take a look at the Ember Twiddle I posted, and open up your console. In your code, num is a string because you've wrapped it in an ES6 template string, which is converting the value of this.get('count').
Ember.computed was designed to render data into templates. It's important to understand that:
It's lazy
It caches the result of the computation.
A Computed Property will only recompute if one or more of the properties it depends on changes.
When you call Ember.computed, you first pass in any number of strings. Each string is a path to a value (on an Ember.Object) that your CP "depends" on.
Because CPs are lazy, 'counter' will only be computed when you access it in your code, or in a template. If 'count' were to change, the cached value of 'counter' would be forgotten. The next time 'counter' were accessed, it would recompute.
In this case, the 'counter' CP function only runs once, because 'count' never changes. This is why you only observe one addition.

Backbone.js Modifying data in model before save

I was wondering how I would go about converting data when I call the set or save methods on a model. Specifically converting the inputted date string to epoch time.
I know I could just convert it in the view, but as far as I know, that wont work very well with my validations.
The model code is here if you are interested.
Thanks for any help!
What I can gather you have two options:
1 Convert them in your view
This means you can roll your own conversions for the view or use something like Backbone.modelbinder to make the conversions for you. Then you have to modify your validate method to accept an epoch date. Personally I would prefer this one, I think that it's suitable for the UI to handle verifying user input's well-formedness and conversion to the right unit and let the model handle validating if the values are within the accepted limits.
2 Convert them in your model
Backbone doesn't offer this out-of-the-box. If you set something to be something, there is no easy way to convert it to something else, especially between validate and set. Basically your best bet would be to roll your own set -function with something like
// Inside the set function
...
if (!this._validate(attrs, options)) return false; // real line in the set func
// insert something like this, after validate you know the values are eligible for conversion
attrs = this.convert(attrs); // a custom func that converts attributes to right units
...
// set continues as usual
Hope this helps!
You can overwrite the sync method in your model:
, sync: function(method, model) {
if(method === 'update'){
// change you model here
}
}
This will be invoke bevor data is send to the backend server. The "method" indecates 'create' or 'update'.
According to the sources, validate is the only callback that is called before set and save. You can to set the values in your validate method directly on the attributes object. Unfortunately you cannot make any changes to attributes at this point.
You can use a plugin like backbone.getters.setters to do this since it looks like it won't be a feature added to backbone.

Categories

Resources