apisync 0.1.0 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ac6a9c1548e8e2dde54d0f957ef97b9d6949259
4
- data.tar.gz: be3397eee31649c642e49bec55741f7cc4cfaa4a
3
+ metadata.gz: f3baebf434178862cf7ad0513124cfa460f1ed8c
4
+ data.tar.gz: 89cfa8062601ae2a64b15a52072303789e97f027
5
5
  SHA512:
6
- metadata.gz: f7dc60dd6dac986fd8aeb6b32b661bbd195a1c1247153f3b2f2e2a82f3f152b8e3b04e62b27c5ee97c1b8d26f3f290262f7b04e7e5c2b1b5002c024be0116a91
7
- data.tar.gz: 4728886e023f1740a9069b6715b58e6321169c8e7e3f9eda680b2f1649224ff82884dae24935ef8bcc1b05f9724b35806ebc2b69dc3ed5c63f94f89838720e64
6
+ metadata.gz: 7e87c8cf404ed809e67588896489dafc1bfcba4a3fdd5e069be68d4f38b38b365f54b9fac016568e15a22c1afbd4b12815a6a03296edcde66e6a62b75f09650e
7
+ data.tar.gz: c1bd720f4e8700182878c26f649c7b0ddfc10dab926159052194007c22f9646dd22859d7063c7840339058d573dd2278907b4265ef53c75f757240f732c5fb4c
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+ *.gem
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Apisync
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/apisync`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ This gem gives you the tools to interact with [apisync.io](apisync.io).
6
4
 
7
5
  ## Installation
8
6
 
@@ -12,27 +10,42 @@ Add this line to your application's Gemfile:
12
10
  gem 'apisync'
13
11
  ```
14
12
 
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
13
+ ## Usage
20
14
 
21
- $ gem install apisync
15
+ ### Vanilla Ruby
22
16
 
23
- ## Usage
17
+ To create an inventory item:
24
18
 
25
- TODO: Write usage instructions here
19
+ ```ruby
20
+ client = Apisync.new(api_key: token)
21
+ client.inventory_items.save({
22
+ attributes: {
23
+ ad_template_type: "vehicle",
24
+ availability: "on-sale",
25
+ brand: "brand",
26
+ condition: "new",
27
+ content_language: "pt-br"
28
+ # ... more attributes
29
+ }
30
+ })
31
+ ```
26
32
 
27
33
  ## Development
28
34
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+ To run tests:
36
+
37
+ ```
38
+ bundle exec rspec spec
39
+ ```
30
40
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
41
+ To release a new version, update the version number in `version.rb`, and then
42
+ run `bundle exec rake release`, which will create a git tag for the version,
43
+ push git commits and tags, and push the `.gem` file to
44
+ [rubygems.org](https://rubygems.org).
32
45
 
33
46
  ## Contributing
34
47
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/kurko/apisync.
48
+ Bug reports and pull requests are welcome on GitHub at https://github.com/apisync/apisync-ruby.
36
49
 
37
50
  ## License
38
51
 
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "apisync"
8
8
  spec.version = Apisync::VERSION
9
9
  spec.authors = ["Alexandre de Oliveira"]
10
- spec.email = ["alex@veiculo.online"]
10
+ spec.email = ["chavedomundo@gmail.com"]
11
11
 
12
12
  spec.summary = %q{Official client to apisync.io}
13
13
  spec.homepage = "https://github.com/apisync/apisync-ruby"
@@ -20,7 +20,11 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
+ spec.add_dependency "httparty", "~> 0.13"
24
+
23
25
  spec.add_development_dependency "bundler", "~> 1.15"
24
26
  spec.add_development_dependency "rake", "~> 10.0"
25
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "awesome_print"
29
+ spec.add_development_dependency "pry"
26
30
  end
@@ -1,5 +1,29 @@
1
+ require "bundler/setup"
2
+ require "httparty"
3
+
1
4
  require "apisync/version"
5
+ require "apisync/exceptions"
6
+ require "apisync/resource"
7
+ require "apisync/http_client"
8
+ require "apisync/http/url"
9
+ require "apisync/http/query_string"
10
+
11
+ class Apisync
12
+ @@api_key = nil
13
+
14
+ def initialize(api_key: nil)
15
+ @api_key = api_key || @@api_key
16
+
17
+ raise ArgumentError, "missing keyword: api_key" if @api_key.nil?
18
+ end
19
+
20
+ def method_missing(name, args = {}, &block)
21
+ # overrides the instance api_key as `authorization`
22
+ options = args.merge(api_key: @api_key)
23
+ Apisync::Resource.new(name, options)
24
+ end
2
25
 
3
- module Apisync
4
- # Your code goes here...
26
+ def self.api_key=(key)
27
+ @@api_key = key
28
+ end
5
29
  end
@@ -0,0 +1,7 @@
1
+ class Apisync
2
+ class Exception < StandardError; end
3
+
4
+ # List of exceptions. They are all inherited from Apisync::Exception
5
+ class UrlAndPayloadIdMismatch < Apisync::Exception; end
6
+ class InvalidFilter < Apisync::Exception; end
7
+ end
@@ -0,0 +1,68 @@
1
+ class Apisync
2
+ module Http
3
+ class QueryString
4
+ def initialize(filters:)
5
+ @filters = filters
6
+ end
7
+
8
+ def to_s
9
+ result = ""
10
+ result << format_filters if @filters
11
+ result
12
+ end
13
+
14
+ private
15
+
16
+ # Takes a list of `[key]=value` strings and maps them adding `"filter"`
17
+ # as prefix.
18
+ #
19
+ # Results in `filter[key]=value&filter[key2]=value2`.
20
+ def format_filters
21
+ recursive_brackets(@filters)
22
+ .flatten
23
+ .map { |filter| "filter#{filter}" }
24
+ .join("&")
25
+ end
26
+
27
+ # Takes a hash such as
28
+ #
29
+ # {
30
+ # field_one: 'value1',
31
+ # metadata: {
32
+ # field_two: "value2",
33
+ # field_three: "value3"
34
+ # }
35
+ # }
36
+ #
37
+ # and returns
38
+ #
39
+ # [
40
+ # "[field-one]=value1",
41
+ # "[metadata][field-two]=value2",
42
+ # "[metadata][field-three]=value3"
43
+ # ]
44
+ #
45
+ # This can be used for creating filter querystrings.
46
+ def recursive_brackets(hash, prefix = "")
47
+ result = []
48
+ hash.each do |key, value|
49
+ key = hyphenize(key.to_s)
50
+ if value.is_a?(Hash)
51
+ prefix = "#{prefix}[#{key}]"
52
+ top_nodes = recursive_brackets(value, prefix)
53
+ result << top_nodes
54
+ else
55
+ result << "#{prefix}[#{key}]=#{value}"
56
+ end
57
+ end
58
+
59
+ result
60
+ end
61
+
62
+ # Converts application_id in application-id.
63
+ def hyphenize(string)
64
+ string.gsub(/_/, "-")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ class Apisync
2
+ module Http
3
+
4
+ # Responsible for generating URLs
5
+ class Url
6
+ DEFAULT_HOST = "https://api.apisync.io"
7
+
8
+ # - resource_name: a name in plural such as 'users', 'profiles' etc.
9
+ # - id: id of the resource that you're looking for
10
+ # - filters: these will define what's in the query string, such as
11
+ # 'filter[application-id]=value'
12
+ # - options: allows you to pass options such 'host'. Accepted options are
13
+ #
14
+ # - host: a custom host for the URL, defaults to DEFAULT_HOST
15
+ def initialize(resource_name:, id: nil, filters: nil, options:)
16
+ @resource_name = resource_name
17
+ @id = id
18
+ @filters = filters
19
+ @options = {
20
+ host: nil
21
+ }.merge(options)
22
+ end
23
+
24
+ # to_s
25
+ #
26
+ # Takes a host, api_version, resource name and id and form the URL. Then
27
+ # pass filters and other options into QueryString class which will return
28
+ # whatever is after the `?` symbol.
29
+ #
30
+ # Returns a string such as
31
+ #
32
+ # 'https://api.apisync.io/inventory-items?filter[application-id]=abc'
33
+ #
34
+ # If there are no query strings, omits the `?`
35
+ #
36
+ # 'https://api.apisync.io/inventory-items'
37
+ #
38
+ def to_s
39
+ url = [
40
+ host,
41
+ api_version,
42
+ normalized_resource_name,
43
+ @id
44
+ ].compact.join("/")
45
+ url = remove_duplicated_slashes(url)
46
+ [url, query_string].compact.join("?")
47
+ end
48
+
49
+ private
50
+
51
+ def api_version
52
+ Apisync::HttpClient::VERSION_PREFIX
53
+ end
54
+
55
+ def host
56
+ @options[:host] || DEFAULT_HOST
57
+ end
58
+
59
+ def query_string
60
+ str = Apisync::Http::QueryString.new(filters: @filters).to_s
61
+ str if str != ""
62
+ end
63
+
64
+ def normalized_resource_name
65
+ @resource_name.to_s.downcase.gsub("_", "-")
66
+ end
67
+
68
+ def remove_duplicated_slashes(string)
69
+ string.gsub(/([^:])\/\//, '\1/')
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,74 @@
1
+ class Apisync
2
+ class HttpClient
3
+ VERSION_PREFIX = "".freeze
4
+
5
+ HEADER = {
6
+ "Content-Type" => "application/vnd.api+json",
7
+ "Accept" => "application/vnd.api+json"
8
+ }.freeze
9
+
10
+ def self.post(resource_name:, data:, options: {})
11
+ url = Apisync::Http::Url.new(
12
+ resource_name: resource_name,
13
+ options: options
14
+ )
15
+ payload = payload_from_data(data)
16
+ HTTParty.post(
17
+ url.to_s,
18
+ body: {data: payload}.to_json,
19
+ headers: header(api_key: options[:api_key])
20
+ )
21
+ end
22
+
23
+ def self.put(resource_name:, id:, data:, options: {})
24
+ raise Apisync::UrlAndPayloadIdMismatch unless id == data[:id]
25
+
26
+ url = Apisync::Http::Url.new(
27
+ resource_name: resource_name,
28
+ id: id,
29
+ options: options
30
+ )
31
+ payload = payload_from_data(data)
32
+ HTTParty.put(
33
+ url.to_s,
34
+ body: {data: payload}.to_json,
35
+ headers: header(api_key: options[:api_key])
36
+ )
37
+ end
38
+
39
+ def self.get(resource_name:, id: nil, filters: nil, options: {})
40
+ raise Apisync::InvalidFilter if !filters.nil? && !filters.is_a?(Hash)
41
+
42
+ url = Apisync::Http::Url.new(
43
+ resource_name: resource_name,
44
+ id: id,
45
+ filters: filters,
46
+ options: options
47
+ )
48
+ HTTParty.get(url.to_s, headers: header(api_key: options[:api_key]))
49
+ end
50
+
51
+ private
52
+
53
+ def self.header(api_key: nil)
54
+ final = HEADER
55
+ if api_key
56
+ final = final.merge("Authorization" => "ApiToken #{api_key}")
57
+ end
58
+ final
59
+ end
60
+
61
+ def self.payload_from_data(data)
62
+ transformed_payload = {}
63
+ data.each do |key, value|
64
+ if value.is_a?(Hash)
65
+ transformed_payload[key.to_s] = payload_from_data(value)
66
+ else
67
+ new_key = key.to_s.gsub("_", "-").to_sym
68
+ transformed_payload[new_key] = value
69
+ end
70
+ end
71
+ transformed_payload
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,67 @@
1
+ class Apisync
2
+ class Resource
3
+ def initialize(name, options = {})
4
+ @name = name
5
+ @options = options
6
+ end
7
+
8
+ # Saves a resource.
9
+ #
10
+ # When the resource has an id in `data`, a `PUT` request is done. Otherwise
11
+ # a `POST` takes place.
12
+ #
13
+ def save(data)
14
+ data[:type] = @name.to_s.gsub("_", "-")
15
+ if data[:id].nil?
16
+ post(data)
17
+ else
18
+ put(data)
19
+ end
20
+ end
21
+
22
+ # Returns all resources that match the conditions passed in.
23
+ #
24
+ # 1. To find a resource by its id:
25
+ #
26
+ # get(id: 'customer-id')
27
+ #
28
+ # 2. To find a resource by a column value
29
+ #
30
+ # get(filters: {column_name: 'customer-id' }})
31
+ #
32
+ def get(conditions)
33
+ http_client.get(
34
+ resource_name: @name,
35
+ id: conditions[:id],
36
+ filters: conditions[:filters],
37
+ options: @options
38
+ )
39
+ end
40
+
41
+ private
42
+
43
+
44
+ def post(data)
45
+ http_client.post(
46
+ resource_name: @name,
47
+ data: data,
48
+ options: @options
49
+ )
50
+ end
51
+
52
+ def put(data)
53
+ http_client.put(
54
+ resource_name: @name,
55
+ id: data[:id],
56
+ data: data,
57
+ options: @options
58
+ )
59
+ end
60
+
61
+ private
62
+
63
+ def http_client
64
+ Apisync::HttpClient
65
+ end
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
- module Apisync
2
- VERSION = "0.1.0"
1
+ class Apisync
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apisync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre de Oliveira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-10 00:00:00.000000000 Z
11
+ date: 2017-10-10 00:00:00.000000000 Z
12
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.13'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.13'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,9 +66,37 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  description:
56
98
  email:
57
- - alex@veiculo.online
99
+ - chavedomundo@gmail.com
58
100
  executables:
59
101
  - console
60
102
  - setup
@@ -72,6 +114,11 @@ files:
72
114
  - bin/console
73
115
  - bin/setup
74
116
  - lib/apisync.rb
117
+ - lib/apisync/exceptions.rb
118
+ - lib/apisync/http/query_string.rb
119
+ - lib/apisync/http/url.rb
120
+ - lib/apisync/http_client.rb
121
+ - lib/apisync/resource.rb
75
122
  - lib/apisync/version.rb
76
123
  homepage: https://github.com/apisync/apisync-ruby
77
124
  licenses: