sk_api_schema 0.0.1 → 0.0.2

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -68,7 +68,6 @@
68
68
  "description": "Geolocation longitude",
69
69
  "optional":true,
70
70
  "type":"string"
71
- },
72
-
71
+ }
73
72
  }
74
73
  }
@@ -0,0 +1,59 @@
1
+ { "type":"object",
2
+ "title": "attachment",
3
+ "description":"An file attachment",
4
+ "properties": {
5
+ "id": {
6
+ "description": "uuid of the object.",
7
+ "identity":true,
8
+ "readonly":true,
9
+ "type":"string"
10
+ },
11
+ "filename": {
12
+ "description": "The filename as set when uploaded",
13
+ "optional":true,
14
+ "readonly":true,
15
+ "type":"string"
16
+ },
17
+ "disk_filename": {
18
+ "description": "The filename as set by SK",
19
+ "optional":true,
20
+ "readonly":true,
21
+ "type":"string"
22
+ },
23
+ "url": {
24
+ "description": "File download url. Unique and valid for 15 minutes, public accessible.",
25
+ "optional":true,
26
+ "readonly":true,
27
+ "type":"string"
28
+ },
29
+ "content_type": {
30
+ "description": "Auto detected on upload. Might not always reflect the real content type",
31
+ "optional":true,
32
+ "readonly":true,
33
+ "type":"string"
34
+ },
35
+ "size": {
36
+ "description": "Filesize in kb. Auto detected on upload.",
37
+ "optional":true,
38
+ "readonly":true,
39
+ "type":"integer"
40
+ },
41
+ "is_signed": {
42
+ "description": "True if the file(pdf) has been digitally signed.",
43
+ "optional":true,
44
+ "type":"boolean"
45
+ },
46
+ "created_at": {
47
+ "description": "Date the object was created in SK. Never changes aftwerwards",
48
+ "format":"date-time",
49
+ "readonly":true, "type":"string"
50
+ },
51
+ "updated_at": {
52
+ "description": "Date the object was edited in SK.",
53
+ "format":"date-time",
54
+ "readonly":true,
55
+ "type":"string"
56
+ }
57
+
58
+ }
59
+ }
@@ -76,6 +76,13 @@
76
76
  "type":"object",
77
77
  "properties":{"$ref":"./client.json#properties"}
78
78
  },
79
+ "archived_pdf":{
80
+ "description": "Archived PDF version of the document. Is created when an document is printed and archived. A document can have multiple archived versions. This only returns the most recent one. ",
81
+ "optional":true,
82
+ "readonly":true,
83
+ "type":"object",
84
+ "properties":{"$ref":"./attachment.json#properties"}
85
+ },
79
86
  "client_id":{
80
87
  "description": "The clients uuid, must be set for a new document. New invoices take the clients address field, due days and cash discount if those fields are not set.",
81
88
  "type":"string"
data/lib/sk_api_schema.rb CHANGED
@@ -1 +1,65 @@
1
- require 'activesupport'
1
+ require 'activesupport'
2
+
3
+ module SK
4
+ module Api
5
+ class Schema
6
+
7
+ # Read a schema with a given version and return it as hash
8
+ # See ../json folder for available schema's and versions
9
+ # === Parameter
10
+ # schema<String|Symbol>::name of the schema, available ones are in json directory
11
+ # version<String>:: version to read, this is the folder name where the schema is in.
12
+ def self.read(schema, version)
13
+ file_path = File.join(File.dirname(__FILE__), '../json', version, "#{schema}.json")
14
+ plain_data = File.open(file_path, 'r'){|f| f.read}
15
+ ActiveSupport::JSON.decode(plain_data)
16
+ end
17
+
18
+ # Create a Hash with the available (api)object attributes defined in
19
+ # schema properties.
20
+ #
21
+ # === Example
22
+ # obj = Invoice.new(:title =>'hello world', :number=>'4711')
23
+ # obj_hash = Sk::Api::Schema.to_hash_from_schema(obj, 'v1.0')
24
+ #
25
+ # obj_hash => { invoice =>{'title'=>'hello world', 'number'=>'4711' } }
26
+ #
27
+ # === Parameter
28
+ # obj<Object>:. An ruby object which is returned as hash
29
+ # version<String>:. An ruby object which is returned as hash
30
+ # === Return
31
+ # <Hash{String=>{String=>Mixed}}>:: The object as hash:
32
+ # { invoice =>{'title'=>'hello world', 'number'=>''4711 } }
33
+ def self.to_hash_from_schema(obj, version)
34
+ # get objects class name without inheritance
35
+ obj_class_name = obj.class.name.split('::').last.underscore
36
+ # init data hash
37
+ data = {}
38
+ # get schema
39
+ schema = self.read(obj_class_name, version)
40
+ # iterate over the defined schema fields
41
+ schema['properties'].each do |field, prop|
42
+ if prop['type'] == 'array'
43
+ # always set an empty array
44
+ data[field] = []
45
+ if rel_objects = obj.send( field )
46
+ rel_objects.each do |rel_obj|
47
+ # call related objects to_hash_from_schema method ex: data[:client][:addresses] << SKApi::Models::Address.to_hash_from_schema(object)
48
+ data[field] << self.to_hash_from_schema(rel_obj, version)
49
+ end
50
+ end
51
+ elsif prop['type'] == 'object' # a singular related object
52
+ data[field] = nil
53
+ if rel_obj = obj.send( field )
54
+ data[field] = self.to_hash_from_schema(rel_obj, version)
55
+ end
56
+ else # a simple field is only added if objects know its
57
+ data[field] = obj.send(field) if obj.respond_to?(field.to_sym)
58
+ end
59
+ end
60
+ { obj_class_name => data }
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sk_api_schema}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Georg Leciejewski"]
12
- s.date = %q{2010-11-08}
12
+ s.date = %q{2010-11-11}
13
13
  s.description = %q{SalesKing API JSON schema and utility methods}
14
14
  s.email = %q{gl@salesking.eu}
15
15
  s.extra_rdoc_files = [
@@ -21,15 +21,15 @@ Gem::Specification.new do |s|
21
21
  "Rakefile",
22
22
  "VERSION",
23
23
  "json/v1.0/address.json",
24
+ "json/v1.0/attachment.json",
24
25
  "json/v1.0/client.json",
25
26
  "json/v1.0/credit_note.json",
26
27
  "json/v1.0/invoice.json",
27
28
  "json/v1.0/line_item.json",
28
29
  "lib/sk_api_schema.rb",
29
- "lib/utils/serializer.rb",
30
30
  "sk_api_schema.gemspec",
31
- "spec/spec_helper.rb",
32
- "spec/utils/field_map_spec.rb"
31
+ "spec/sk_api_schema_spec.rb",
32
+ "spec/spec_helper.rb"
33
33
  ]
34
34
  s.homepage = %q{http://github.com/salesking/sk_api_schema}
35
35
  s.rdoc_options = ["--charset=UTF-8"]
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
38
38
  s.summary = %q{SalesKing API JSON Schema}
39
39
  s.test_files = [
40
40
  "spec/spec_helper.rb",
41
- "spec/utils/field_map_spec.rb"
41
+ "spec/sk_api_schema_spec.rb"
42
42
  ]
43
43
 
44
44
  if s.respond_to? :specification_version then
@@ -0,0 +1,76 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe SK::Api::Schema do
4
+
5
+ it "should read json schema file" do
6
+ schema = SK::Api::Schema.read(:invoice, 'v1.0')
7
+ schema['title'].should == 'invoice'
8
+ schema['type'].should == 'object'
9
+ schema['properties'].should be_a Hash
10
+ schema['properties']['id']['identity'].should be_true
11
+ end
12
+
13
+ it "should raise error if version folder does not exist" do
14
+ lambda{
15
+ SK::Api::Schema.read(:invoice, 'v3.0')
16
+ }.should raise_error
17
+ end
18
+
19
+ it "should raise error if schema file does not exist" do
20
+ lambda{
21
+ SK::Api::Schema.read(:nope, 'v1.0')
22
+ }.should raise_error
23
+ end
24
+
25
+ end
26
+
27
+ describe SK::Api::Schema, 'object parsing' do
28
+
29
+ before :each do
30
+ @invoice = Invoice.new
31
+ @invoice.id = 'some-uuid'
32
+ @invoice.title = 'Your Invoice'
33
+ @invoice.number = '911'
34
+
35
+ @client = Client.new
36
+ @client.id = 'some-uuid'
37
+ @client.organisation = 'Dirty Food Inc.'
38
+ @client.number = '911'
39
+
40
+ @item = LineItem.new
41
+ @item.id = 'some-uuid'
42
+ @item.name = 'Pork Chops'
43
+ @item.description = 'Yummi Pork chopped by mexian emigrants'
44
+ @item.position = 1
45
+ @item.price_single = 0.99
46
+ end
47
+
48
+
49
+ it "should parse object without relations from schema" do
50
+ obj_hash = SK::Api::Schema.to_hash_from_schema(@invoice, 'v1.0')
51
+ obj_hash.should == {"invoice"=>{"number"=>"911", "line_items"=>[], "title"=>"Your Invoice", "id"=>"some-uuid", "date"=>nil, "client"=>nil, "due_date"=>nil}}
52
+ client_obj_hash = SK::Api::Schema.to_hash_from_schema(@client, 'v1.0')
53
+ client_obj_hash.should == {"client"=>{"number"=>"911", "addresses"=>[], "id"=>"some-uuid", "organisation"=>"Dirty Food Inc.", "last_name"=>nil}}
54
+ end
55
+
56
+ it "should parse object with relations from schema" do
57
+ @invoice.line_items = [@item]
58
+ @invoice.client = @client
59
+ obj_hash = SK::Api::Schema.to_hash_from_schema(@invoice, 'v1.0')
60
+ obj_hash.should == {"invoice"=>{"number"=>"911", "line_items"=>[{"line_item"=>{"position"=>1, "name"=>"Pork Chops", "id"=>"some-uuid", "description"=>"Yummi Pork chopped by mexian emigrants", "price_single"=>0.99}}], "title"=>"Your Invoice", "id"=>"some-uuid", "date"=>nil, "client"=>{"client"=>{"number"=>"911", "addresses"=>[], "id"=>"some-uuid", "organisation"=>"Dirty Food Inc.", "last_name"=>nil}}, "due_date"=>nil}}
61
+ end
62
+
63
+ end
64
+
65
+ ################################################################################
66
+ # virtual classes used in test
67
+ class Invoice
68
+ attr_accessor :id, :title, :description, :number, :date, :due_date, :line_items, :client
69
+ end
70
+
71
+ class LineItem
72
+ attr_accessor :id, :name, :description, :position, :price_single
73
+ end
74
+ class Client
75
+ attr_accessor :id, :organisation, :last_name, :number, :addresses
76
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  require 'rubygems'
2
2
  require 'spec'
3
- #require "#{File.dirname(__FILE__)}/../lib/sk_api"
3
+ require "#{File.dirname(__FILE__)}/../lib/sk_api_schema"
4
4
  #require File.dirname(__FILE__) + '/../vendor/jsonschema-1.0.0/lib/jsonschema'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sk_api_schema
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Georg Leciejewski
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-08 00:00:00 +01:00
18
+ date: 2010-11-11 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -60,15 +60,15 @@ files:
60
60
  - Rakefile
61
61
  - VERSION
62
62
  - json/v1.0/address.json
63
+ - json/v1.0/attachment.json
63
64
  - json/v1.0/client.json
64
65
  - json/v1.0/credit_note.json
65
66
  - json/v1.0/invoice.json
66
67
  - json/v1.0/line_item.json
67
68
  - lib/sk_api_schema.rb
68
- - lib/utils/serializer.rb
69
69
  - sk_api_schema.gemspec
70
+ - spec/sk_api_schema_spec.rb
70
71
  - spec/spec_helper.rb
71
- - spec/utils/field_map_spec.rb
72
72
  has_rdoc: true
73
73
  homepage: http://github.com/salesking/sk_api_schema
74
74
  licenses: []
@@ -105,4 +105,4 @@ specification_version: 3
105
105
  summary: SalesKing API JSON Schema
106
106
  test_files:
107
107
  - spec/spec_helper.rb
108
- - spec/utils/field_map_spec.rb
108
+ - spec/sk_api_schema_spec.rb
@@ -1,66 +0,0 @@
1
- module SKApi
2
- module Utils
3
- # Mixed into Resources::Base providing to_hash and to_json serialisation for
4
- # SKApi Resources.
5
- # Inside SalesKing this serialising is used to render the output.
6
- # f.ex. in the clients api controller
7
- # => SKApi::Resources::Client.to_json(a_client)
8
- # This way you can keep your API client up to date by using the resources and
9
- # relying on SKApi::Resources::Client.schema
10
- module Serializer
11
- def self.included(base)
12
- base.extend ClassMethods
13
- end
14
-
15
- module ClassMethods
16
-
17
- def schema_to_hash
18
-
19
- end
20
-
21
- # Create a Hash with the available (api)object attributes defined in api_fields.
22
- #
23
- # ==== Parameter
24
- # obj<object>:. An ruby object which is returned as hash
25
- def to_hash_from_schema(obj)
26
- # first set the root node to the objects class name as symbol
27
- obj_class_name = obj.class.name.split('::').last.underscore
28
- # obj_class_name = obj.class.to_s.underscore.to_sym
29
- data = { obj_class_name => {} }
30
- # iterate over the defined api fields hash
31
- self.schema_props.each do |field, props|
32
- if props['type'] == 'array'
33
- # always set the field, so the user can expect an empty array
34
- data[obj_class_name][field] = []
35
- if rel_objects = obj.send( field )
36
- rel_objects.each do |rel_obj|
37
- # setup scope for related class
38
- klass = "SKApi::Resources::#{rel_obj.class}".constantize
39
- # call related objects to_hash_from_schema method ex: data[:client][:addresses] << SKApi::Models::Address.to_hash_from_schema(object)
40
- data[obj_class_name][field] << klass.to_hash_from_schema(rel_obj)
41
- end
42
- end
43
- elsif props['type'] == 'object' # a singular resource TODO should we add an empty object?
44
- if rel_obj = obj.send( field )
45
- klass = "SKApi::Resources::#{rel_obj.class}".constantize
46
- # ex: data['invoice']['client'] = SKApi::Models::Client.to_hash_from_schema(client)
47
- data[obj_class_name][field] = klass.to_hash_from_schema(rel_obj)
48
- end
49
- else # a simple field which can be directly called, only added of objects know its
50
- data[obj_class_name][field] = obj.send(field) if obj.respond_to?(field.to_sym)
51
- end
52
- end
53
- data
54
- end
55
-
56
- def to_json(obj)
57
- data = self.to_hash_from_schema(obj)
58
- # data[:links] = self.api_links
59
- ActiveSupport::JSON.encode(data)
60
- end
61
-
62
- end #ClassMethods
63
-
64
- end #mixin
65
- end #utils
66
- end #SKApi
@@ -1,73 +0,0 @@
1
- require 'spec/spec_helper'
2
-
3
- describe SKApi::Utils::FieldMap do
4
-
5
- before :each do
6
- @loc_obj = LocalContact.new
7
- @rem_obj = RemoteContact.new()
8
- @map = SKApi::Utils::FieldMap.new(@loc_obj, @rem_obj, map_hash)
9
- end
10
-
11
- it "should create a mapping" do
12
- @map.outdated?.should be_false # both objects are empty
13
- end
14
-
15
- it "should find outdated fields" do
16
- @loc_obj.firstname = 'theo'
17
- @map.outdated?.should be_true
18
- @map.outdated.first[:loc_key].should == :firstname
19
- end
20
-
21
- it "should update outdated remote fields" do
22
- @loc_obj.firstname = 'theo'
23
- @map.update_remote_outdated
24
- @rem_obj.first_name.should == @loc_obj.firstname
25
- # test logging
26
- @map.log.should_not be_empty
27
- end
28
-
29
- it "should update outdated local fields" do
30
- @rem_obj.first_name = 'Heinz'
31
- @map.update_local_outdated
32
- @rem_obj.first_name.should == @loc_obj.firstname
33
- @map.log.length.should == 1
34
- end
35
- # it "should update outdated local fields" do
36
- # @rem_obj.first_name = 'Heinz'
37
- # @map.outdated?
38
- # @map.update_local_outdated
39
- # @rem_obj.first_name.should == @loc_obj.firstname
40
- # end
41
-
42
- def map_hash
43
- [
44
- {:loc_key => :firstname, :rem_key => :first_name},
45
- {:loc_key => :street, :rem_key => :address1},
46
- {:loc_key => :postcode, :rem_key => :zip},
47
- {:loc_key => :city, :rem_key => :city},
48
- {:loc_key => :gender, :rem_key => :gender, :trans => { :obj=>'TransferFunctions',
49
- :loc_trans => 'set_local_gender',
50
- :rem_trans => 'set_remote_gender'}
51
- }
52
- ]
53
- end
54
-
55
- end
56
-
57
- class RemoteContact
58
- attr_accessor :first_name, :address1, :zip, :city, :gender
59
- end
60
- class LocalContact
61
- attr_accessor :firstname, :street, :postcode, :city, :gender
62
- end
63
-
64
- class TransferFunctions
65
- def self.set_local_gender(remote_val)
66
- return 'male' if remote_val == 'm'
67
- return 'female' if remote_val == 'f'
68
- end
69
- def self.set_remote_gender(local_val)
70
- return 'm' if local_val == 'male'
71
- return 'f' if local_val == 'female'
72
- end
73
- end