Skip to content

Commit 64ab993

Browse files
authored
Merge pull request #479 from zendesk/issue468-search-articles
Issue468 search articles
2 parents 01cae6e + 2eebe05 commit 64ab993

File tree

8 files changed

+106
-118
lines changed

8 files changed

+106
-118
lines changed

README.md

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,22 @@
66

77
## Documentation
88

9-
This Ruby gem is a wrapper around Zendesk's REST API. Please see our [API documentation](https://developer.zendesk.com) for more information.
9+
This Ruby gem is a generic wrapper around Zendesk's REST API. Follow this README and the [wiki](https://github.com/zendesk/zendesk_api_client_rb/wiki) for how to use it.
1010

11-
Please check out the [wiki](https://github.com/zendesk/zendesk_api_client_rb/wiki), [class documentation](https://www.rubydoc.info/gems/zendesk_api/), and [issues](https://github.com/zendesk/zendesk_api_client_rb/issues) before reporting a bug or asking for help.
11+
You can interact with all the resources defined in [`resources.rb`](lib/zendesk_api/resources.rb). Basically we have some cleaver code to convert Ruby objects into HTTP requests.
12+
13+
Please refer to our [API documentation](https://developer.zendesk.com) for the specific endpoints and once you understand the mapping between Ruby and the HTTP endpoints you should be able to call any endpoint.
14+
15+
The Yard generated documentation is available in at [RubyDoc](https://www.rubydoc.info/gems/zendesk_api).
16+
17+
Please report any bug in the [Github issues page](https://github.com/zendesk/zendesk_api_client_rb/issues).
1218

1319
## Product Support
1420

1521
This Ruby gem supports the REST API's for Zendesk Support, Zendesk Guide,
1622
and Zendesk Talk. It does not yet support other Zendesk products such as
1723
Zendesk Chat, Zendesk Explore, and Zendesk Sell.
1824

19-
## Important Notices
20-
21-
* Version 0.0.5 brings with it a change to the top-level namespace. All references to `Zendesk` should now use `ZendeskAPI`.
22-
* Version 0.3.0 changed the license from MIT to Apache Version 2.
23-
* Version 0.3.2 introduced a regression when side-loading roles on users. This was fixed in 0.3.4.
24-
* Version 1.0.0 changes the way errors are handled. Please see the [wiki page](https://github.com/zendesk/zendesk_api_client_rb/wiki/Errors) for more info.
25-
* Version 1.3.0 updates the Faraday dependency to 0.9. Since Faraday did not bump a major version we have not either, but there is no guarantee >= 1.3.0 works with Faraday < 0.9
26-
* Version 1.3.8 had a bug where attachments were created, but the response was not handled properly
27-
* Version >= 1.0 and < 1.4.2 had a bug where non application/json response bodies were discarded
28-
* Version 1.5.0 removed support for Ruby 1.8
29-
* Version 1.6.0 ZendeskAPI::Voice::CertificationAddress is now ZendeskAPI::Voice::Address
30-
* Version 1.8.0 no longer considers 1XX and 3XX (except 304) response status codes valid and will raise a NetworkError
31-
* Version 1.x.x requires you to install `scrub_rb` or `string-scrub` or similar implementation of `String#scrub!` if you're using Ruby 1.9 or 2.0.
32-
3325
## Installation
3426

3527
The Zendesk API client can be installed using Rubygems or Bundler.
@@ -44,14 +36,15 @@ gem install zendesk_api
4436

4537
Add it to your Gemfile
4638

47-
gem "zendesk_api"
39+
```
40+
gem "zendesk_api"
41+
```
4842

49-
and follow normal [Bundler](https://bundler.io/) installation and execution procedures.
43+
Then `bundle` as usual.
5044

5145
## Configuration
5246

5347
Configuration is done through a block returning an instance of `ZendeskAPI::Client`.
54-
The block is mandatory and if not passed, an `ArgumentError` will be thrown.
5548

5649
```ruby
5750
require 'zendesk_api'
@@ -449,9 +442,4 @@ bundle exec rubocop # Runs the lint (use `--fix` for autocorrect)
449442

450443
Copyright 2015-2022 Zendesk
451444

452-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
453-
You may obtain a copy of the License at
454-
455-
https://www.apache.org/licenses/LICENSE-2.0
456-
457-
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
445+
See [LICENSE](./LICENSE).

lib/zendesk_api/association.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,8 @@ def class_from_namespace(klass_as_string)
1919
nil
2020
end
2121

22-
# 1.9+ changed default to search ancestors, added flag to disable behavior.
2322
def module_defines_class?(mod, klass_as_string)
24-
if RUBY_VERSION < '1.9'
25-
mod.const_defined?(klass_as_string)
26-
else
27-
mod.const_defined?(klass_as_string, false)
28-
end
23+
mod.const_defined?(klass_as_string, false)
2924
end
3025
end
3126

@@ -58,7 +53,6 @@ def generate_path(*args)
5853

5954
namespace = @options[:class].to_s.split("::")
6055
namespace[-1] = @options[:class].resource_path
61-
6256
# Remove components without path information
6357
ignorable_namespace_strings.each { |ns| namespace.delete(ns) }
6458
has_parent = namespace.size > 1 || (options[:with_parent] && @options.parent)

lib/zendesk_api/collection.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require 'zendesk_api/resource'
22
require 'zendesk_api/resources'
3+
require 'zendesk_api/search'
34

45
module ZendeskAPI
56
# Represents a collection of resources. Lazily loaded, resources aren't
@@ -28,7 +29,7 @@ class Collection
2829
# @param [String] resource The resource being collected.
2930
# @param [Hash] options Any additional options to be passed in.
3031
def initialize(client, resource, options = {})
31-
@client, @resource_class, @resource = client, resource, resource.resource_name
32+
@client, @resource_class, @resource = client, resource, resource.resource_path
3233
@options = SilentMash.new(options)
3334

3435
set_association_from_options
@@ -186,6 +187,7 @@ def fetch!(reload = false)
186187
return (@resources = [])
187188
end
188189
path_query_link = (@query || path)
190+
189191
@response = get_response(path_query_link)
190192

191193
if path_query_link == "search/export"
@@ -253,7 +255,7 @@ def next
253255
if @options["page"]
254256
clear_cache
255257
@options["page"] += 1
256-
elsif @query = @next_page
258+
elsif (@query = @next_page)
257259
fetch(true)
258260
else
259261
clear_cache
@@ -269,7 +271,7 @@ def prev
269271
if @options["page"] && @options["page"] > 1
270272
clear_cache
271273
@options["page"] -= 1
272-
elsif @query = @prev_page
274+
elsif (@query = @prev_page)
273275
fetch(true)
274276
else
275277
clear_cache
@@ -398,8 +400,6 @@ def _save(method = :save)
398400
result
399401
end
400402

401-
## Initialize
402-
403403
def join_special_params
404404
# some params use comma-joined strings instead of query-based arrays for multiple values
405405
@options.each do |k, v|
@@ -415,7 +415,6 @@ def set_association_from_options
415415
association_options = { :path => @options.delete(:path) }
416416
association_options[:path] ||= @collection_path.join("/") if @collection_path
417417
@association = @options.delete(:association) || Association.new(association_options.merge(:class => @resource_class))
418-
419418
@collection_path ||= [@resource]
420419
end
421420

lib/zendesk_api/helpers.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@ module ZendeskAPI
22
# @private
33
module Helpers
44
# From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/modulize.rb
5+
# Converts a string to module name representation.
6+
#
7+
# This is essentially #camelcase, but it also converts
8+
# '/' to '::' which is useful for converting paths to
9+
# namespaces.
10+
#
11+
# Examples
12+
#
13+
# "method_name".modulize #=> "MethodName"
14+
# "method/name".modulize #=> "Method::Name"
15+
#
16+
# @param string [string] input, `module/class_name`
17+
# @return [string] a string that can become a class, `Module::ClassName`
518
def self.modulize_string(string)
619
# gsub('__','/'). # why was this ever here?
720
string.gsub(/__(.?)/) { "::#{$1.upcase}" }.
@@ -11,6 +24,14 @@ def self.modulize_string(string)
1124
end
1225

1326
# From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb
27+
# Underscore a string such that camelcase, dashes and spaces are
28+
# replaced by underscores. This is the reverse of {#camelcase},
29+
# albeit not an exact inverse.
30+
#
31+
# "SnakeCase".snakecase #=> "snake_case"
32+
# "Snake-Case".snakecase #=> "snake_case"
33+
# "Snake Case".snakecase #=> "snake_case"
34+
# "Snake - Case".snakecase #=> "snake_case"
1435
def self.snakecase_string(string)
1536
# gsub(/::/, '/').
1637
string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').

lib/zendesk_api/resource.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
require 'zendesk_api/verbs'
77

88
module ZendeskAPI
9-
# Represents a resource that only holds data.
9+
# Represents an abstract resource that only holds data.
1010
class Data
1111
include Associations
1212

@@ -54,6 +54,7 @@ def namespace(namespace)
5454
# @param [Hash] attributes The optional attributes that describe the resource
5555
def initialize(client, attributes = {})
5656
raise "Expected a Hash for attributes, got #{attributes.inspect}" unless attributes.is_a?(Hash)
57+
5758
@association = attributes.delete(:association) || Association.new(:class => self.class)
5859
@global_params = attributes.delete(:global) || {}
5960
@client = client
@@ -177,7 +178,7 @@ class DeleteResource < DataResource
177178
include Destroy
178179
end
179180

180-
# Represents a resource that can CRUD (create, read, update, delete).
181+
# Represents an abstract resource that can CRUD (create, read, update, delete).
181182
class Resource < DataResource
182183
include Read
183184
include Create

lib/zendesk_api/resources.rb

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -277,83 +277,6 @@ class SatisfactionRating < ReadResource
277277
has Group
278278
end
279279

280-
class Search
281-
class Result < Data; end
282-
283-
# Creates a search collection
284-
def self.search(client, options = {})
285-
unless (%w{query external_id} & options.keys.map(&:to_s)).any?
286-
warn "you have not specified a query for this search"
287-
end
288-
289-
ZendeskAPI::Collection.new(client, self, options)
290-
end
291-
292-
# Quack like a Resource
293-
# Creates the correct resource class from the result_type passed in
294-
def self.new(client, attributes)
295-
result_type = attributes["result_type"]
296-
297-
if result_type
298-
result_type = ZendeskAPI::Helpers.modulize_string(result_type)
299-
klass = ZendeskAPI.const_get(result_type) rescue nil
300-
end
301-
302-
(klass || Result).new(client, attributes)
303-
end
304-
305-
class << self
306-
def resource_name
307-
"search"
308-
end
309-
310-
alias :resource_path :resource_name
311-
312-
def model_key
313-
"results"
314-
end
315-
end
316-
end
317-
318-
# This will use cursor pagination by default
319-
class SearchExport
320-
class Result < Data; end
321-
322-
# Creates a search export collection
323-
def self.search_export(client, options = {})
324-
unless (%w{query external_id} & options.keys.map(&:to_s)).any?
325-
warn "you have not specified a query for this search"
326-
end
327-
328-
ZendeskAPI::Collection.new(client, self, options)
329-
end
330-
331-
# Quack like a Resource
332-
# Creates the correct resource class from the result_type passed in
333-
def self.new(client, attributes)
334-
result_type = attributes["result_type"]
335-
336-
if result_type
337-
result_type = ZendeskAPI::Helpers.modulize_string(result_type)
338-
klass = ZendeskAPI.const_get(result_type) rescue nil
339-
end
340-
341-
(klass || Result).new(client, attributes)
342-
end
343-
344-
class << self
345-
def resource_name
346-
"search/export"
347-
end
348-
349-
alias :resource_path :resource_name
350-
351-
def model_key
352-
"results"
353-
end
354-
end
355-
end
356-
357280
class Request < Resource
358281
class Comment < DataResource
359282
include Save

lib/zendesk_api/search.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# `zendesk_api` gem root
2+
module ZendeskAPI
3+
# A rich factory that returns a class for your searches
4+
class Search
5+
# Creates a search collection
6+
def self.search(client, options = {})
7+
if (options.keys.map(&:to_s) & %w[query external_id]).empty?
8+
warn "you have not specified a query for this search"
9+
end
10+
11+
ZendeskAPI::Collection.new(client, self, options)
12+
end
13+
14+
# Quack like a Resource
15+
# Creates the correct resource class from `attributes[:result_type]`
16+
def self.new(client, attributes)
17+
present_result_type = (attributes[:result_type] || attributes["result_type"]).to_s
18+
result_type = ZendeskAPI::Helpers.modulize_string(present_result_type)
19+
klass = begin
20+
ZendeskAPI.const_get(result_type)
21+
rescue NameError
22+
Result
23+
end
24+
25+
(klass || Result).new(client, attributes)
26+
end
27+
28+
class Result < Data; end
29+
30+
class << self
31+
def resource_name
32+
"search"
33+
end
34+
alias resource_path resource_name
35+
36+
def model_key
37+
"results"
38+
end
39+
end
40+
end
41+
42+
# This will use cursor pagination by default
43+
class SearchExport < Search
44+
class << self
45+
def resource_name
46+
"search/export"
47+
end
48+
alias resource_path resource_name
49+
end
50+
end
51+
end

spec/live/article_spec.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
expect(article).not_to be_nil
66
end
77

8-
describe "creating articles withing sections" do
8+
describe "creating articles within a section" do
99
def valid_attributes
1010
{ :name => "My Article", user_segment_id: nil, permission_group_id: 2801272, title: "My super article" }
1111
end
@@ -25,5 +25,16 @@ def valid_attributes
2525
it "can be created" do
2626
expect(section_article).not_to be_nil
2727
end
28+
29+
describe "#search" do
30+
before { section_article }
31+
32+
it "finds the article", :vcr do
33+
actual = client.articles.search(query: "What")
34+
35+
expect(actual.count).to be > 0
36+
expect(actual.last.title).to eq("What are these sections and articles doing here?")
37+
end
38+
end
2839
end
2940
end

0 commit comments

Comments
 (0)