apisync 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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: