Detect if a newly created model has changed attributes - ember.js

Say you have a /new route, and the router creates a new instance of your model.
Your model's properties are bound to some input fields on the page.
I want to be able to detect if the new model has changed since it's instantiation.
model.get('hasDirtyAttributes') unfortunately reports true for new instances, because it has not been saved yet.
I thought to try model.get('hasDirtyAttributes') && model.get('dirtyType') === 'updated' but dirtyType is still created until you do the first save.

You can call model.changedAttributes() and see if it's empty (docs), but you can't observe it. Ex -
Object.keys(this.get('model').changedAttributes()).length > 0
I am not aware of a general attribute that you could observe in this case. You would have to observe a specified list of attributes.
or you could override set on your model and have it set a value -
set: (key, value) ->
#attributeHasChanged = true
#_super(key, value)

You could create a computed property on that model which would depend on any declared attribute and would return true if any of attributes differs from it's initial value, otherways false.
For better performance you could only compute this property if model.get('isNew') === true.

Related

Getting False value for a key in self.data even when it is not present in the request

I have 2 radio buttons in the UI, one for setting a variable (ng-model) say selected as true (ng-value=true) and other one for setting it as false (ng-value=false). Now, when none of them is selected it results in the variable selected being absent from the outgoing request (as expected).
However, when that is dealt with Django Forms, the self.data dictionary in the clean() method gives False on accessing self.data.get('selected') / self.data['selected'] why is that so? Shouldn't it be None or at least give a key-error when it was not even present in the actual request?
Note that the variable 'selected' is actually a field in a Django Model with default=False, is that thing responsible for this behaviour? How can I circumvent this situation considering that altering the Django Model field isn't an option?
So I dealt with it the other day by checking for the selected key in the raw request.body. Now, since its a string, I had to parse it to a dict and then access the mentioned key using :
json.loads(request.body).get('selected')
In this way, if selected is not present at all when none of the radio buttons are selected, I get None. Similarly, if the radio button for ng-value=true is selected then I get True and vice-versa.

Checking for model update in Computed Property

I'm creating a component for rendering tables. The component is actually a set of nested components and receives a route model and config object, at the top level, then is processed within the component and passed on / iterated over in the next etc.
The final child component receives a model (representing just one row in the table) along with field name that defines which filed to display from the model.
All of this works perfectly and UI updates are bound to the model. The problem that I have is that model updates are not being pushed to the UI. Within my child component I bind to the UI element using the following:
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.property()
tdValUpdated : function(){
this.get('data').set(this.get('details').get('field'),this.get('val'));
}.property('tdVal'),
As you can see there is no computed property literal set for tdVal, which is why model updates are not being pushed to the UI. If I were to give this a literal value such as 'data.status' then status updates to the model are pushed to the UI.
What literal value can I use to compute on any attribute change in the model?
I've tried 'data.isUpdated', 'data.isSaving' etc. I can't use 'data.[]' as the single model, not an array of model.
OK, after much trial and error I think I've found a workaround for this. It's messy and I'm not very happy with it:
//as previous I render the the appropriate value from the model as defined
//by the passed in config object
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.property(),
//then detect UI changes and push to model if required
tdValUpdated : function(){
this.get('data').set(this.get('details').get('field'),this.get('val'));
}.property('tdVal'),
//Then I observe any changes to model isSaving and directly set tdVal with
//the value of the field for the current td
generalUpdateCatch: function() {
this.set('tdVal',this.get('data').get(this.get('details').get('field')));
}.observes('data.isSaving'),
I did try the following instead:
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.observes('data.isSaving'),
But get the error: 'Uncaught TypeError: unsupported content', no idea why? If anybody has a better solution then please post as I very much dislike these workarounds.

Sitecore return field "Fields" with zero count in SocialProfiles

Sitecore return field "Fields" with zero count in SocialProfiles, but this fields in social network really exist. How I can get need fields?
var socialProfileManager = new SocialProfileManager();
var twitterNetwork = allProfiles.FirstOrDefault(x => x.NetworkName == "Twitter");
if (twitterNetwork.Fields.Count != 0) //Dicitionary "Fields" is empty here
{
...
}
I had a similar situation where I was trying to retrieve the fields and dealing with the zero field count. Take a look at this post: https://stackoverflow.com/a/30519345/4897782
Specifically, my issue was resolved when I passed false as the second parameter in the base login method. The default true parameter attempts to update the profile asynchronously, making it unavailable during my attempts to do what you are doing.
To be able to override the parameter though, I had to deviate from the standard out of the box login controls and implement my own version of what happens when you click login. It's pretty simple though. Take a look at the post and hopefully that resolves your issue.

Django : Know if property is the default value

How can you know if a value is the default value for a Model's property.
For example
class Alias(models.Model) :
image = models.ImageField(upload_to='alias', default='/media/alias-default.png')
a = Alias.get("123")
# this doesn't work
if a.image == a.image.default :
pass
# nor this
if a.image == Alias.image.default :
pass
I tried digging in the docs, but didn't see anything.
You can't get it from the property itself, you have to go via the model options under model._meta.
a._meta.get_field_by_name('image')[0].get_default()
The default in Django is not the same as SQL default - it's there merely for admin to auto-fill the form field on new object creation.
If you want to compare something to value defined as default you have to define it somewhere else (i.e. in settings.py). Like:
class MyModel(models.Model):
...
my_field = models.IntegerField(default=settings.INT_DEFAULT)
The default value is stored in MyModel._meta._fields()[field_creation_index].default but be aware that this is digging in internals.

Django : Setting a generic (content_type) field with a real object sets it to None

Update 3 (Read This First) :
Yes, this was caused by the object "profile" not having been saved. For those getting the same symptoms, the moral is "If a ForeignKey field seems to be getting set to None when you assign a real object to it, it's probably because that other objects hasn't been saved."
Even if you are 100% sure that it was saved, check again ;-)
Hi,
I'm using content_type / generic foreign keys in a class in Django.
The line to create an instance of the class is roughly this :
tag = SecurityTag(name='name',agent=an_agent,resource=a_resource,interface=an_interface)
Where both agent and resource are content_type fields.
Most of the time, this works as I expect and creates the appropriate object. But I have one specific case where I call this line to create a SecurityTag but the value of the agent field seems to end up as None.
Now, in this particular case, I test, in the preceding line, that the value of an_agent does contain an existing, saved Django.model object of an agent type. And it does.
Nevertheless, the resulting SecurityTag record comes out with None for this field.
I'm quite baffled by this. I'm guessing that somewhere along the line, something is failing in the ORM's attempt to extract the id of the object in an_agent, but there's no error message nor exception being raised. I've checked that the an_agent object is saved and has a value in its id field.
Anyone seen something like this? Or have any ideas?
====
Update : 10 days later exactly the same bug has come to bite me again in a new context :
Here's some code which describes the "security tag" object, which is basically a mapping between
a) some kind of permission-role (known as "agent" in our system) which is a generic content_type,
b) a resource, which is also a generic content_type, (and in the current problem is being given a Pinax "Profile"),
and c) an "interface" (which is basically a type of access ... eg. "Viewable" or "Editable" that is just a string)
class SecurityTag(models.Model) :
name = models.CharField(max_length='50')
agent_content_type = models.ForeignKey(ContentType,related_name='security_tag_agent')
agent_object_id = models.PositiveIntegerField()
agent = generic.GenericForeignKey('agent_content_type', 'agent_object_id')
interface = models.CharField(max_length='50')
resource_content_type = models.ForeignKey(ContentType,related_name='security_tag_resource')
resource_object_id = models.PositiveIntegerField()
resource = generic.GenericForeignKey('resource_content_type', 'resource_object_id')
At a particular moment later, I do this :
print "before %s, %s" % (self.resource,self.agent)
t = SecurityTag(name=self.tag_name,agent=self.agent,resource=self.resource,interface=self.interface_id)
print "after %s, %s, %s, %s" % (t.resource,t.resource_content_type,type(t.resource),t.resource_object_id)
The result of which is that before, the "resource" variable does reference a Profile, but after ...
before phil, TgGroup object
after None, profile, <type 'NoneType'>, None
In other words, while the value of t.resource_content_type has been set to "profile", everything else is None. In my previous encounter with this problem, I "solved" it by reloading the thing I was trying to assign to the generic type. I'm starting to wonder if this is some kind of ORM cache issue ... is the variable "self.resource" holding some kind proxy object rather than the real thing?
One possibility is that the profile hasn't been saved. However, this code is being called as the result of an after_save signal for profile. (It's setting up default permissions), so could it be that the profile save hasn't been committed or something?
Update 2 : following Matthew's suggestion below, I added
print self.resource._get_pk_value() and self.resource.id
which has blown up saying Profile doesn't have _get_pk_value()
So here's what I noticed passing through the Django code: when you create a new instance of a model object via a constructor, a pre-init function called (via signals) for any generic object references.
Rather than directly storing the object you pass in, it stores the type and the primary key.
If your object is persisted and has an ID, this works fine, because when you get the field at a later date, it retrieves it from the database.
However -- if your object doesn't have an ID, the fetch code returns nothing, and the getter returns None!
You can see the code in django.contrib.contenttypes.generic.GenericForeignKey, in the instance_pre_init and __get__ functions.
This doesn't really answer my question or satisfy my curiosity but it does seem to work if I pull the an_agent object out of the database immediately before trying to use it in the SecurityTag constructor.
Previously I was passing a copy that had been made earlier with get_or_create. Did this old instance somehow go out of date or scope?