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.
Related
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.
When calling .values() or .values_list() on a QuerySet you can pass in the specific fields you want returned, or even fields you want from related tables. What I'm wanting to do is include the result of a method defined on the model, in addition to some fields, for example:
class MyModel(models.Model):
name = models.CharField()
def favouriteNumber(self):
return random.randint(1,10)
list(MyModel.objects.all().values('name','favouriteNumber'))
=> [{'name':'Bob', 'favouriteNumber':6}, {'name':'Fred', 'favouriteNumber':4}]
The above doesn't work, but is what I'm wanting to do, in the same way that the templating language can treat model methods without parameters just like fields.
The reason I'm wanting to do this is so that I can pass the information to the JavaScript in the front end to use instead of making calls back to the server to retrieve it each time.
Assuming the above (or something similar) isn't possible, I know I could loop over my values() result afterwards and add in the extra information manually.. what would be the most efficient (and clean) way to do that?
You might want to try using only() instead of values(). Like values() it will only fetch the specified fields from the database, but unlike values() it will return actual instance objects that you can call methods on.
That way, whether you're looping in the view or the template, you can access the method in addition to the specified fields.
If you need dictionary-like structures (for json.dumps(), say) you can just construct them in a comprehension:
instances = MyModel.objects.only('name')
data = [{'name': instance.name,
'favourite': instance.favouriteNumber()} for instance in instances]
Well, this is not my first jQuery plugin but the first I think others would benefit from. So for me its the first time to make sure every possible application works as predicted.
My plugin handles modal less overlays and therefore has to save the overlay visibility in cookies.
At first I thought ok, I need one cookie to store the visibilitie. Of course this won't work as multiple elements can be overlays and therefore have different states.
The only solution I can think at this moment is, to normalize the used jQuery selector and use it as cookie path which in my opinion is no proper solution.
Additional resources
Plugin Demo
Plugin documentation and full source code
How can I save associatedelement data in a proper fashion?
Edit:
$.cookie(PLUGIN_IDENTIFIER+'IsVisible', settings._isVisible);
var isOverlayVisible = $.cookie(PLUGIN_IDENTIFIER+'IsVisible');
Store the id's with value in a JavaScript Object and then stringify / parse it with JSON:
// set;
$.cookie(PLUGIN_IDENTIFIER, JSON.stringify({ id1: true, id2: false }));
// get;
var obj = JSON.parse($.cookie(PLUGIN_IDENTIFIER));
Or use [Session|Local|Global]Storage...
I'm writing a jQuery plugin that works on a piece of JSON data object.
This data needs to be calculated by the plugin only once, so I want to calculate it on the first call to the plugin and store it to be used in every subsequent call.
My questtion is whether there's a standard and accepted methodology for storing data used by jQuery plugins.
Assuming my plugin is:
jQuery.fn.myPlugin = function(){...}
I was thinking of storing it's calculated data in:
jQuery.myPlugin.data = {...}
Is this the acceptable way of going about it?
I think storing it there is acceptable (or jQuery.fn.myPlugin.data for that matter)...or instead use your own ID in $.cache which is for storage but uses integer IDs for jQuery events and data, so you won't have any conflict, for example:
$.cache["myPlugin"] = myData;
//and to get:
var dataToUse = $.cache["myPlugin"];
The main reason I'd take this route is it eliminates the potential jQuery.something naming conflicts that could arise with future versions.
How do you fix a names mismatch problem, if the client-side names are keywords or reserved words in the server-side language you are using?
The DOJO JavaScript toolkit has a QueryReadStore class that you can subclass to submit REST patterned queries to the server. I'm using this in conjunction w/ the FilteringSelect Dijit.
I can subclass the QueryReadStore and specify the parameters and arguments getting passed to the server. But somewhere along the way, a "start" and "count" parameter are being passed from the client to the server. I went into the API and discovered that the QueryReadStore.js is sending those parameter names.
I'm using Fiddler to confirm what's actually being sent and brought back. The server response is telling me I have a parameter names mismatch, because of the "start" and "count" parameters. The problem is, I can't use "start" and "count" in PL/SQL.
Workaround or correct implementation advice would be appreciated...thx.
//I tried putting the code snippet in here, but since it's largely HTML, that didn't work so well.
While it feels like the wrong thing to do, because I'm hacking at a well tested, nicely written JavaScript toolkit, this is how I fixed the problem:
I went into the DOJOX QueryReadStore.js and replaced the "start" and "count" references with acceptable (to the server-side language) parameter names.
I would have like to handled the issue via my PL/SQL (but I don't know how to get around reserved words) or client-side code (subclassing did not do the trick)...without getting into the internals of the library. But it works, and I can move on.
As opposed to removing it from the API, as you mentioned, you can actually create a subclass with your own fetch, and remove start/count parameters (theoretically). Have a look at this URL for guidance:
http://www.sitepen.com/blog/2008/06/25/web-service-data-store/
Start and count are actually very useful because they allow you to pass params for the query that you can use to filter massive data sets, and it helps to manage client-side paging. I would try to subclass instead, intercept, and remove.
Is your pl/sql program accessed via a URL and mod_plsql? If so, then you can use "flexible parameter passing" and the variables get assigned to an array of name/value pairs.
Define your package spec like this...
create or replace package pkg_name
TYPE plsqltable
IS
TABLE OF VARCHAR2 (32000)
INDEX BY BINARY_INTEGER;
empty plsqltable;
PROCEDURE api (name_array IN plsqltable DEFAULT empty ,
value_array IN plsqltable DEFAULT empty
);
END pkg_name;
Then the body:
CREATE OR REPLACE PACKAGE BODY pkg_name AS
l_count_value number;
l_start_value number;
PROCEDURE proc_name (name_array IN plsqltable DEFAULT empty,
value_array IN plsqltable DEFAULT empty) is
------------
FUNCTION get_value (p_name IN VARCHAR) RETURN VARCHAR2 IS
BEGIN
FOR i IN 1..name_array.COUNT LOOP
IF UPPER(name_array(i)) = UPPER(p_name) THEN
RETURN value_array(i);
END IF;
END LOOP;
RETURN NULL;
END get_value;
----------------------
begin
l_count_value := get_value('count');
l_start_value := get_value('start');
end api;
end pkg_name;
Then you can call pkg_name.api using
http://server/dad/!pkg_name.api?start=3&count=3