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

Relationships with ActiveModelSerializers::Model #1961

Closed
andrewferk opened this issue Oct 27, 2016 · 13 comments
Closed

Relationships with ActiveModelSerializers::Model #1961

andrewferk opened this issue Oct 27, 2016 · 13 comments

Comments

@andrewferk
Copy link

I'm using version 0.10.2 and attempting to create a relationship (belongs_to) with ActiveModelSerializers::Model (and not ActiveRecord::Model). The relationship output keeps returning null.

Thanks!

Model

class User::Registration < ActiveModelSerializers::Model

  attr_reader :user
  attr_accessor :email

  def save
    register_user
  end

  def email=(value)
    # Follow Devise's configuration to check if email is case insensitive
    @email = Devise.case_insensitive_keys.include?(:email) ? value.try(:downcase) : value
  end

  def id
    email
  end

  private

  def register_user
    @user = User.new(email: email)
    @user.provider = 'email'

    @user.send_confirmation_instructions if @user.save
    @user.clean_up_passwords

    @user.persisted?
  end
end

Resource

class User::RegistrationSerializer < ApplicationSerializer
  attributes :email
  belongs_to :user
end

Controller

def create
  @registration = User::Registration.new(email: @request[:email])
  @registration.save
  render json: @registration, status: :created
end

Ouptut

{"data": {"id":"a@b.co","type":"user-registrations","attributes":{"email":"a@b.co"},"relationships":{"user":{"data":null}}}}

I'd expect the relationships output to not be null.

@beauby
Copy link
Contributor

beauby commented Oct 28, 2016

What is the output of @registration.user before the save call?

@andrewferk
Copy link
Author

What is the output of @registration.user before the save call?

It is nil.

It looks like I'm having problems with ActiveModelSerializers::Model as it sets @attributes in the initializers and uses it for serialization. That doesn't work for me because I'm setting the user using @user.

My model has been updated to the following:

class User::Registration < ActiveModelSerializers::Model
  include ActiveModel::Model
  include ActiveModel::Serialization
end

ActiveModel::Serialization sets alias :read_attribute_for_serialization :send.

@beauby
Copy link
Contributor

beauby commented Oct 28, 2016

As far as I can tell, you're not setting the user, so I do not understand why it would be surprising that the user is nil in the serialized document?

@andrewferk
Copy link
Author

It's set in the User::Registration#register_user method.

@beauby
Copy link
Contributor

beauby commented Oct 28, 2016

As far as I can tell it is never called though.

@beauby
Copy link
Contributor

beauby commented Oct 28, 2016

Oops – it is indeed called in the save method.

@beauby
Copy link
Contributor

beauby commented Oct 28, 2016

What is the value of @registration.user after the save call?

@andrewferk
Copy link
Author

It's a User, and it did save successfully. I think the change I did will allow this to work, although I haven't gotten around to checking yet.

@groyoh
Copy link
Member

groyoh commented Oct 28, 2016

I guess this is related to #1953. @andrewferk you are right in #1961 (comment). When @user = ... is set, the @attributes value is not actually changed and @attributes is the value used for serializing the object (ref). That's an issue with the AMS::Model class itself. As mentioned in #1953 I'm not entirely aware of the purpose of AMS::Model and if it's really meant to be used outside AMS. @beauby what's your thoughts about that?

@bf4
Copy link
Member

bf4 commented Nov 2, 2016

@andrewferk This is a known bug in AMS::Model that no one has fixed yet. see #1903 until it is fixed, you can either roll your own poro, using AMS::Model as a reference doc (which is part of its intention), or call attributes[:user] = self.user = User.new(email: email) instead of self.user = User.new(email: email) :(

@bf4
Copy link
Member

bf4 commented Nov 22, 2016

Looks like I've implemented a good chunk of this in #1984

@axsuul
Copy link

axsuul commented Mar 28, 2017

@bf4 Sorry, I did some digging but still not quite sure if this has been fixed or not by your pull request

@bf4
Copy link
Member

bf4 commented Nov 2, 2017

Also see

# At this time, just for organization of intent
class_attribute :association_names
self.association_names = []
def self.associations(*names)
self.association_names |= names.map(&:to_sym)
# Silence redefinition of methods warnings
ActiveModelSerializers.silence_warnings do
attr_accessor(*names)
end
end
def associations
association_names.each_with_object({}) do |association_name, result|
result[association_name] = public_send(association_name).freeze
end.with_indifferent_access.freeze
end
def attributes
super.except(*association_names)
end

@bf4 bf4 closed this as completed Nov 2, 2017
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

5 participants