qrapi-wrapper 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/lib/qrapi.rb +79 -0
  3. data/lib/qrapi/client.rb +58 -0
  4. data/lib/qrapi/error_handling_resourceable.rb +22 -0
  5. data/lib/qrapi/mappings/contact_mapping.rb +22 -0
  6. data/lib/qrapi/mappings/distribution_mapping.rb +68 -0
  7. data/lib/qrapi/mappings/division_mapping.rb +27 -0
  8. data/lib/qrapi/mappings/error_mapping.rb +19 -0
  9. data/lib/qrapi/mappings/group_mapping.rb +27 -0
  10. data/lib/qrapi/mappings/library_message_mapping.rb +20 -0
  11. data/lib/qrapi/mappings/mailing_list_mapping.rb +20 -0
  12. data/lib/qrapi/mappings/organization_mapping.rb +19 -0
  13. data/lib/qrapi/mappings/response_export_mapping.rb +14 -0
  14. data/lib/qrapi/mappings/responses_mapping.rb +45 -0
  15. data/lib/qrapi/mappings/survey_mapping.rb +33 -0
  16. data/lib/qrapi/mappings/user_mapping.rb +40 -0
  17. data/lib/qrapi/models/base_model.rb +22 -0
  18. data/lib/qrapi/models/distribution.rb +45 -0
  19. data/lib/qrapi/models/distribution/headers.rb +27 -0
  20. data/lib/qrapi/models/distribution/message.rb +26 -0
  21. data/lib/qrapi/models/distribution/recipients.rb +26 -0
  22. data/lib/qrapi/models/distribution/survey_link.rb +26 -0
  23. data/lib/qrapi/models/division.rb +32 -0
  24. data/lib/qrapi/models/group.rb +31 -0
  25. data/lib/qrapi/models/library_message.rb +27 -0
  26. data/lib/qrapi/models/mailing_list.rb +27 -0
  27. data/lib/qrapi/models/mailing_list/contact.rb +33 -0
  28. data/lib/qrapi/models/organization.rb +29 -0
  29. data/lib/qrapi/models/response.rb +40 -0
  30. data/lib/qrapi/models/response_export.rb +71 -0
  31. data/lib/qrapi/models/survey.rb +45 -0
  32. data/lib/qrapi/models/survey/expiration.rb +25 -0
  33. data/lib/qrapi/models/user.rb +44 -0
  34. data/lib/qrapi/resources/distribution_resource.rb +47 -0
  35. data/lib/qrapi/resources/division_resource.rb +24 -0
  36. data/lib/qrapi/resources/group_resource.rb +44 -0
  37. data/lib/qrapi/resources/library_message_resource.rb +41 -0
  38. data/lib/qrapi/resources/mailing_list_resource.rb +51 -0
  39. data/lib/qrapi/resources/organization_resource.rb +12 -0
  40. data/lib/qrapi/resources/response_export_resource.rb +49 -0
  41. data/lib/qrapi/resources/response_import_resource.rb +26 -0
  42. data/lib/qrapi/resources/survey_resource.rb +27 -0
  43. data/lib/qrapi/resources/user_resource.rb +35 -0
  44. data/lib/qrapi/utils/kartograph_optional_properties.rb +21 -0
  45. data/lib/qrapi/version.rb +3 -0
  46. metadata +271 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6f55c877f28d86f3eef311c12ca12259e4cc657f9e62ace2f9276dae6f81a460
4
+ data.tar.gz: 4ae23eaeb89fb89ba8e08cb4247828c9b30326865abfdcb99bc32de6631fd5fe
5
+ SHA512:
6
+ metadata.gz: 91bfc6a270ee30f6cf7b27707271c8806994090fde5bcb5ea12b0ae169c8c3a84aec0c0554214da6277d3741eb1a5139253e860bd5aa759e13e69af7fcb7a537
7
+ data.tar.gz: eda8bb8744cd27b4e5a0ca1c740beaffb6e4d62fdea5e6d3372b08f3318c5427660e118f150f73e5245f3952c62678eea98e735ce4246823f9c775223fcd66fc
@@ -0,0 +1,79 @@
1
+ require "zip"
2
+ require "json"
3
+ require "kartograph"
4
+ require "resource_kit"
5
+ require "qrapi/version"
6
+ require "active_model"
7
+ require "active_support/all"
8
+
9
+ module QRAPI
10
+ autoload :Client, "qrapi/client"
11
+
12
+ # Models
13
+ autoload :BaseModel, "qrapi/models/base_model"
14
+ autoload :Organization, "qrapi/models/organization"
15
+ autoload :Division, "qrapi/models/division"
16
+ autoload :Group, "qrapi/models/group"
17
+ autoload :Survey, "qrapi/models/survey"
18
+ Survey.autoload :Expiration, "qrapi/models/survey/expiration"
19
+ autoload :User, "qrapi/models/user"
20
+ autoload :LibraryMessage, "qrapi/models/library_message"
21
+ autoload :Distribution, "qrapi/models/distribution"
22
+ Distribution.autoload :Headers, "qrapi/models/distribution/headers"
23
+ Distribution.autoload :Message, "qrapi/models/distribution/message"
24
+ Distribution.autoload :Recipients, "qrapi/models/distribution/recipients"
25
+ Distribution.autoload :SurveyLink, "qrapi/models/distribution/survey_link"
26
+ autoload :ResponseExport, "qrapi/models/response_export"
27
+ autoload :Response, "qrapi/models/response"
28
+ autoload :MailingList, "qrapi/models/mailing_list"
29
+ MailingList.autoload :Contact, "qrapi/models/mailing_list/contact"
30
+
31
+ # Resources
32
+ autoload :OrganizationResource, "qrapi/resources/organization_resource"
33
+ autoload :DivisionResource, "qrapi/resources/division_resource"
34
+ autoload :GroupResource, "qrapi/resources/group_resource"
35
+ autoload :SurveyResource, "qrapi/resources/survey_resource"
36
+ autoload :UserResource, "qrapi/resources/user_resource"
37
+ autoload :LibraryMessageResource, "qrapi/resources/library_message_resource"
38
+ autoload :DistributionResource, "qrapi/resources/distribution_resource"
39
+ autoload :ResponseExportResource, "qrapi/resources/response_export_resource"
40
+ autoload :ResponseImportResource, "qrapi/resources/response_import_resource"
41
+ autoload :MailingListResource, "qrapi/resources/mailing_list_resource"
42
+
43
+ # JSON Maps
44
+ autoload :OrganizationMapping, "qrapi/mappings/organization_mapping"
45
+ autoload :DivisionMapping, "qrapi/mappings/division_mapping"
46
+ autoload :GroupMapping, "qrapi/mappings/group_mapping"
47
+ autoload :SurveyMapping, "qrapi/mappings/survey_mapping"
48
+ autoload :ExpirationMapping, "qrapi/mappings/expiration_mapping"
49
+ autoload :UserMapping, "qrapi/mappings/user_mapping"
50
+ autoload :LibraryMessageMapping, "qrapi/mappings/library_message_mapping"
51
+ autoload :DistributionMapping, "qrapi/mappings/distribution_mapping"
52
+ autoload :ResponseExportMapping, "qrapi/mappings/response_export_mapping"
53
+ autoload :ResponsesMapping, "qrapi/mappings/responses_mapping"
54
+ autoload :MailingListMapping, "qrapi/mappings/mailing_list_mapping"
55
+ autoload :ContactMapping, "qrapi/mappings/contact_mapping"
56
+
57
+ # Utils
58
+ autoload :ErrorHandlingResourceable, "qrapi/error_handling_resourceable"
59
+ autoload :Kartograph, "qrapi/utils/kartograph_optional_properties"
60
+
61
+ # Errors
62
+ autoload :ErrorMapping, "qrapi/mappings/error_mapping"
63
+ Error = Class.new(StandardError)
64
+ FailedCreate = Class.new(QRAPI::Error)
65
+ FailedUpdate = Class.new(QRAPI::Error)
66
+
67
+ class RateLimitReached < QRAPI::Error
68
+ attr_accessor :reset_at
69
+ attr_writer :limit, :remaining
70
+
71
+ def limit
72
+ @limit.to_i if @limit
73
+ end
74
+
75
+ def remaining
76
+ @remaning.to_i if @remaning
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,58 @@
1
+ require "faraday"
2
+
3
+ module QRAPI
4
+ class Client
5
+ attr_reader :api_token, :data_center_id
6
+
7
+ def initialize(options = {})
8
+ @api_token = options[:api_token]
9
+ @data_center_id = options[:data_center_id]
10
+ end
11
+
12
+ def connection
13
+ Faraday.new(connection_options) do |req|
14
+ req.adapter :net_http
15
+ end
16
+ end
17
+
18
+ def self.resources
19
+ {
20
+ organization: OrganizationResource,
21
+ divisions: DivisionResource,
22
+ groups: GroupResource,
23
+ users: UserResource,
24
+ surveys: SurveyResource,
25
+ response_exports: ResponseExportResource,
26
+ response_imports: ResponseImportResource,
27
+ library_messages: LibraryMessageResource,
28
+ distributions: DistributionResource,
29
+ mailing_lists: MailingListResource
30
+ }
31
+ end
32
+
33
+ def method_missing(name, *args, &block)
34
+ if self.class.resources.keys.include?(name)
35
+ resources[name] ||= self.class.resources[name].new(connection: connection)
36
+ resources[name]
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def resources
43
+ @resources ||= {}
44
+ end
45
+
46
+ private
47
+
48
+ def connection_options
49
+ {
50
+ url: "https://#{@data_center_id}.qualtrics.com",
51
+ headers: {
52
+ content_type: "application/json",
53
+ X_API_TOKEN: api_token
54
+ }
55
+ }
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,22 @@
1
+ module ErrorHandlingResourceable
2
+ def self.included(base)
3
+ base.send(:resources) do
4
+ default_handler do |response|
5
+ if (200...299).include?(response.status)
6
+ next
7
+ elsif response.status == 429
8
+ error = QRAPI::RateLimitReached.new("#{response.status}: #{response.body}")
9
+ error.limit = response.headers["RateLimit-Limit"]
10
+ error.remaining = response.headers["RateLimit-Remaining"]
11
+ error.reset_at = response.headers["RateLimit-Reset"]
12
+ raise error
13
+ else
14
+ body = JSON.parse(response.body)
15
+ error_message = body["meta"]["error"]["errorMessage"]
16
+ error_code = body["meta"]["error"]["errorCode"]
17
+ raise QRAPI::Error.new("Status: #{response.status} Error: #{error_code} - #{error_message}")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module QRAPI
2
+ class ContactMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping MailingList::Contact
7
+ root_key plural: "elements", scopes: [:read]
8
+
9
+ property :id, scopes: [:read]
10
+
11
+ scoped :read, :update do
12
+ property :first_name, key: "firstName", optional: true
13
+ property :last_name, key: "lastName", optional: true
14
+ property :email, optional: true
15
+ property :external_data_reference, key: "externalDataReference", optional: true
16
+ property :language, optional: true
17
+ property :embedded_data, key: "embeddedData", optional: true
18
+ property :unsubscribed, optional: true
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
1
+ module QRAPI
2
+ class DistributionMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping Distribution
7
+ root_key singular: "result", plural: "elements", scopes: [:read]
8
+
9
+ property :send_date, scopes: [:read, :create, :create_child], key: "sendDate"
10
+
11
+ property :recipients, scopes: [:read, :create] do
12
+ mapping Distribution::Recipients
13
+
14
+ property :mailing_list_id, scopes: [:read, :create], key: "mailingListId"
15
+ property :contact_id, scopes: [:read, :create], key: "contactId", optional: true
16
+ end
17
+
18
+ property :headers, scopes: [:read, :create, :create_child] do
19
+ mapping Distribution::Headers
20
+
21
+ property :from_email, scopes: [:read, :create, :create_child], key: "fromEmail"
22
+ property :from_name, scopes: [:read, :create, :create_child], key: "fromName"
23
+ property :reply_to_email, scopes: [:read, :create, :create_child], key: "replyToEmail"
24
+ property :subject, scopes: [:read, :create, :create_child]
25
+ end
26
+
27
+ property :message, scopes: [:read, :create], optional: true do
28
+ mapping Distribution::Message
29
+
30
+ property :message_id, scopes: [:read, :create], key: "messageId"
31
+ property :library_id, scopes: [:read, :create], key: "libraryId"
32
+ property :message_text, scopes: [:read, :create], key: "messageText"
33
+ end
34
+
35
+ property :survey_link, scopes: [:read, :create], optional: true, key: "surveyLink" do
36
+ mapping Distribution::SurveyLink
37
+
38
+ property :survey_id, scopes: [:read, :create], key: "surveyId"
39
+ property :expiration_date, scopes: [:read, :create], key: "expirationDate"
40
+ property :type, scopes: [:read, :create]
41
+ end
42
+
43
+ scoped :read do
44
+ property :id
45
+ property :parent_distribution_id, key: "parentDistributionId"
46
+ property :owner_id, key: "ownerId"
47
+ property :organization_id, key: "organizationId"
48
+ property :request_status, key: "requestStatus"
49
+ property :request_type, key: "requestType"
50
+ property :created_date, key: "createdDate"
51
+ property :modified_date, key: "modifiedDate"
52
+ property :stats
53
+ end
54
+
55
+ scoped :create_child do
56
+ property :message do
57
+ mapping Distribution::Message
58
+
59
+ scoped :create_child do
60
+ property :message_id, key: "messageId"
61
+ property :library_id, key: "libraryId"
62
+ property :message_text, key: "messageText"
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,27 @@
1
+ module QRAPI
2
+ class DivisionMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping Division
7
+ root_key singular: "result", scopes: [:read]
8
+
9
+ property :name, scopes: [:read, :update], optional: true
10
+ property :status, scopes: [:read, :update], optional: true
11
+ # property :permissions, scopes: [:read, :create, :update], optional: true
12
+
13
+ scoped :read do
14
+ property :id
15
+ property :organization_id, key: "organizationId"
16
+ property :creation_date, key: "creationDate"
17
+ property :creator_id, key: "creatorId"
18
+ property :response_counts, key: "responseCounts"
19
+ end
20
+
21
+ scoped :create do
22
+ property :name
23
+ property :division_admins, key: "divisionAdmins", optional: true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module QRAPI
2
+ class ErrorMapping
3
+ Error = Struct.new(:message, :id)
4
+
5
+ include Kartograph::DSL
6
+
7
+ kartograph do
8
+ mapping Error
9
+
10
+ property :id, scopes: [:read]
11
+ property :message, scopes: [:read]
12
+ end
13
+
14
+ def self.fail_with(klass, content)
15
+ error = extract_single(content, :read)
16
+ raise klass, error.message
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module QRAPI
2
+ class GroupMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping Group
7
+ root_key singular: "result", plural: "elements", scopes: [:read]
8
+
9
+ property :type, scopes: [:read, :create]
10
+ property :name, scopes: [:read, :create]
11
+ property :division_id, scopes: [:read, :update], key: "divisionId", optional: true
12
+
13
+ scoped :read do
14
+ property :id
15
+ property :organization_id, key: "organizationId"
16
+ property :all_users, key: "allUsers"
17
+ property :creation_date, key: "creationDate"
18
+ property :creator_id, key: "creatorId"
19
+ end
20
+
21
+ scoped :update do
22
+ property :type, optional: true
23
+ property :name, optional: true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module QRAPI
2
+ class LibraryMessageMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping LibraryMessage
7
+ root_key singular: "result", plural: "elements", scopes: [:read]
8
+
9
+ property :id, scopes: [:read]
10
+ property :category, scopes: [:read, :create]
11
+ property :messages, scopes: [:read, :update], optional: true
12
+ property :description, scopes: [:read, :update], optional: true
13
+
14
+ scoped :create do
15
+ property :description
16
+ property :messages
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module QRAPI
2
+ class MailingListMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping MailingList
7
+ root_key singular: "result", plural: "elements", scopes: [:read]
8
+
9
+ property :id, scopes: [:read]
10
+ property :name, scopes: [:read, :create]
11
+ property :library_id, scopes: [:read, :create], key: "libraryId"
12
+ property :category, scopes: [:read, :create, :update], optional: true
13
+
14
+ scoped :update do
15
+ property :name, optional: true
16
+ property :library_id, key: "libraryId", optional: true
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module QRAPI
2
+ class OrganizationMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping Organization
7
+ root_key singular: "result", scopes: [:read]
8
+
9
+ scoped :read do
10
+ property :id
11
+ property :name
12
+ property :base_url
13
+ property :type
14
+ property :status
15
+ property :stats
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module QRAPI
2
+ class ResponseExportMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping ResponseExport
7
+ root_key singular: "result", scopes: [:read]
8
+
9
+ scoped :read do
10
+ property :percent_complete, key: "percentComplete"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,45 @@
1
+ module QRAPI
2
+ class ResponsesMapping
3
+ # Maps each of the responses to a QRAPI::Response model
4
+ #
5
+ # @return [QRAPI::Response]
6
+ def self.from_json_or_xml(serialized_response, f_type)
7
+ case f_type
8
+ when :json
9
+ responses_hash = JSON.parse(serialized_response)
10
+ unmapped_responses = responses_hash["responses"]
11
+ when :xml
12
+ responses_hash = Hash.from_xml(serialized_response)
13
+ unmapped_responses = responses_hash["xml"]["Response"]
14
+ end
15
+
16
+ responses = []
17
+ unmapped_responses.each do |response|
18
+ r = Response.new
19
+ r.id = response["ResponseID"]
20
+ r.response_set = response["ResponseSet"]
21
+ r.ip_address = response["IPAddress"]
22
+ r.start_date = response["StartDate"]
23
+ r.end_date = response["EndDate"]
24
+ r.last_name = response["RecipientLastName"]
25
+ r.first_name = response["RecipientFirstName"]
26
+ r.email = response["RecipientEmail"]
27
+ r.external_data_reference = response["ExternalDataReference"]
28
+ r.finished = response["Finished"]
29
+ r.status = response["Status"]
30
+ r.location_latitude = response["LocationLatitude"]
31
+ r.location_longitude = response["LocationLongitude"]
32
+ r.location_accuracy = response["LocationAccuracy"]
33
+
34
+ r.questions = {}
35
+ response.keys.grep(/Q([0-9xy_]+)/).each do |key|
36
+ r.questions[key] = response[key]
37
+ end
38
+
39
+ responses << r
40
+ end
41
+
42
+ responses
43
+ end
44
+ end
45
+ end