Description
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