Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

belongsTo needs to be redefined. #3696

Closed
arenoir opened this issue Aug 24, 2015 · 14 comments
Closed

belongsTo needs to be redefined. #3696

arenoir opened this issue Aug 24, 2015 · 14 comments

Comments

@arenoir
Copy link
Contributor

arenoir commented Aug 24, 2015

Since ember data moved to using json api as the internal data format I believe we lost the functionality of a belongs to relationship. Instead I would argue belongsTo is now a hasOne relationship. What happened to the foreign_key and why is it not considered a attribute?

@wecc
Copy link
Contributor

wecc commented Aug 24, 2015

Would you be able to explain a bit more what the issue is now compared to before? foreign_key still works with the ActiveModelSerializer, no?

@arenoir
Copy link
Contributor Author

arenoir commented Aug 24, 2015

Well the biggest one is not being able to look up the foreign_key or rollback changes.

@arenoir
Copy link
Contributor Author

arenoir commented Aug 24, 2015

With a belongsTo relationship the relationship is directly tied to the model. Unlike hasMany or hasOne where changing the relationship has no effect to the parent.

@wecc
Copy link
Contributor

wecc commented Aug 24, 2015

The old internal format for a record with a belongsTo relationship was something like:

{
  "id": 1,
  "author": 2
}

The new one uses JSON API and the same representation as above now looks like:

{
  "data": {
    "id": "1",
    "type": "post",
    "relationships": {
      "author": {
        "data": {
          "id": "2",
          "type": "user"
        }
      }
    }
  }
}

How does this change how belongsTo relationships work?

I'm just trying to understand the issue here, sorry if I'm missing something.

@arenoir
Copy link
Contributor Author

arenoir commented Aug 24, 2015

Yes but moving the foreign_key out of the models attributes changes the definition from a belongsTo relationship to a hasOne.

In previous versions of ember data rolling back a belongsTo relationship was straight forward as was filtering records by foreign_key. It just feels like Ember Data is blurring the line between hasMany, hasOne and belongsTo.

Fore example using the new format you could have a "belongsTo" relationship without a foreign_key by using just a link and no data hash.

data": [{
    "type": "posts",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "related": "http://example.com/author?post_id=1&limit=1"
        },
      },

@arenoir
Copy link
Contributor Author

arenoir commented Sep 9, 2015

@wecc Issue #2705 also demonstrates how the belongsTo relationship behaves like a hasOne. The fact that we have to load the relationship to get it's id describes a hasOne relationship.

@fivetanley
Copy link
Member

It might be good for us to list the differences between has_one and belongs_to. They feel like the same thing to me but I don't know too much about hasOne.

@bmac
Copy link
Member

bmac commented Sep 10, 2015

Hi @arenoir.

I think this tread has some confusion about the definition of belongsTo and hasOne. As a starting point would you mind sharing you definition of a belongsTo and a hasOne relationship?

My understanding of this thread is that you are thinking of these terms in the mindset of a relational database. Where:

  • a belongsTo relationship represents a parent row with a foreign key to a child record.
  • a hasOne relationship is the opposite, where a child row has a relationship with a parent row and the foreign key describing the relationship lives on the parent row.

The hasMany and belongsTo in Ember Data are methods used to describe relationships in a REST interface (and more specifically JSON API). As a result, they do not necessarily map one-to-one to a relational database. From Ember Data's perspective, it does not care where or how a relationship is stored only that the relationship exists between 2 models (I believe this also statement applies to JSON API). In some cases, a serializer may care where and how a relationships is store but this is because they are more tightly coupled to a specific backend.

As for the inability to rollback changes on belongsTo relationships or access the id with out fetching the full record. I agree that these are 2 big pain points in Ember Data today. However, I believe these features can be added without requiring Ember Data to make a distinction between hasOne and belongsTo relationships.

@arenoir
Copy link
Contributor Author

arenoir commented Sep 11, 2015

@bmac,

You defined the difference between belongsTo and hasOne perfectly. It is all about the foreign key.

The problem with the current implementation is that if the payload has a foreign key ED creates the association and throws it out.

If we say that Ember data makes no distinction between hasOne and belongsTo then we will never be able to fetch the id without loading the association.

@pangratz
Copy link
Member

If we say that Ember data makes no distinction between hasOne and belongsTo then we will never be able to fetch the id without loading the association.

As already mentioned in #2705 and other issues, this will be possible once the implementation for RFC#57 is merged, which currently tracked at #3303. I will have time again starting in October to finalize this PR. Soon soon 😉 ...

@arenoir
Copy link
Contributor Author

arenoir commented Sep 11, 2015

@pangratz,

Given the following payload "hasOne" I don't see how it would be possible to retrieve the relationships id without loading the record.

data": [{
    "type": "user",
    "id": "1",
    "attributes": {
      "name": "Mike"
    },
    "relationships": {
      "passport": {
        "links": {
          "related": "http://example.com/passport?user_id=1&limit=1"
        },
      }

vs a belongsTo relationship.

data": [{
    "type": "user",
    "id": "1",
    "attributes": {
      "name": "Mike"
    },
    "relationships": {
      "passport": {
        "data": { "type": "passport", "id": "10" }
      }
    }
}

@pangratz
Copy link
Member

@arenoir It seems that I misunderstood your use case then. What I meant was your second sample above: the passport_id is already available locally, but there is currently no (public API) way to get the id of that relationship, without triggering a fetch the passport record.

In your first payload above, I also don't see another way of getting the id of the related passport relationship, without fetching the link http://example.com/passport?user_id=1&limit=1.


With the references API it will be possible to get the id of the passport, without triggering a fetch: user.belongsTo('passport').id() === '10'. It will also be possible to get the link.

@arenoir
Copy link
Contributor Author

arenoir commented Sep 11, 2015

@pangratz,

This is why I think there should be a difference between hasOne and belongsTo.

Since ED 1.13.0 belongsTo acts more like hasOne.

The behaviors that I look for in a belongs to relationship.

  1. being able to access the foreign key
  2. changing the relationship/foreign_key marks the record as dirty. (not dirty relationships but dirty record)

I have implemented the rollback and marking the record dirty. However because there is no difference between hasOne and belongsTo changing a hasOne relationship IMO incorrectly marks the parent dirty.

In my application I have to find a work around to getting the foreign_key without loading the record. Right now the only solution is to do it in the serializer and copy the key to another attribute.

export default ApplicationSerializer.extend({
   normalize: function(typeClass, hash, prop) {
     var foreignKey = hash['passportId'];
     if (foreignKey) {
       hash['_passportId'] = foreignKey;
     }
     return this._super(typeClass, hash, prop);
  }
});

@wecc
Copy link
Contributor

wecc commented Oct 22, 2016

Related: emberjs/rfcs#21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants