-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #479 from intercom/AP/customer-search-core
Add support for Customer Search API
- Loading branch information
Showing
9 changed files
with
218 additions
and
4 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,7 +97,7 @@ intercom.users.find_all(type: 'users', page: 1, per_page: 10, created_since: 2, | |
# Paginate through your list of users choosing how many to return per page (default and max is 50 per page) | ||
intercom.users.find_all(type: 'users', page: 1, per_page: 10, order: :asc).to_a.each_with_index {|usr, i| puts "#{i+1}: #{usr.name}"} | ||
|
||
# Duplicate users? If you have duplicate users you can search for them via their email address. | ||
# Duplicate users? If you have duplicate users you can search for them via their email address. | ||
# Note this feature is only available from version 1.1 of the API so you will need to switch to that version | ||
# This will return multiple users if they have the same email address | ||
usrs = intercom.users.find_all(type: 'users', email: '[email protected]', page: 1, per_page: 10, order: :asc) | ||
|
@@ -402,7 +402,7 @@ The metadata key values in the example are treated as follows- | |
|
||
*NB:* This version of the gem reserves the field name `type` in Event data. | ||
|
||
### Contacts | ||
#### Contacts | ||
|
||
`Contacts` represent logged out users of your application. | ||
Note that `contacts` are referred to as `leads` in the [Intercom](https://developers.intercom.com/intercom-api-reference/reference#leads) | ||
|
@@ -458,7 +458,13 @@ intercom.contacts.scroll.each { |lead| puts lead.id} | |
# Please see users scroll for more details of how to use scroll | ||
``` | ||
|
||
### Counts | ||
#### Customers | ||
|
||
# Search for customers | ||
customers = intercom.customers.search(query: { "field": "name", "operator": "=", "value": "Alice"}, per_page: 50, sort_field: "name", sort_order: "ascending") | ||
customers.each { |customer| p customer.name } | ||
|
||
#### Counts | ||
|
||
```ruby | ||
# App-wide counts | ||
|
@@ -468,7 +474,7 @@ intercom.counts.for_app | |
intercom.counts.for_type(type: 'user', count: 'segment') | ||
``` | ||
|
||
### Subscriptions | ||
#### Subscriptions | ||
|
||
Subscribe to events in Intercom to receive webhooks. | ||
|
||
|
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
require 'intercom/search_collection_proxy' | ||
require 'intercom/utils' | ||
|
||
module Intercom | ||
module ApiOperations | ||
module Search | ||
def search(params) | ||
collection_name = Utils.resource_class_to_collection_name(collection_class) | ||
search_details = { | ||
url: "/#{collection_name}/search", | ||
params: params | ||
} | ||
SearchCollectionProxy.new(collection_name, search_details: search_details, client: @client) | ||
end | ||
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
require 'intercom/traits/api_resource' | ||
|
||
module Intercom | ||
class Customer | ||
include Traits::ApiResource | ||
|
||
def identity_vars ; [:id, :email, :user_id] ; end | ||
def flat_store_attributes ; [:custom_attributes] ; 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
require "intercom/utils" | ||
|
||
module Intercom | ||
class SearchCollectionProxy | ||
|
||
attr_reader :resource_name, :resource_class | ||
|
||
def initialize(resource_name, search_details: {}, client:) | ||
@resource_name = resource_name | ||
@resource_class = Utils.constantize_resource_name(resource_name) | ||
@search_url = search_details[:url] | ||
@search_params = search_details[:params] | ||
@client = client | ||
end | ||
|
||
def each(&block) | ||
loop do | ||
response_hash = @client.post(@search_url, payload) | ||
raise Intercom::HttpError.new('Http Error - No response entity returned') unless response_hash | ||
deserialize_response_hash(response_hash, block) | ||
break unless has_next_link?(response_hash) | ||
end | ||
self | ||
end | ||
|
||
def [](target_index) | ||
self.each_with_index do |item, index| | ||
return item if index == target_index | ||
end | ||
nil | ||
end | ||
|
||
include Enumerable | ||
|
||
private | ||
|
||
def deserialize_response_hash(response_hash, block) | ||
top_level_type = response_hash.delete('type') | ||
top_level_entity_key = Utils.entity_key_from_type(top_level_type) | ||
response_hash[top_level_entity_key].each do |object_json| | ||
block.call Lib::TypedJsonDeserializer.new(object_json).deserialize | ||
end | ||
end | ||
|
||
def has_next_link?(response_hash) | ||
paging_info = response_hash.delete('pages') | ||
paging_next = paging_info["next"] | ||
if paging_next | ||
@search_params[:starting_after] = paging_next["starting_after"] | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
def payload | ||
payload = { | ||
query: @search_params[:query] | ||
} | ||
if @search_params[:sort_field] || @search_params[:sort_order] | ||
payload[:sort] = {} | ||
if @search_params[:sort_field] | ||
payload[:sort][:field] = @search_params[:sort_field] | ||
end | ||
if @search_params[:sort_order] | ||
payload[:sort][:order] = @search_params[:sort_order] | ||
end | ||
end | ||
if @search_params[:per_page] || @search_params[:starting_after] | ||
payload[:pagination] = {} | ||
if @search_params[:per_page] | ||
payload[:pagination][:per_page] = @search_params[:per_page] | ||
end | ||
if @search_params[:starting_after] | ||
payload[:pagination][:starting_after] = @search_params[:starting_after] | ||
end | ||
end | ||
return payload | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
require 'intercom/service/base_service' | ||
require 'intercom/api_operations/search' | ||
|
||
module Intercom | ||
module Service | ||
class Customer < BaseService | ||
include ApiOperations::Search | ||
|
||
def collection_class | ||
Intercom::Customer | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,13 @@ | |
require 'time' | ||
include WebMock::API | ||
|
||
def test_customer(email="[email protected]") | ||
customer = test_user(email) | ||
customer["type"] = "customer" | ||
customer["role"] = "user" | ||
customer | ||
end | ||
|
||
def test_user(email="[email protected]") | ||
{ | ||
"type" =>"user", | ||
|
@@ -228,6 +235,22 @@ def page_of_users(include_next_link= false) | |
} | ||
end | ||
|
||
def page_of_customers(include_starting_after= false) | ||
{ | ||
"type"=>"customer.list", | ||
"pages"=> | ||
{ | ||
"type"=>"pages", | ||
"next"=> (include_starting_after ? { "page" => 2, "starting_after" => "EnCrYpTeDsTrInG" } : nil), | ||
"page"=>1, | ||
"per_page"=>50, | ||
"total_pages"=>7 | ||
}, | ||
"customers"=> [test_customer("[email protected]"), test_customer("[email protected]"), test_customer("[email protected]")], | ||
"total_count"=>314 | ||
} | ||
end | ||
|
||
def users_scroll(include_users= false) | ||
{ | ||
"type"=>"user.list", | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
require "spec_helper" | ||
|
||
describe Intercom::SearchCollectionProxy do | ||
let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') } | ||
|
||
it "send query to the customer search endpoint" do | ||
client.expects(:post).with("/customers/search", { query: {} }). returns(page_of_customers(false)) | ||
client.customers.search(query: {}).first | ||
end | ||
|
||
it "send query to the customer search endpoint with sort_field" do | ||
client.expects(:post).with("/customers/search", { query: {}, sort: { field: "name" } }). returns(page_of_customers(false)) | ||
client.customers.search(query: {}, sort_field: "name").first | ||
end | ||
|
||
it "send query to the customer search endpoint with sort_field and sort_order" do | ||
client.expects(:post).with("/customers/search", { query: {}, sort: { field: "name", order: "ascending" } }). returns(page_of_customers(false)) | ||
client.customers.search(query: {}, sort_field: "name", sort_order: "ascending").first | ||
end | ||
|
||
it "send query to the customer search endpoint with per_page" do | ||
client.expects(:post).with("/customers/search", { query: {}, pagination: { per_page: 10 }}). returns(page_of_customers(false)) | ||
client.customers.search(query: {}, per_page: 10).first | ||
end | ||
|
||
it "send query to the customer search endpoint with starting_after" do | ||
client.expects(:post).with("/customers/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}). returns(page_of_customers(false)) | ||
client.customers.search(query: {}, starting_after: "EnCrYpTeDsTrInG").first | ||
end | ||
|
||
it "stops iterating if no starting_after value" do | ||
client.expects(:post).with("/customers/search", { query: {} }). returns(page_of_customers(false)) | ||
emails = [] | ||
client.customers.search(query: {}).each { |user| emails << user.email } | ||
emails.must_equal %W([email protected] [email protected] [email protected]) | ||
end | ||
|
||
it "keeps iterating if starting_after value" do | ||
client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(true)) | ||
client.expects(:post).with("/customers/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}).returns(page_of_customers(false)) | ||
emails = [] | ||
client.customers.search(query: {}).each { |user| emails << user.email } | ||
end | ||
|
||
it "supports indexed array access" do | ||
client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(false)) | ||
client.customers.search(query: {})[0].email.must_equal '[email protected]' | ||
end | ||
|
||
it "supports map" do | ||
client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(false)) | ||
emails = client.customers.search(query: {}).map { |user| user.email } | ||
emails.must_equal %W([email protected] [email protected] [email protected]) | ||
end | ||
|
||
end |