Skip to content

Commit

Permalink
Merge pull request #11 from gadabout/feature/remove-related
Browse files Browse the repository at this point in the history
Remove related resources for has-many relationship
  • Loading branch information
Chris Dosé committed Oct 13, 2016
2 parents 74fd6a9 + f95fa30 commit 5edd78e
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 64 deletions.
1 change: 1 addition & 0 deletions lib/lurch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

require "lurch/uri"
require "lurch/query_builder"
require "lurch/payload_builder"
require "lurch/query"
require "lurch/changeset"
require "lurch/client"
Expand Down
14 changes: 1 addition & 13 deletions lib/lurch/changeset.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Lurch
class Changeset
attr_reader :type, :id, :attributes
attr_reader :id, :type, :attributes

def initialize(type, attributes = {})
is_resource = type.is_a?(Resource)
Expand All @@ -9,18 +9,6 @@ def initialize(type, attributes = {})
@attributes = attributes
end

def payload
{
"id" => id,
"type" => type,
"data" => {
"attributes" => attributes.each_with_object({}) do |(key, value), hash|
hash[Inflecto.dasherize(key.to_s)] = value
end
}
}.reject { |_, v| v.nil? }
end

def inspect
attrs = ["id: #{id.inspect}"]
attrs = attrs.concat attributes.map { |name, value| "#{name}: #{value.inspect}" }
Expand Down
8 changes: 6 additions & 2 deletions lib/lurch/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ def patch(path, payload)
catch_errors(client.patch(path, payload)).body
end

def delete(path)
catch_errors(client.delete(path)).body
def delete(path, payload = nil)
resp = client.delete do |req|
req.url path
req.body = payload unless payload.nil?
end
catch_errors(resp).body
end

private
Expand Down
41 changes: 41 additions & 0 deletions lib/lurch/payload_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Lurch
class PayloadBuilder
def initialize(input, resource_identifier_only = false)
@input = input
@resource_identifier_only = resource_identifier_only
end

def build
{ "data" => data }
end

private

def data
if @input.is_a?(Enumerable)
@input.map { |resource| resource_object_for(resource) }
else
resource_object_for(@input)
end
end

def resource_object_for(resource)
{
"id" => resource.id,
"type" => Inflecto.dasherize(resource.type.to_s),
"attributes" => attributes_for(resource)
}.reject { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
end

def attributes_for(resource)
return {} if @resource_identifier_only
dasherize_keys(resource.attributes)
end

def dasherize_keys(attributes)
attributes.each_with_object({}) do |(key, value), hash|
hash[Inflecto.dasherize(key.to_s)] = value
end
end
end
end
18 changes: 12 additions & 6 deletions lib/lurch/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ def save(changeset)
return insert(changeset) if changeset.id.nil?
url = URI.resource_uri(changeset.type, changeset.id)

document = client.patch(url, changeset.payload)
document = client.patch(url, PayloadBuilder.new(changeset).build)
process_document(document)
end

def insert(changeset)
return save(changeset) unless changeset.id.nil?
url = URI.resources_uri(changeset.type)

document = client.post(url, changeset.payload)
document = client.post(url, PayloadBuilder.new(changeset).build)
process_document(document)
end

Expand All @@ -39,15 +39,21 @@ def delete(resource)
true
end

def add_relationship
# add resource(s) to a has many relationship
def add_related
# TODO
end

def delete_relationship
# TODO
# remove resource(s) from a has many relationship
def remove_related(resource, relationship_key, related_resources)
url = URI.relationship_uri(resource.type, resource.id, relationship_key)
payload = PayloadBuilder.new(related_resources, true).build
client.delete(url, payload)
true
end

def update_relationship
# replace resource(s) for a has many or has one relationship
def update_related
# TODO
end

Expand Down
5 changes: 5 additions & 0 deletions lib/lurch/uri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ def self.resource_uri(type, id, query = "")
uri.query = query unless query.empty?
uri.to_s
end

def self.relationship_uri(type, id, relationship_key)
uri = ::URI.parse("#{Inflecto.dasherize(type.to_s)}/#{id}/relationships/#{Inflecto.dasherize(relationship_key.to_s)}")
uri.to_s
end
end
end
2 changes: 1 addition & 1 deletion lib/lurch/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Lurch
VERSION = "0.0.10".freeze
VERSION = "0.0.11".freeze
end
37 changes: 1 addition & 36 deletions spec/lurch/changeset_spec.rb
Original file line number Diff line number Diff line change
@@ -1,40 +1,5 @@
RSpec.describe Lurch::Changeset do
let(:type) { :people }
let(:type_or_resource) { type }
let(:changes) { {} }
let(:changeset) { Lurch::Changeset.new(type_or_resource, changes) }

describe "#payload" do
subject(:payload) { changeset.payload }

context "when given a type" do
it { is_expected.to include("type" => type) }
it { is_expected.not_to include("id") }
end

context "when given a resource" do
let(:type_or_resource) { Lurch::Resource.new(nil, type, 1) }

it { is_expected.to include("type" => type) }
it { is_expected.to include("id" => 1) }
end

context "when given some changes" do
let(:name) { "Mr. Example" }
let(:changes) { { name: name } }

it { is_expected.to include("data" => { "attributes" => { "name" => name } }) }
end

context "when given changes with underscored keys" do
let(:email_address) { "[email protected]" }
let(:changes) { { email_address: email_address } }

it "dasherizes the keys" do
expect(payload).to include("data" => { "attributes" => { "email-address" => email_address } })
end
end
end
let(:changeset) { Lurch::Changeset.new(:people) }

describe "#inspect" do
subject { changeset.inspect }
Expand Down
23 changes: 17 additions & 6 deletions spec/lurch/store_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

before do
stub_request(:patch, "example.com/people/1")
.with(body: JSON.dump(changeset.payload), headers: json_api_headers)
.with(body: JSON.dump(Lurch::PayloadBuilder.new(changeset).build), headers: json_api_headers)
.to_return(File.new(File.expand_path("../../responses/save.txt", __FILE__)))
end

Expand All @@ -58,7 +58,7 @@

before do
stub_request(:post, "example.com/people")
.with(body: JSON.dump(changeset.payload), headers: json_api_headers)
.with(body: JSON.dump(Lurch::PayloadBuilder.new(changeset).build), headers: json_api_headers)
.to_return(File.new(File.expand_path("../../responses/insert.txt", __FILE__)))
end

Expand All @@ -82,15 +82,26 @@
end
end

describe "#add_relationship" do
describe "#add_related" do
pending "TODO"
end

describe "#delete_relationship" do
pending "TODO"
describe "#remove_related" do
let(:resource) { Lurch::Resource.new(store, :person, 1) }
let(:related_resources) { [Lurch::Resource.new(store, :language, 1)] }

before do
stub_request(:delete, "example.com/people/1/relationships/favorite-languages")
.with(body: JSON.dump(Lurch::PayloadBuilder.new(related_resources, true).build), headers: json_api_headers)
.to_return(File.new(File.expand_path("../../responses/delete.txt", __FILE__)))
end

it "sends a DELETE request to the server for the given relationship" do
expect(store.remove_related(resource, :favorite_languages, related_resources)).to be true
end
end

describe "#update_relationship" do
describe "#update_related" do
pending "TODO"
end
end

0 comments on commit 5edd78e

Please sign in to comment.