chord 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ecdb151eb16d8e1187e7ae8a6bf59cd57895580ba5c578fd166ed5b2c795da16
4
+ data.tar.gz: 33bb400c1a6c0f6df638125ebc86d6fa54f513075e994756e71daf72a1cc198d
5
+ SHA512:
6
+ metadata.gz: cac1d8dfeb749f6e8e5e12776031973755f73e4976ed6bb4505fc464eb92b43942cffed3251ccb34d9013fbfab3ee4b32648c257107bac885b90e11231a27810
7
+ data.tar.gz: 1c95d655de397bd5b0d88c46d924ce8dbdd760bde3e17a16a38bf4dc7c262a8127a7f662ab9eacd5eb91315a5b9645cbea918a09a040eb0df281846f7ed5ab20
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ Major changes for each release. Please see the Git log for complete list of changes.
4
+
5
+ ## 0.0.1
6
+
7
+ * Very rudimentary start, focused on the parts of the API I need to use.
8
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009-2021 Alex Reisner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Chord OMS
2
+
3
+ These classes provide simple read and write access to the Chord OMS API. Get started like this:
4
+
5
+ CHORD_API_CONFIG = {
6
+ staging: {
7
+ base_url: 'https://<customer>.staging.assembly-api.com/api/',
8
+ api_key: '<key>'
9
+ },
10
+ production: {
11
+ base_url: 'https://<customer>.assembly-api.com/api/',
12
+ api_key: '<key>'
13
+ }
14
+ }
15
+
16
+ u = Chord::User.find(1) # fetch user
17
+ u.attributes # see attributes hash
18
+ u.update(name: 'New Name', notes: 'Etc') # update attributes
19
+ u.update(metadata: {ambassador_id: 415}) # when updating 'metadata' attribute, the given
20
+ # hash is merged into the existing value and
21
+ # keys and values are stringified (since
22
+ # metadata is stored in OMS as a JSON string)
23
+ u.add_role(3) # add role (by ID) to the user
24
+ u.remove_role(3) # remove role (by ID) from the user
25
+ u.subscriptions # fetch the user's subscriptions
26
+
27
+ Objects are constructed in a way that minimizes API calls but occasionally yields objects that seem incomplete. For example:
28
+
29
+ u = Chord::User.find(44)
30
+ s = u.subscriptions.first
31
+ s.user
32
+
33
+ will return a Chord::User object with only two attributes (ID and email) because the API only returns two attributes with a Subscription object.
34
+
data/bin/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'chord'
5
+
6
+ if File.exist?('config.yml')
7
+ require 'yaml'
8
+ CHORD_API_CONFIG = YAML.load(File.read('config.yml'), symbolize_names: true)
9
+ end
10
+
11
+ require 'irb'
12
+ IRB.start
@@ -0,0 +1,3 @@
1
+ module Chord
2
+ VERSION = "0.0.1"
3
+ end
data/lib/chord.rb ADDED
@@ -0,0 +1,201 @@
1
+ require 'httparty'
2
+
3
+ module Chord
4
+
5
+ class << self
6
+ attr_writer :env
7
+ def env; @env || :staging; end # :staging by default
8
+ end
9
+
10
+ class Base
11
+ include HTTParty
12
+
13
+ class << self
14
+ attr_writer :per_page
15
+ def per_page; @per_page || 99999; end
16
+ end
17
+
18
+ def self.base_url
19
+ CHORD_API_CONFIG[Chord.env][:base_url]
20
+ end
21
+
22
+ def self.find(id)
23
+ attrs = get(base_url + "#{base_path}/#{id}", http_options).parsed_response
24
+ new(id, attrs)
25
+ end
26
+
27
+ def self.fetch_all_data(query_options = {})
28
+ query_options = {
29
+ per_page: per_page
30
+ }.merge(query_options)
31
+ get(base_url + "#{base_path}?#{hash_to_query(query_options)}", http_options).parsed_response
32
+ end
33
+
34
+ def self.all(query_options = {})
35
+ @all ||= fetch_all_data(query_options)[base_path].map{ |i| new(i['id'], i) }
36
+ end
37
+
38
+ def self.http_options
39
+ {headers: {
40
+ 'Authorization' => "Bearer #{CHORD_API_CONFIG[Chord.env][:api_key]}",
41
+ 'Content-Type' => 'application/json'
42
+ }}
43
+ end
44
+
45
+ def self.hash_to_query(hash)
46
+ require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
47
+ hash.collect{ |p|
48
+ p[1].nil? ? nil : p.map{ |i| CGI.escape i.to_s } * '='
49
+ }.compact.sort * '&'
50
+ end
51
+
52
+ def base_url
53
+ self.class.base_url
54
+ end
55
+
56
+ def base_path
57
+ self.class.base_path
58
+ end
59
+
60
+ def http_options
61
+ self.class.http_options
62
+ end
63
+
64
+ attr_reader :id
65
+ attr_accessor :attributes
66
+
67
+ def initialize(id, attributes = {})
68
+ @id = id
69
+ @attributes = attributes
70
+ end
71
+
72
+ def update(new_attributes)
73
+ new_attributes.stringify_keys!
74
+ # merge values into existing metadata
75
+ if new_attributes.include?('metadata')
76
+ # Chord expects all metadata values to be strings
77
+ new_metadata = new_attributes['metadata'].map{ |k,v| [k.to_s, v.to_s] }.to_h
78
+ new_attributes['metadata'] = (attributes['metadata'] || {}).merge(new_metadata)
79
+ # TODO: delete entries with empty value?
80
+ end
81
+ self.attributes = self.class.patch(base_url + "#{base_path}/#{id}",
82
+ http_options.merge(body: new_attributes.to_json)
83
+ ).parsed_response
84
+ end
85
+
86
+ def delete
87
+ self.class.delete(base_url + "#{base_path}/#{id}", http_options).parsed_response
88
+ end
89
+
90
+ def method_missing(method, *args, &block)
91
+ if attributes.include?(method.to_s)
92
+ attributes[method.to_s]
93
+ else
94
+ super
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ class User < Base
101
+
102
+ #
103
+ # For avoiding API calls.
104
+ #
105
+ def self.all_by_id
106
+ unless @all_by_id
107
+ @all_by_id = {}
108
+ all.each do |u|
109
+ @all_by_id[u.id] = u
110
+ end
111
+ end
112
+ @all_by_id
113
+ end
114
+
115
+ #
116
+ # For mapping users on our old site to Chord.
117
+ #
118
+ def self.all_by_email
119
+ unless @all_by_email
120
+ @all_by_email = {}
121
+ all.each do |u|
122
+ @all_by_email[u.email] = u
123
+ end
124
+ end
125
+ @all_by_email
126
+ end
127
+
128
+ def self.base_path
129
+ 'users'
130
+ end
131
+
132
+ def add_role(role_id)
133
+ self.class.put(base_url + "roles/#{role_id}/add/#{id}", http_options).parsed_response
134
+ end
135
+
136
+ def remove_role(role_id)
137
+ self.class.put(base_url + "roles/#{role_id}/remove/#{id}", http_options).parsed_response
138
+ end
139
+
140
+ def subscriptions
141
+ self.class.get(base_url + "users/#{id}/subscriptions", http_options).parsed_response['subscriptions'].map{ |s| Chord::Subscription.new(s['id'], s) }
142
+ end
143
+
144
+ def find_subscription(subscription_id)
145
+ self.class.get(base_url + "users/#{id}/subscriptions/#{subscription_id}", http_options).parsed_response
146
+ end
147
+ end
148
+
149
+
150
+ class Order < Base
151
+
152
+ def self.base_path
153
+ 'orders'
154
+ end
155
+
156
+ def user
157
+ Chord::User.find(attributes['user_id'])
158
+ end
159
+
160
+ def payments
161
+ self.class.get(base_url + "orders/#{id}/payments", http_options).parsed_response['payments'].map{ |p| Chord::Payment.new(p['id'], p) }
162
+ end
163
+
164
+ def create_adjustment(order_id, label, discount)
165
+ attributes = {
166
+ label: label,
167
+ discount_by: discount
168
+ }
169
+ self.class.post(base_url + "hub/orders/#{order_id}/adjustments",
170
+ http_options.merge(body: attributes.to_json)
171
+ ).parsed_response
172
+ end
173
+ end
174
+
175
+
176
+ class Role < Base
177
+
178
+ def self.base_path
179
+ 'roles'
180
+ end
181
+ end
182
+
183
+
184
+ class Subscription < Base
185
+
186
+ def user
187
+ u = attributes['user']
188
+ Chord::User.new(u['id'], u)
189
+ end
190
+ end
191
+
192
+ class Payment < Base
193
+ end
194
+
195
+ class Product < Base
196
+
197
+ def self.base_path
198
+ 'products'
199
+ end
200
+ end
201
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chord
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alex Reisner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.20.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.20.0
27
+ description: ActiveRecord-like syntax. Still in alpha-stage early development. Many
28
+ endpoints and features not yet supported. Some bugs.
29
+ email:
30
+ - alex@alexreisner.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE
37
+ - README.md
38
+ - bin/console
39
+ - lib/chord.rb
40
+ - lib/chord/version.rb
41
+ homepage: https://www.github.com/alexreisner/chord
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ source_code_uri: https://github.com/alexreisner/chord
46
+ changelog_uri: https://github.com/alexreisner/chord/blob/master/CHANGELOG.md
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 2.0.0
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.1.6
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: Easy access to Chord Commerce API.
66
+ test_files: []