Read-only attributes in ember-data 1.0.0-beta

In ember-data-RC there was a hack to make attributes read-only. Is this behaviour supported by default in ember-data-beta? If not how can I do the same or apply the following code that i was using before there too?

# Store
addAttributes: (data, record) ->
    record.eachAttribute ((name, attribute) ->
      @_addAttribute data, record, name, attribute.type  unless attribute.options.readOnly
    ), this

# Model
App.Post = DS.Model.extend(
    viewsCount:       DS.attr 'number', readOnly: true
)

@seif , you have to define custom serializer and override the serializeAttribute method. This is what I have in my app:

App.ApplicationSerializer = DS.RESTSerializer.extend({
  serializeAttribute: function(record, json, key, attribute) {
    if (attribute.options && attribute.options.readOnly) {
      return
    } else {
      this._super(record, json, key, attribute);
    }
  }      
});
2 Likes

@madadam Thanks, but I realised that in ember-data now only send attributes that you pass. It doesn’t send all attributes from the model like it used to do before.

@madadam What exactly do you mean by that? If you don’t declare properties in the model JS file, they wont’ get sent back and forth, but you will still have access to un-named properties as getters?

Could you elaborate on that a bit? I’ve just run into an issue where I can’t get ember-data to send my belongsTo id attributes back to the server and I’m wondering if there’s something I’m missing.

@lookingsideways At first i thought ember only sent parameters changed, but i don’t know maybe i was wrong or later ember-beta versions ditched that. Anyway, I’m not doing anything from ember’s side to handle what to send and what not to send. I’m depending on rails 4 permitted attributes to filter attributes like followers, followings count, …etc. to do that.

I’m currently using an implementation for read-only attributes that is similar:

  • Mark any attribute as read-only via DS.attr('someTransform', { readOnly: true }).
  • override serializer.serializeAttribute to not serialize any attributes marked as readOnly.

There is still a lingering problem that I see two ways of dealing with, and I’m not sure which way is the best. There is nothing preventing you from changing the those attributes marked as readOnly. So not only are they truly not read only, they also will cause the record to become dirty if they are changed. In that sense, readOnly means that the serializer will not serialize those attributes when it communicates with the persistence layer, and the adapter will blindly override any value those attributes will have with the value that comes back from the latest persistence layer call.

I’m currently working with this by overriding didSetProperty in model/states.js to only send the ‘becomeDirty’ event if the attribute that has changed is not read-only. The other way I see this being dealt with is by simply throwing an error or not allowing the attribute to be changed at all.

Overriding didSetProperty seemed easier because it means that if something in the app indeed does cause a readOnly attribute to change, the model will not know or care, and the value will be restored to whatever the persistence layer says it is the next time that model comes back from it or when the client calls rollback on it (careful coding and UI design can ensure that a typical user never changes the readOnly property, making this problem moot for the vast majority of use cases within the app). This way the adapter or the store doesn’t need to have a special privilege to update a readOnly attribute without causing an error, which I imagine requires more logic than adding && !meta.options.readOnly to an if statement inside didSetProperty.

Just my 2 cents.