Created
October 21, 2015 23:15
-
-
Save kurko/702c7f3b324682c04e7e to your computer and use it in GitHub Desktop.
JSONAPI Deserialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module JsonApi | |
class Relationships | |
def initialize(record, payload, id_attr: :uuid) | |
@record = record | |
@payload = payload | |
@id_attr = id_attr | |
end | |
def set_relationships(*relations_names) | |
relations_names = Array.wrap(relations_names) | |
return unless valid_relationship_payload? | |
relations_names.each do |name| | |
if relationship_exists?(name) | |
record.public_send(relationship_attr(name), get_relation_id(name)) | |
end | |
end | |
end | |
private | |
attr_reader :record, :payload, :id_attr | |
def payload_relationships | |
payload[:data] && payload[:data][:relationships] | |
end | |
def get_relation_id(name) | |
if payload_relationships[name] | |
# passed_id is usually a uuid. Below, we get this e.g UUID and get the | |
# actual record. Then we keep the ID. | |
passed_id = payload_relationships[name][:data][:id] | |
klass = resource_class(name) | |
klass.public_send("find_by_#{id_attr}", passed_id).id | |
end | |
end | |
# resource_name is a symbol such as :category | |
def resource_class(resource_name) | |
resource_name.to_s.classify.constantize | |
rescue NameError # some classes might not exist | |
nil | |
end | |
def valid_relationship_payload? | |
payload_relationships.present? | |
end | |
def relationship_exists?(name) | |
record.respond_to?(relationship_attr(name)) | |
end | |
def relationship_attr(name) | |
"#{name}_id=" | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rails_helper" | |
RSpec.describe JsonApi::Relationships do | |
let(:now) { "#{Time.now.utc.iso8601}" } | |
let(:record) { build(:entry, category: nil) } | |
let(:category) { create(:category) } | |
let(:payload) do | |
{ | |
data: { | |
id: "uuid", | |
type: "entries", | |
attributes: { | |
name: "Supermarket", | |
amount: 12.34, | |
currency: "R$", | |
notes: "This is a note\nSecond line!", | |
date: now, | |
entry_type: "expense" | |
}, | |
relationships: { | |
category: { | |
data: { | |
type: "categories", | |
id: category.uuid | |
} | |
} | |
} | |
} | |
} | |
end | |
subject { described_class.new(record, payload) } | |
describe "#set_relationships" do | |
it "set the relationships" do | |
expect(record.category).to eq(nil) | |
subject.set_relationships(:category, :non_existent) | |
expect(record.category).to eq(category) | |
end | |
context "no relationships" do | |
before do | |
payload[:data].delete(:relationships) | |
end | |
it "set the relationships" do | |
expect(record.category).to eq(nil) | |
subject.set_relationships(:category, :non_existent) | |
expect(record.category).to eq(nil) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment