Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lib/basecrm/services/deals_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ def update(deal)
Deal.new(root[:data])
end

# Upsert a deal
#
# post '/deals/upsert?filter_param=filter_value
#
# Create a new deal or update an existing, based on a value of a filter or a set of filters.
# At least a single filter - query parameter - is required. If no parameters are present, the request will return an error.
# See full docs https://developers.getbase.com/docs/rest/reference/deals
#
# @param filters [Hash] - hash contain filters, one level deep e.g. { name: 'string', 'custom_fields[field]': 'value' }
# @param deal [Deal, Hash] - This object's attributes describe the object to be updated or created
# @return [Deal] The resulting object representing updated or created resource.
def upsert(filters, deal)
validate_upsert_filters!(filters)
validate_type!(deal)

attributes = sanitize(deal)
query_string = URI.encode_www_form(filters)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was trying to find a way on encoding the hash without using Rails only methods (like Object.to_query) or a new gem like Addressable, this seems to do the trick, but other opinions welcome

_, _, root = @client.post("/deals/upsert?#{query_string}", attributes)

Deal.new(root[:data])
end


# Delete a deal
#
Expand All @@ -127,6 +149,11 @@ def validate_type!(deal)
raise TypeError unless deal.is_a?(Deal) || deal.is_a?(Hash)
end

def validate_upsert_filters!(filters)
raise TypeError unless filters.is_a?(Hash)
raise ArgumentError, "at least one filter is required" if filters.empty?
end

def extract_params!(deal, *args)
params = deal.to_h.select{ |k, _| args.include?(k) }
raise ArgumentError, "one of required attributes is missing. Expected: #{args.join(',')}" if params.count != args.length
Expand Down
17 changes: 17 additions & 0 deletions spec/services/deals_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
it { should respond_to :destroy }
it { should respond_to :find }
it { should respond_to :update }
it { should respond_to :upsert }
it { should respond_to :where }

end
Expand Down Expand Up @@ -59,6 +60,22 @@
end
end

describe :upsert do
it 'raises a TypeError if filters is nil' do
expect(client.deals.upsert(nil, { name: 'unique_name' }).to raise_error(TypeError)
end

it 'raises an ArgumentError if filters is empty' do
expect(client.deals.upsert({}, { name: 'unique_name' }).to raise_error(ArgumentError)
end

it 'calls the upsert route with encoded filters' do
filters = { name: 'unique_name', 'custom_fields[external_id]': 'unique-1' }
attributes = filters.merge('custom_fields[category]': 'bags')
expect(client.deals.upsert(filters, attributes)).to be_instance_of BaseCRM::Deal
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests seems to require an Access Token and actually attempt to hit a running API, is that expected?

end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above

end

describe :destroy do
it "returns true on success" do
@deal = create(:deal)
Expand Down