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

Override for relationship with super is not working. Also setter for a relationship is working anomalously #405

Open
isfando opened this issue Jan 13, 2023 · 2 comments

Comments

@isfando
Copy link

isfando commented Jan 13, 2023

class BillingAccount < JsonApiClient::Resource

#internal class starts
  class Create < JsonApiClient::Resource

    property :billing_account_type, type: :string
    has_many :products, class_name: 'foo'

    def product_offerings=(items)
      #item._model is of type 'foo'
      self.products = items.map { |item| item._model }
    end

    def attributes_for_serialization
      relationship_keys = self.class.associations.collect(&:attr_name).map(&:to_s)
      super.reject { |k, v| v.nil? || relationship_keys.include?(k) }
    end

    def self.key_formatter
      JsonApiClient::UnderscoredKeyFormatter
    end

    def self.path(*)
      Bssapi::V1::BillingAccount.path
    end

    def meta
      {
        channel: 'abc'
      }
    end


    def as_json_api
      super.tap do |data|
        data['type'] = BillingAccount.type.dasherize
      end
    end

    def save(sync: true)
      saved = super()
      if saved && async_response?(last_result_set) && sync
        when_async_request_done(last_result_set) do |request|
          if request.done?
            self.id = billing_account_id
            true
          elsif request.failed?
            errors.add(:base, request.reasons || "unknown error")
            false
          end
        end
      else
        saved
      end
    end
  end
# internal class ends here


  has_many :products, class_name: 'foo'
  has_one :billing_account_type, class_name: 'bar'

  def meta
    {
      channel: 'abc'
    }
  end

  def product_offerings=(items)
    #item._model is of type 'foo'
    self.products = items.map { |item| item._model } 
  end

  def valid?
    if new_record?
      create = resource_for_create
      if create.valid?
        true
      else
        errors.merge!(create.errors)
        false
      end
    else
      super
    end
  end

  def save(sync: true)
    if new_record?
      create = resource_for_create
      if create.save(sync: sync)
        self.id = create.id
        true
      else
        errors.merge!(create.errors)
        false
      end
    else
      super()
    end
  end

  private

  def resource_for_create
    Create.new(
      attributes.merge(
        billing_account_type: billing_account_type # This is a relationship in GET and string in POST
      )
    )
  end
end

###########################################################################################################################
###########################################################################################################################
Reason for internal class:
Use a different class for POST to avail asynchronus creation etc.

Problem during Creation of new resource:
BillingAccount.new(
billing_account_type: "test",
product_offerings: items,
).save

The products relation will be absent from resulting pay load to api.

POST http://localhost:7777/api/v1/billing-accounts with body 
'{"data":{"type":"billing-accounts","attributes":{"billing_account_type":"1111"}},"meta":{"channel":"abc"}}'

If i remove the method #product_offerings= from the outer class (BillingAccount) then it works fine

POST http://localhost:7777/api/v1/billing-accounts with body 
'{"data":{"type":"billing-accounts","relationships":{"products":{"data":[{"type":"foo","id":"33333"}]}},"attributes":{"billing_account_type":"6002"}},"meta":{"channel":"abc"}}'

The method in the outer class BillingAccount is required for PATCH as BillingAccount::Create is only used for POST.
What can i do in such situation.

I have also used the following method to override the products relationship in BillingAccount::Create but it does not help either

class Create < JsonApiClient::Resource
  property :billing_account_type, type: :string
  has_many :products, class_name: 'foo'
  
  def products=(items)
    #item._model is of type 'foo'
    super(items.map { |item| item._model }) 
  end
end
@isfando
Copy link
Author

isfando commented Jan 13, 2023

@sebasjimenez10 i read one of your posts and that helped somehow with POST and using super in relationship override method. But it does not work with PATCH

#390

@sebasjimenez10
Copy link
Contributor

@isfando to clarify, when you tried doing BillingAccount.new.tap do |...| it still didn't serialize the object as expected?

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

2 participants