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

Allow serialized ID to be overwritten for belongs-to relationships #2130

Merged
merged 1 commit into from
May 15, 2017
Merged

Allow serialized ID to be overwritten for belongs-to relationships #2130

merged 1 commit into from
May 15, 2017

Conversation

greysteil
Copy link
Contributor

Purpose

If the id attribute for a class isn't taken directly from the object when serializing it, it may be desirable for other classes that serialize a relationship with that class to overwrite the relationship IDs they serialize.

For example, suppose we have:

class Repo < Model
  attributes :id, :github_id, :name
  associations :configs
end

class Config < Model
  attributes :id
  belongs_to :repo
end

class RepoSerializer < ActiveModel::Serializer
  attributes :id, :name

  has_many :update_configs

  def id
    object.github_id
  end
end

class ConfigSerializer < ActiveModel::Serializer
  attributes :id
  belongs_to :repo
end

In the above example, serializing a list of Repos will give the github_id for each one, but serializing a Config will give the id for its parent repo.

Changes

I've updated the belongs_to? path of Relationship#data_for_one to use read_attribute_for_serialization instead of object.send to fetch the serialized foreign key. This allows the serialized relationship ID to be
overwritten using:

class ConfigSerializer < ActiveModel::Serializer
  ...

  def repo_id
    object.repo.github_id
  end
end

Caveats

Ideally AMS would inspect the RepoSerializer when serializing the Config, and realise it can't just output the foreign key. Unfortunately, getting the serialization class for the child repo currently requires loading the record (via evaluating lazy_assocation), and loses the performance benefit of the existing belongs_to? path.

Related GitHub issues

#2125. (Not resolved by this, but the ID issue is at least improved, for no performance cost.)

Additional helpful information

@mention-bot
Copy link

@greysteil, thanks for your PR! By analyzing the history of the files in this pull request, we identified @bf4, @beauby and @bolshakov to be potential reviewers.

Copy link
Member

@bf4 bf4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Can you add an entry to the changelog?

If the `id` attribute for a class isn't taken directly from the object when
serializing it, it may be desirible for other classes that serialize a
relationship with that class to overwrite the relationship IDs they serialize.

For example, suppose we have:

```(ruby)
class Repo < Model
  attributes :id, :github_id, :name
  associations :configs
end

class Config < Model
  attributes :id
  belongs_to :repo
end

class RepoSerializer < ActiveModel::Serializer
  attributes :id, :name

  has_many :update_configs

  def id
    object.github_id
  end
end

class ConfigSerializer < ActiveModel::Serializer
  attributes :id
  belongs_to :repo
end
```

In the above example, serializing a list of `Repo`s will give the `github_id`
for each one, but serializing a `Config` will give the `id` for its parent repo.

Ideally AMS would inspect the `RepoSerializer` when serializing the `Config`,
and realise it can't just output the foreign key. Unfortunately, getting the
serialization class for the child repo currently requires loading the record
(via evaluating `lazy_assocation`), and loses the performance benefit of the
existing `belongs_to?` path. Instead, I've opted to use
`read_attribute_for_serialization` instead of `object.send` to fetch the
serialized foreign key. This allows the serialized relationship ID to be
overwritten using

```(ruby)
class ConfigSerializer < ActiveModel::Serializer
  ...

  def repo_id
    object.repo.github_id
  end
end
```
@greysteil
Copy link
Contributor Author

@bf4 - done.

@bf4 bf4 merged commit a5ab62f into rails-api:0-10-stable May 15, 2017
@bf4
Copy link
Member

bf4 commented May 15, 2017

@greysteil Thanks!

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

Successfully merging this pull request may close these issues.

3 participants