elibri_api_client 1.0.3 → 1.0.4

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/Gemfile CHANGED
@@ -2,6 +2,7 @@ source "http://rubygems.org"
2
2
 
3
3
  gem "httparty", "~> 0.7.8"
4
4
  gem "nokogiri", "~> 1.5.0"
5
+ gem 'activesupport', '>= 3.1.0.rc1'
5
6
 
6
7
  group :development do
7
8
  gem "ruby-debug"
data/Gemfile.lock CHANGED
@@ -1,6 +1,8 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activesupport (3.1.0.rc1)
5
+ multi_json (~> 1.0)
4
6
  columnize (0.3.3)
5
7
  crack (0.1.8)
6
8
  git (1.2.5)
@@ -14,6 +16,7 @@ GEM
14
16
  rbx-require-relative (> 0.0.4)
15
17
  minitest (2.2.2)
16
18
  mocha (0.9.12)
19
+ multi_json (1.0.3)
17
20
  nokogiri (1.5.0)
18
21
  rake (0.9.0)
19
22
  rbx-require-relative (0.0.5)
@@ -28,6 +31,7 @@ PLATFORMS
28
31
  ruby
29
32
 
30
33
  DEPENDENCIES
34
+ activesupport (>= 3.1.0.rc1)
31
35
  bundler (~> 1.0.0)
32
36
  httparty (~> 0.7.8)
33
37
  jeweler (~> 1.6.2)
data/README.rdoc CHANGED
@@ -1,20 +1,49 @@
1
- = elibri_api_client
1
+ = Klient API serwisu elibri.com.pl
2
2
 
3
- require 'elibri_api_client'
4
- cli = Elibri::ApiClient.new(:host_uri => 'http://localhost:3010', :login => '1b20fa9d72234423979c', :password => '2847cbf4f15a4057e2ab')
3
+ === 0. Gemfile dla Bundlera
4
+ gem 'elibri_api_client'
5
+
6
+ === 1. Tworzymy instancje klienta
7
+ elibri = Elibri::ApiClient.new(:login => '1b20fa9d72234423979c', :password => '2847cbf4f15a4057e2ab')
5
8
 
6
- cli.refill_all_queues!
7
- cli.pending_data?
8
- cli.last_pickups
9
+ === 2. Przegladanie dostepnych danych
10
+
11
+ elibri.publishers.each do |publisher|
12
+ puts "#{publisher.name}, #{publisher.city} (#{publisher.products_count} produktow)"
13
+ publisher.products.each_with_index do |product, product_no|
14
+ puts "\t#{product_no}. #{product.main_title}"
15
+ # puts product.onix_xml
16
+ end
17
+ end
18
+
9
19
 
10
- cli.pending_queues.each do |pending_queue|
20
+
21
+ === 3. Operacje na kolejkach zmian
22
+
23
+ ==== 3a. Pobieranie ostatnio zmienionych produktow w Elibri
24
+
25
+ # Wypelnij wszystkie kolejki oczekujace, wszystkimi dostepnymi danymi.
26
+ # Przydatne przy wykonywaniu pelnej synchronizacji pomiedzy nasza aplikacja a Elibri.
27
+ # Inna mozliwosc to iteracja elibri.publishers i sekwencyjne pobieranie danych kolejnych
28
+ # produktow (moze byc wolniejsze od kolejek zmian).
29
+ # elibri.refill_all_queues!
30
+
31
+ elibri.pending_queues.each do |pending_queue|
32
+ # Aby moc pobierac dane, musimy kolejke oczekujaca przekonwertowac na kolejke nazwana.
33
+ # Taka kolejke identyfikujemy po ID i jej tresc pozniej nie ulega zmianie.
11
34
  named_queue = pending_queue.pick_up!
12
35
 
13
- named_queue.each_product do |product_xml, product_no|
14
- # [...]
36
+ # Majac kolejke nazwana, mozemy iterowac po jej produktach (ONIX):
37
+ named_queue.each_product_onix do |product_xml, product_no|
38
+ # Otrzymujemy przeparsowany XML za pomoca Nokogiri
39
+ # product_xml.class => Nokogiri::XML::Element
40
+
41
+ puts product.xml.css('RecordReference')
15
42
  end
16
43
  end
17
44
 
45
+ ==== 3b. Znadz ostatnio pobrane kolejki
46
+ named_queue = elibri.last_pickups.first
18
47
 
19
48
 
20
49
  == Copyright
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{elibri_api_client}
8
- s.version = "1.0.3"
8
+ s.version = "1.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Marcin Urba\305\204ski"]
12
- s.date = %q{2011-07-06}
12
+ s.date = %q{2011-07-13}
13
13
  s.description = %q{API client for elibri.com.pl publishing system}
14
14
  s.email = %q{marcin@urbanski.vdl.pl}
15
15
  s.extra_rdoc_files = [
@@ -31,6 +31,8 @@ Gem::Specification.new do |s|
31
31
  "lib/elibri_api_client/core_extensions.rb",
32
32
  "lib/elibri_api_client/version.rb",
33
33
  "test/elibri_api_client_test.rb",
34
+ "test/elibri_api_v1_adapter_product_test.rb",
35
+ "test/elibri_api_v1_adapter_publisher_test.rb",
34
36
  "test/elibri_api_v1_adapter_queue_test.rb",
35
37
  "test/elibri_api_v1_adapter_test.rb",
36
38
  "test/helper.rb"
@@ -47,6 +49,7 @@ Gem::Specification.new do |s|
47
49
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
50
  s.add_runtime_dependency(%q<httparty>, ["~> 0.7.8"])
49
51
  s.add_runtime_dependency(%q<nokogiri>, ["~> 1.5.0"])
52
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.1.0.rc1"])
50
53
  s.add_development_dependency(%q<ruby-debug>, [">= 0"])
51
54
  s.add_development_dependency(%q<mocha>, [">= 0"])
52
55
  s.add_development_dependency(%q<minitest>, [">= 0"])
@@ -56,6 +59,7 @@ Gem::Specification.new do |s|
56
59
  else
57
60
  s.add_dependency(%q<httparty>, ["~> 0.7.8"])
58
61
  s.add_dependency(%q<nokogiri>, ["~> 1.5.0"])
62
+ s.add_dependency(%q<activesupport>, [">= 3.1.0.rc1"])
59
63
  s.add_dependency(%q<ruby-debug>, [">= 0"])
60
64
  s.add_dependency(%q<mocha>, [">= 0"])
61
65
  s.add_dependency(%q<minitest>, [">= 0"])
@@ -66,6 +70,7 @@ Gem::Specification.new do |s|
66
70
  else
67
71
  s.add_dependency(%q<httparty>, ["~> 0.7.8"])
68
72
  s.add_dependency(%q<nokogiri>, ["~> 1.5.0"])
73
+ s.add_dependency(%q<activesupport>, [">= 3.1.0.rc1"])
69
74
  s.add_dependency(%q<ruby-debug>, [">= 0"])
70
75
  s.add_dependency(%q<mocha>, [">= 0"])
71
76
  s.add_dependency(%q<minitest>, [">= 0"])
@@ -3,19 +3,31 @@ require 'time'
3
3
  require 'httparty'
4
4
  require 'nokogiri'
5
5
  require 'forwardable'
6
+ require 'active_support/core_ext/object/blank'
7
+ require 'active_support/core_ext/hash/keys'
6
8
  require 'elibri_api_client/core_extensions'
7
9
  require 'elibri_api_client/version'
8
10
  require 'elibri_api_client/api_adapters'
9
11
 
10
12
  module Elibri
13
+
14
+ # Klient API, hermetyzujacy magie polaczen i parsowania XML`a. Na jego instancji mozna wykonac wszystkie metody
15
+ # instancji Elibri::ApiClient::ApiAdapters::V1.
11
16
  class ApiClient
12
17
  extend Forwardable
13
18
 
19
+ # Domyslny adres serwera API
14
20
  DEFAULT_API_HOST_URI = 'http://api.elibri.com.pl:80'
21
+ # Adres hosta, pod ktorym figuruje serwer API - domyslnie to DEFAULT_API_HOST_URI
15
22
  attr_reader :host_uri
16
23
 
17
24
 
25
+ # cli = Elibri::ApiClient.new(:login => '1b20fa9d72234423979c', :password => '2847cbf4f15a4057e2ab')
26
+ #
27
+ # Opcjonalnie mozna podac adres servera API:
28
+ # cli = Elibri::ApiClient.new(:host_uri => 'http://localhost:3010', :login => '1b20fa9d72234423979c', :password => '2847cbf4f15a4057e2ab')
18
29
  def initialize(options = {})
30
+ options.assert_valid_keys(:login, :password, :host_uri, :api_version)
19
31
  @login = options[:login]
20
32
  @password = options[:password]
21
33
  @host_uri = options[:host_uri] || DEFAULT_API_HOST_URI
@@ -28,8 +40,7 @@ module Elibri
28
40
 
29
41
 
30
42
  # Metody API delegujemy do odpowiedniego adaptera:
31
- def_delegators :@api_adapter,
32
- :refill_all_queues!, :pending_data?, :pending_queues, :pick_up_queue!, :last_pickups, :each_product, :each_page
43
+ def_delegators :@api_adapter, :refill_all_queues!, :pending_data?, :pending_queues, :last_pickups, :publishers
33
44
 
34
45
  end
35
46
  end
@@ -10,9 +10,11 @@ module Elibri
10
10
  URI_PREFIX = '/api/v1'
11
11
 
12
12
  include HTTParty
13
+ #--
13
14
  #debug_output $stderr
15
+ #++
14
16
 
15
- def initialize(host_uri, login, password)
17
+ def initialize(host_uri, login, password) #:nodoc:
16
18
  @host_uri = host_uri
17
19
  @auth = {:username => login, :password => password}
18
20
  end
@@ -20,35 +22,80 @@ module Elibri
20
22
 
21
23
  # Wypelnij wszystkie kolejki oczekujace, wszystkimi dostepnymi danymi. Przydatne przy wykonywaniu
22
24
  # pelnej synchronizacji pomiedzy nasza aplikacja a Elibri.
25
+ # call-seq:
26
+ # refill_all_queues! -> true
27
+ #
23
28
  def refill_all_queues!
24
29
  # Dla POST musi byc jakies 'body' requestu, bo serwery czesto rzucaja wyjatkami (WEBrick w szczegolnosci).
25
30
  post '/queues/refill_all', :body => ' '
31
+ true
26
32
  end
27
33
 
28
34
 
29
- # Zwroc liste kolejek z oczekujacymi danymi.
35
+ # Zwroc liste kolejek z oczekujacymi danymi - instancje Elibri::ApiClient::ApiAdapters::V1::Queue
36
+ # call-seq:
37
+ # pending_queues -> array
38
+ #
30
39
  def pending_queues
31
40
  resp = get '/queues/pending_data'
32
41
 
33
- pending_queues = []
34
- resp.parsed_response.css('queue').each do |queue_xml|
35
- queue = Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(self, queue_xml)
36
- pending_queues << queue if queue.items_total.nonzero?
37
- end
38
- pending_queues
42
+ Array.new.tap do |pending_queues|
43
+ resp.parsed_response.css('queue').each do |queue_xml|
44
+ queue = Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(self, queue_xml)
45
+ pending_queues << queue if queue.products_count.nonzero?
46
+ end
47
+ end
39
48
  end
40
49
 
41
50
 
42
51
  # Czy sa jakies oczekujace dane w Elibri?
52
+ # call-seq:
53
+ # pending_data? -> true or false
54
+ #
43
55
  def pending_data?
44
56
  !pending_queues.empty?
45
57
  end
46
58
 
47
59
 
60
+ # Ostatnio utworzone nazwane kolejki. Gdy wysypie nam sie aplikacja, mozna przegladac ostatnie pickupy
61
+ # i ponownie pobierac z nich dane. Zwraca instance Elibri::ApiClient::ApiAdapters::V1::Queue
62
+ # call-seq:
63
+ # last_pickups -> array
64
+ #
65
+ def last_pickups
66
+ Array.new.tap do |last_pickups|
67
+ %w{meta stocks}.each do |queue_name|
68
+ begin
69
+ response = get "/queues/#{queue_name}/last_pick_up"
70
+ queue_xml = response.parsed_response.css('queue').first
71
+ last_pickups << Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(self, queue_xml)
72
+ rescue Exceptions::NoRecentlyPickedUpQueues # Ignoruj bledy o braku ostatnich pickupow.
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+
79
+ # Zwroc liste dostepnych wydawnictw - instancje Elibri::ApiClient::ApiAdapters::V1::Publisher
80
+ # call-seq:
81
+ # publishers -> array
82
+ #
83
+ def publishers
84
+ resp = get '/publishers'
85
+
86
+ Array.new.tap do |publishers|
87
+ resp.parsed_response.css('publisher').each do |publisher_xml|
88
+ publisher = Elibri::ApiClient::ApiAdapters::V1::Publisher.build_from_xml(self, publisher_xml)
89
+ publishers << publisher
90
+ end
91
+ end
92
+ end
93
+
94
+
48
95
  # Utworz z danych oczekujacych w kolejce np. 'pending_meta', kolejke nazwana.
49
96
  # Tylko z kolejek nazwanych mozna pobierac dane. Jako argument przyjmuje nazwe kolejki (np. 'pending_meta')
50
97
  # lub odpowiednia instancje Elibri::ApiClient::ApiAdapters::V1::Queue.
51
- def pick_up_queue!(queue)
98
+ def pick_up_queue!(queue) #:nodoc:
52
99
  case queue
53
100
  when Elibri::ApiClient::ApiAdapters::V1::Queue
54
101
  queue_name = queue.name
@@ -64,7 +111,7 @@ module Elibri
64
111
  end
65
112
 
66
113
 
67
- def each_page(queue, &block)
114
+ def each_page_in_queue(queue, &block) #:nodoc:
68
115
  raise 'Need a Elibri::ApiClient::ApiAdapters::V1::Queue instance' unless queue.kind_of? Elibri::ApiClient::ApiAdapters::V1::Queue
69
116
 
70
117
  page_no = 1
@@ -80,11 +127,11 @@ module Elibri
80
127
 
81
128
  # Trawersuj kolekcje produktow w nazwanej kolejce. Instancje nazwanej kolejki nalezy przekazac
82
129
  # jako argument metody.
83
- def each_product(queue, &block)
130
+ def each_product_onix_in_queue(queue, &block) #:nodoc:
84
131
  raise 'Need a Elibri::ApiClient::ApiAdapters::V1::Queue instance' unless queue.kind_of? Elibri::ApiClient::ApiAdapters::V1::Queue
85
132
 
86
133
  product_no = 1
87
- each_page(queue) do |products_page_xml, page_no|
134
+ each_page_in_queue(queue) do |products_page_xml, page_no|
88
135
  products_page_xml.css('Product').each do |product_xml|
89
136
  block.call(product_xml, product_no)
90
137
  product_no += 1
@@ -93,20 +140,25 @@ module Elibri
93
140
  end
94
141
 
95
142
 
96
- # Ostatnio utworzone nazwane kolejki. Gdy wysypie nam sie aplikacja, mozna przegladac ostatnie pickupy
97
- # i ponownie pobierac z nich dane.
98
- def last_pickups
99
- last_pickups = []
100
- %w{meta stocks}.each do |queue_name|
101
- begin
102
- response = get "/queues/#{queue_name}/last_pick_up"
103
- queue_xml = response.parsed_response.css('queue').first
104
- last_pickups << Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(self, queue_xml)
105
- rescue NoRecentlyPickedUpQueues # Ignoruj bledy o braku ostatnich pickupow.
106
- end
107
- end
108
-
109
- last_pickups
143
+ # Zwroc liste produktow dla podanego wydawnictwa.
144
+ def products_for_publisher(publisher) #:nodoc:
145
+ raise 'Need a Elibri::ApiClient::ApiAdapters::V1::Publisher instance' unless publisher.kind_of? Elibri::ApiClient::ApiAdapters::V1::Publisher
146
+ resp = get "/publishers/#{publisher.publisher_id}/products"
147
+
148
+ Array.new.tap do |products|
149
+ resp.parsed_response.css('product').each do |product_xml|
150
+ product = Elibri::ApiClient::ApiAdapters::V1::Product.build_from_xml(self, publisher, product_xml)
151
+ products << product
152
+ end
153
+ end
154
+ end
155
+
156
+
157
+ # Zwroc ONIX dla konkretnego produktu.
158
+ def onix_xml_for_product(product) #:nodoc:
159
+ raise 'Need a Elibri::ApiClient::ApiAdapters::V1::Product instance' unless product.kind_of? Elibri::ApiClient::ApiAdapters::V1::Product
160
+ resp = get "/products/#{product.record_reference}"
161
+ resp.parsed_response.css('Product').first
110
162
  end
111
163
 
112
164
 
@@ -151,7 +203,7 @@ module Elibri
151
203
 
152
204
  # Jesli Elibri zwoci jakis blad, to rzucamy odpowiednim wyjatkiem.
153
205
  def raise_if_error_present_in(response)
154
- raise Unauthorized, 'Bad login or password' if response.code == 401
206
+ raise Exceptions::Unauthorized, 'Bad login or password' if response.code == 401
155
207
 
156
208
  response_xml = response.parsed_response
157
209
  if response_xml && !response_xml.css('error').empty?
@@ -163,7 +215,7 @@ module Elibri
163
215
  raise exception_class, error_message
164
216
  else
165
217
  # Jakis nieznany blad - rzucamy chociaz stringiem
166
- raise UnknownError, "ELIBRI_API ERROR #{error_id}: #{error_message}"
218
+ raise Exceptions::UnknownError, "ELIBRI_API ERROR #{error_id}: #{error_message}"
167
219
  end
168
220
  end
169
221
  end
@@ -1,46 +1,61 @@
1
1
 
2
2
  # Klasy pomocnicze dla API w wersji 1
3
- module Elibri
3
+ module Elibri #:nodoc:
4
4
  class ApiClient
5
5
  module ApiAdapters
6
6
 
7
7
  # Adapter dla pierwszej wersji API.
8
8
  class V1
9
9
 
10
- class UnknownError < RuntimeError; end
11
- class Unauthorized < RuntimeError; end
12
- class NotFound < RuntimeError; end
13
- class Forbidden < RuntimeError; end
14
- class ServerError < RuntimeError; end
15
- class NoPendingData < RuntimeError; end
16
- class NoRecentlyPickedUpQueues < RuntimeError; end
17
- class QueueDoesNotExists < RuntimeError; end
18
- class InvalidPageNumber < RuntimeError; end
19
-
20
- # Klasy wyjatków rzucanych, gdy elibri zwróci określony blad. Np. gdy dostaniemy:
10
+ module Exceptions #:nodoc:all
11
+ class UnknownError < RuntimeError; end
12
+ class Unauthorized < RuntimeError; end
13
+ class NotFound < RuntimeError; end
14
+ class Forbidden < RuntimeError; end
15
+ class ServerError < RuntimeError; end
16
+ class NoPendingData < RuntimeError; end
17
+ class NoRecentlyPickedUpQueues < RuntimeError; end
18
+ class QueueDoesNotExists < RuntimeError; end
19
+ class InvalidPageNumber < RuntimeError; end
20
+ end
21
+
22
+ # Klasy wyjatkow rzucanych, gdy elibri zwroci okreslony blad. Np. gdy dostaniemy:
21
23
  # <error id="1001">
22
24
  # <message>Queue does not exist</message>
23
25
  # </error>
24
- # Biblioteka rzuca wyjatkiem QueueDoesNotExists.
26
+ # Biblioteka rzuca wyjatkiem Elibri::ApiClient::ApiAdapters::V1::Exceptions::QueueDoesNotExists.
25
27
  EXCEPTION_CLASSES = {
26
- '404' => NotFound,
27
- '403' => Forbidden,
28
- '500' => ServerError,
29
- '1001' => QueueDoesNotExists,
30
- '1002' => NoPendingData,
31
- '1003' => NoRecentlyPickedUpQueues,
32
- '1004' => InvalidPageNumber
28
+ '404' => Exceptions::NotFound,
29
+ '403' => Exceptions::Forbidden,
30
+ '500' => Exceptions::ServerError,
31
+ '1001' => Exceptions::QueueDoesNotExists,
32
+ '1002' => Exceptions::NoPendingData,
33
+ '1003' => Exceptions::NoRecentlyPickedUpQueues,
34
+ '1004' => Exceptions::InvalidPageNumber
33
35
  }.freeze
34
36
 
35
37
 
36
38
  # Zamiast rzezbic ciagle w XML`u, tworzymy instancje kolejek.
37
39
  class Queue
38
- attr_reader :name, :items_total, :picked_up_at, :last_insert_at, :queue_id, :url
39
-
40
- def initialize(api_adapter, attributes = {})
40
+ # Nazwa kolejki - te z przedroskiem 'pending' sa oczekujace
41
+ attr_reader :name
42
+ # Ilosc produktow znajdujacych sie w kolejce
43
+ attr_reader :products_count
44
+ # Kiedy kolejka zostala przekonwertowana na nazwana? (otrzymala ID w bazie)
45
+ attr_reader :picked_up_at
46
+ # Kiedy ostatnio umieszczono jakis produkt w kolejce?
47
+ attr_reader :last_insert_at
48
+ # Unikalny identyfikator kolejki w bazie
49
+ attr_reader :queue_id
50
+ # Entrypoint API, pod ktorym mozna zobaczyc zawartosc kolejki
51
+ attr_reader :url
52
+
53
+
54
+ def initialize(api_adapter, attributes = {}) #:nodoc:
55
+ attributes.assert_valid_keys(:name, :products_count, :queue_id, :url, :last_insert_at, :picked_up_at)
41
56
  @api_adapter = api_adapter
42
57
  @name = attributes[:name]
43
- @items_total = attributes[:items_total].to_i
58
+ @products_count = attributes[:products_count].to_i
44
59
  @queue_id = attributes[:queue_id]
45
60
  @url = attributes[:url]
46
61
 
@@ -50,37 +65,167 @@ module Elibri
50
65
 
51
66
 
52
67
  # Przekonwertuj kolejke z danymi oczekujacymi (np. 'pending_meta') na kolejke nazwana.
68
+ # call-seq:
69
+ # pick_up! -> named_queue_instance
70
+ #
53
71
  def pick_up!
54
72
  @api_adapter.pick_up_queue!(self) unless picked_up?
55
73
  end
56
74
 
57
75
 
58
- # Hermetyzujemy stronicowanie danych. Programiste interesuja tylko kolejne rekordy <Product>
59
- def each_product(&block)
60
- @api_adapter.each_product(self, &block)
76
+ # Iteruj po kolejnych rekordach ONIX w nazwanej kolejce.
77
+ def each_product_onix(&block) #:yields: product_xml
78
+ raise 'Cannot iterate unpicked queue products! Try named = queue.pick_up! and then named.each_product_onix' unless self.picked_up?
79
+ @api_adapter.each_product_onix_in_queue(self, &block)
61
80
  end
62
81
 
63
82
 
64
83
  # Czy to jest kolejka nazwana, czy oczekujaca? Wszystkie kolejki z danymi oczekujacymi maja w nazwie
65
84
  # przedrostek 'pending_'. Np. 'pending_meta', 'pending_stocks'.
85
+ # call-seq:
86
+ # picked_up? -> true or false
87
+ #
66
88
  def picked_up?
67
89
  !self.name.start_with?('pending_')
68
90
  end
69
91
 
70
92
 
71
93
  # Zbuduj instancje kolejki na podstawie XML`a.
72
- def self.build_from_xml(api_adapter, queue_xml)
94
+ def self.build_from_xml(api_adapter, queue_xml) #:nodoc:
73
95
  queue_xml = Nokogiri::XML(queue_xml).css('queue').first if queue_xml.is_a? String
74
96
  Queue.new(api_adapter,
75
97
  :name => queue_xml['name'],
76
- :items_total => queue_xml['items_total'].to_i,
98
+ :products_count => queue_xml['products_count'].to_i,
77
99
  :last_insert_at => queue_xml['last_insert_at'],
78
100
  :url => queue_xml['url'],
79
101
  :queue_id => queue_xml['id'],
80
102
  :picked_up_at => queue_xml['picked_up_at']
81
103
  )
82
104
  end
83
-
105
+ end
106
+
107
+
108
+
109
+ class Publisher
110
+ # Identyfikator wydawnictwa w bazie
111
+ attr_reader :publisher_id
112
+ # Nazwa wlasna wydawnictwa
113
+ attr_reader :name
114
+ # Ilosc wydanych produktow
115
+ attr_reader :products_count
116
+ # Entrypoint API, pod ktorym mozna zobaczyc liste produktow
117
+ attr_reader :products_url
118
+ # Nazwa wydawnictwa jako firmy
119
+ attr_reader :company_name
120
+ # NIP
121
+ attr_reader :nip
122
+ # Ulica
123
+ attr_reader :street
124
+ # Miasto
125
+ attr_reader :city
126
+ # Kod pocztowy
127
+ attr_reader :zip_code
128
+ # Telefon 1
129
+ attr_reader :phone1
130
+ # Telefon 2
131
+ attr_reader :phone2
132
+ # Adres WWW wydawnictwa
133
+ attr_reader :www
134
+ # E-mail kontaktowy
135
+ attr_reader :email
136
+
137
+
138
+ def initialize(api_adapter, attributes = {}) #:nodoc:
139
+ attributes.assert_valid_keys(
140
+ :publisher_id, :name, :products_count, :products_url, :company_name, :nip, :street, :city, :zip_code, :phone1, :phone2, :www, :email
141
+ )
142
+ @api_adapter = api_adapter
143
+ @publisher_id = attributes[:publisher_id].to_i
144
+ @name = attributes[:name]
145
+ @products_count = attributes[:products_count].to_i
146
+ @products_url = attributes[:products_url]
147
+ @company_name = attributes[:company_name]
148
+ @nip = attributes[:nip]
149
+ @street = attributes[:street]
150
+ @city = attributes[:city]
151
+ @zip_code = attributes[:zip_code]
152
+ @phone1 = attributes[:phone1]
153
+ @phone2 = attributes[:phone2]
154
+ @www = attributes[:www]
155
+ @email = attributes[:email]
156
+ end
157
+
158
+
159
+ # Zwroc liste produktow wydanych w wydawnictwie - instancji Elibri::ApiClient::ApiAdapters::V1::Product
160
+ # call-seq:
161
+ # products -> array
162
+ #
163
+ def products
164
+ @api_adapter.products_for_publisher(self)
165
+ end
166
+
167
+
168
+ # Zbuduj instancje wydawnictwa na podstawie XML`a.
169
+ def self.build_from_xml(api_adapter, publisher_xml) #:nodoc:
170
+ publisher_xml = Nokogiri::XML(publisher_xml).css('publisher').first if publisher_xml.is_a? String
171
+ Publisher.new(api_adapter,
172
+ :name => publisher_xml['name'],
173
+ :publisher_id => publisher_xml['id'].to_i,
174
+ :company_name => publisher_xml['company_name'],
175
+ :nip => publisher_xml['nip'],
176
+ :street => publisher_xml['street'],
177
+ :city => publisher_xml['city'],
178
+ :zip_code => publisher_xml['zip_code'],
179
+ :phone1 => publisher_xml['phone1'],
180
+ :phone2 => publisher_xml['phone2'],
181
+ :www => publisher_xml['www'],
182
+ :email => publisher_xml['email'],
183
+ :products_count => publisher_xml.css('products').first['count'].to_i,
184
+ :products_url => publisher_xml.css('products').first['url']
185
+ )
186
+ end
187
+
188
+ end
189
+
190
+
191
+ class Product
192
+ # Wydawnictwo, ktore opublikowalo produkt - instancja Elibri::ApiClient::ApiAdapters::V1::Publisher
193
+ attr_reader :publisher
194
+ # Unikalny identyfikator produktu w ONIX
195
+ attr_reader :record_reference
196
+ # Tytul produktu
197
+ attr_reader :main_title
198
+ # Entrypoint API, pod ktorym mozna pobrac ONIX produktu
199
+ attr_reader :url
200
+
201
+ def initialize(api_adapter, publisher, attributes = {}) #:nodoc:
202
+ attributes.assert_valid_keys(:record_reference, :main_title, :url)
203
+ @api_adapter = api_adapter
204
+ @publisher = publisher
205
+ @record_reference = attributes[:record_reference]
206
+ @main_title = attributes[:main_title]
207
+ @url = attributes[:url]
208
+ end
209
+
210
+
211
+ # Zwroc przeparsowany za pomoca Nokogiri ONIX produktu, pobrany z Elibri
212
+ # call-seq:
213
+ # onix_xml -> nokogiri_parsed_xml
214
+ #
215
+ def onix_xml
216
+ @api_adapter.onix_xml_for_product(self)
217
+ end
218
+
219
+
220
+ # Zbuduj instancje produktu na podstawie XML`a.
221
+ def self.build_from_xml(api_adapter, publisher, product_xml) #:nodoc:
222
+ product_xml = Nokogiri::XML(product_xml).css('product').first if product_xml.is_a? String
223
+ Product.new(api_adapter, publisher,
224
+ :record_reference => product_xml['record_reference'],
225
+ :url => product_xml['url'],
226
+ :main_title => product_xml['main_title']
227
+ )
228
+ end
84
229
 
85
230
  end
86
231
 
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
  # HTTParty ma parsowac XML za pomoca Nokogiri. CRACK jest zbyt prosty do naszych zastosowan.
4
- module HTTParty
4
+ module HTTParty #:nodoc:all
5
5
  class Parser
6
6
 
7
7
  def xml
@@ -12,49 +12,3 @@ module HTTParty
12
12
  end
13
13
 
14
14
 
15
- # Ukradzione z ActiveSupport:
16
- class Object
17
- def blank?
18
- respond_to?(:empty?) ? empty? : !self
19
- end
20
-
21
- def present?
22
- !blank?
23
- end
24
-
25
- def presence
26
- self if present?
27
- end
28
- end
29
-
30
- class NilClass
31
- def blank?
32
- true
33
- end
34
- end
35
-
36
- class FalseClass
37
- def blank?
38
- true
39
- end
40
- end
41
-
42
- class TrueClass
43
- def blank?
44
- false
45
- end
46
- end
47
-
48
-
49
- class String
50
- def blank?
51
- self !~ /\S/
52
- end
53
- end
54
-
55
-
56
- class Numeric #:nodoc:
57
- def blank?
58
- false
59
- end
60
- end
@@ -4,7 +4,7 @@ module Elibri
4
4
  module Version
5
5
  MAJOR = 1
6
6
  MINOR = 0
7
- PATCH = 3
7
+ PATCH = 4
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
10
  end
@@ -40,7 +40,7 @@ describe Elibri::ApiClient do
40
40
  it "should delegate several methods to apropriate API adapter" do
41
41
  client = Elibri::ApiClient.new(:login => 'elibri_login', :password => 'pass')
42
42
 
43
- delegated_methods = %w{refill_all_queues! pending_data? pending_queues pick_up_queue! last_pickups each_product each_page}
43
+ delegated_methods = %w{refill_all_queues! pending_data? pending_queues last_pickups publishers}
44
44
  delegated_methods.each {|method_name| client.instance_variable_get('@api_adapter').expects(method_name) }
45
45
  delegated_methods.each {|method_name| client.send(method_name) }
46
46
  end
@@ -0,0 +1,44 @@
1
+ require 'helper'
2
+
3
+
4
+ describe Elibri::ApiClient::ApiAdapters::V1::Product do
5
+
6
+ before do
7
+ @api_adapter = mock('api_adapter')
8
+ @publisher = stub('publisher', :name => 'Wydawnictwo', :publisher_id => 1234)
9
+ end
10
+
11
+
12
+ it "should have several attributes" do
13
+ product = Elibri::ApiClient::ApiAdapters::V1::Product.new(@api_adapter, @publisher,
14
+ :record_reference => 'AAAAAAAAAAAAAAA',
15
+ :main_title => 'Erlang Programming',
16
+ :url => 'http://api.elibri.com.pl/api/v1/products/AAAAAAAAAAAAAAA'
17
+ )
18
+
19
+ assert_equal 'Erlang Programming', product.main_title
20
+ assert_equal 'AAAAAAAAAAAAAAA', product.record_reference
21
+ assert_equal 'Wydawnictwo', product.publisher.name
22
+ end
23
+
24
+
25
+
26
+ it "should be able to build itself from provided XML" do
27
+ xml = %Q{
28
+ <product record_reference="04325b31fdece145d22e" main_title="Erlang Programming" url="http://api.elibri.com.pl/api/v1/products/04325b31fdece145d22e"/>
29
+ }
30
+
31
+ product = Elibri::ApiClient::ApiAdapters::V1::Product.build_from_xml(@api_adapter, @publisher, xml)
32
+ assert_equal 'Erlang Programming', product.main_title
33
+ assert_equal '04325b31fdece145d22e', product.record_reference
34
+ assert_equal "http://api.elibri.com.pl/api/v1/products/04325b31fdece145d22e", product.url
35
+ end
36
+
37
+
38
+ it "should be able to establish its full ONIX xml" do
39
+ product = Elibri::ApiClient::ApiAdapters::V1::Product.new(@api_adapter, @publisher, :record_reference => '04325b31fdece145d22e')
40
+ @api_adapter.expects(:onix_xml_for_product).with(product)
41
+ product.onix_xml
42
+ end
43
+
44
+ end
@@ -0,0 +1,61 @@
1
+ require 'helper'
2
+
3
+
4
+ describe Elibri::ApiClient::ApiAdapters::V1::Publisher do
5
+
6
+ before do
7
+ @api_adapter = mock('api_adapter')
8
+ end
9
+
10
+
11
+ it "should have several attributes" do
12
+ publisher = Elibri::ApiClient::ApiAdapters::V1::Publisher.new(@api_adapter,
13
+ :name => 'Wydawnicta Naukowo-Techniczne',
14
+ :publisher_id => '1020',
15
+ :products_count => 1503,
16
+ :products_url => 'http://api.elibri.com.pl/api/v1/publishers/1020/products'
17
+ )
18
+
19
+ assert_equal 'Wydawnicta Naukowo-Techniczne', publisher.name
20
+ assert_equal 1020, publisher.publisher_id
21
+ assert_equal 1503, publisher.products_count
22
+ assert_equal 'http://api.elibri.com.pl/api/v1/publishers/1020/products', publisher.products_url
23
+ end
24
+
25
+
26
+
27
+ it "should be able to build itself from provided XML" do
28
+ xml = %Q{
29
+ <publishers>
30
+ <publisher name="Wydawnicta Naukowo-Techniczne" city="Kraków" company_name="WNT Polska Sp. z o.o." zip_code="30-417" id="1" street="Łagiewnicka 33a" phone1="(12) 252-85-92" phone2="(12) 252-85-80" nip="679-284-08-64" www="http://www.wnt.com" email="sprzedaz@wnt.com">
31
+ <products url="http://api.elibri.com.pl/api/v1/publishers/1/products" count="350"/>
32
+ </publisher>
33
+ </publishers>
34
+ }
35
+
36
+ publisher = Elibri::ApiClient::ApiAdapters::V1::Publisher.build_from_xml(@api_adapter, xml)
37
+
38
+ assert_equal 1, publisher.publisher_id
39
+ assert_equal 350, publisher.products_count
40
+ assert_equal "Wydawnicta Naukowo-Techniczne", publisher.name
41
+ assert_equal "WNT Polska Sp. z o.o.", publisher.company_name
42
+ assert_equal "Kraków", publisher.city
43
+ assert_equal "30-417", publisher.zip_code
44
+ assert_equal "Łagiewnicka 33a", publisher.street
45
+ assert_equal "(12) 252-85-92", publisher.phone1
46
+ assert_equal "(12) 252-85-80", publisher.phone2
47
+ assert_equal "679-284-08-64", publisher.nip
48
+ assert_equal "http://www.wnt.com", publisher.www
49
+ assert_equal "sprzedaz@wnt.com", publisher.email
50
+ assert_equal 'http://api.elibri.com.pl/api/v1/publishers/1/products', publisher.products_url
51
+ end
52
+
53
+
54
+ it "should be able to establish its products list" do
55
+ publisher = Elibri::ApiClient::ApiAdapters::V1::Publisher.new(@api_adapter, :publisher_id => 1234)
56
+ @api_adapter.expects(:products_for_publisher).with(publisher)
57
+ publisher.products
58
+ end
59
+
60
+
61
+ end
@@ -12,7 +12,7 @@ describe Elibri::ApiClient::ApiAdapters::V1::Queue do
12
12
  time = Time.now
13
13
  queue = Elibri::ApiClient::ApiAdapters::V1::Queue.new(@api_adapter,
14
14
  :name => 'meta',
15
- :items_total => 120,
15
+ :products_count => 120,
16
16
  :queue_id => '192f134e666df34464bcc14d0413',
17
17
  :url => 'http://api.elibri.com.pl/api/v1/queues/meta/192f134e666df34464bcc14d0413',
18
18
  :last_insert_at => time.to_s,
@@ -20,7 +20,7 @@ describe Elibri::ApiClient::ApiAdapters::V1::Queue do
20
20
  )
21
21
 
22
22
  assert_equal 'meta', queue.name
23
- assert_equal 120, queue.items_total
23
+ assert_equal 120, queue.products_count
24
24
  assert_equal '192f134e666df34464bcc14d0413', queue.queue_id
25
25
  assert_equal 'http://api.elibri.com.pl/api/v1/queues/meta/192f134e666df34464bcc14d0413', queue.url
26
26
  assert_equal time.to_i, queue.last_insert_at.to_i
@@ -30,17 +30,17 @@ describe Elibri::ApiClient::ApiAdapters::V1::Queue do
30
30
 
31
31
 
32
32
  it "should be able to build itself from provided XML" do
33
- xml = %Q{<queue name="stocks" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="http://api.elibri.com.pl/api/v1/queues/stocks/192f134e666df34464bcc14d04135cda2bd13a0c" items_total="1500" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 22:02:22 UTC"/>}
33
+ xml = %Q{<queue name="stocks" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="http://api.elibri.com.pl/api/v1/queues/stocks/192f134e666df34464bcc14d04135cda2bd13a0c" products_count="1500" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 22:02:22 UTC"/>}
34
34
 
35
35
  queue = Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(@api_adapter, xml)
36
36
  assert_equal 'stocks', queue.name
37
- assert_equal 1500, queue.items_total
37
+ assert_equal 1500, queue.products_count
38
38
  assert_equal '192f134e666df34464bcc14d04135cda2bd13a0c', queue.queue_id
39
39
  assert_equal 'http://api.elibri.com.pl/api/v1/queues/stocks/192f134e666df34464bcc14d04135cda2bd13a0c', queue.url
40
40
  assert_equal Time.parse("2011-02-05 21:02:22 UTC"), queue.last_insert_at
41
41
  assert_equal Time.parse("2011-02-05 22:02:22 UTC"), queue.picked_up_at
42
42
 
43
- xml = %Q{<queue name="pending_stocks" items_total="1500" last_insert_at="2011-02-05 21:02:22 UTC"/>}
43
+ xml = %Q{<queue name="pending_stocks" products_count="1500" last_insert_at="2011-02-05 21:02:22 UTC"/>}
44
44
  queue = Elibri::ApiClient::ApiAdapters::V1::Queue.build_from_xml(@api_adapter, xml)
45
45
  assert_nil queue.queue_id
46
46
  assert_nil queue.picked_up_at
@@ -75,8 +75,8 @@ describe Elibri::ApiClient::ApiAdapters::V1::Queue do
75
75
  block = lambda {|product_xml| product_xml.css('RecordReference') }
76
76
 
77
77
  queue = Elibri::ApiClient::ApiAdapters::V1::Queue.new(@api_adapter, :name => 'meta')
78
- @api_adapter.expects(:each_product).with(queue)
79
- queue.each_product(&block)
78
+ @api_adapter.expects(:each_product_onix_in_queue).with(queue)
79
+ queue.each_product_onix(&block)
80
80
  end
81
81
 
82
82
 
@@ -29,7 +29,7 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
29
29
  it "should define several exception classes" do
30
30
  exception_classes = %w{Unauthorized NotFound Forbidden ServerError NoPendingData NoRecentlyPickedUpQueues QueueDoesNotExists InvalidPageNumber}
31
31
  exception_classes.each do |exception_class|
32
- assert(Elibri::ApiClient::ApiAdapters::V1.const_get(exception_class) < RuntimeError)
32
+ assert(Elibri::ApiClient::ApiAdapters::V1::Exceptions.const_get(exception_class) < RuntimeError)
33
33
  end
34
34
  end
35
35
 
@@ -37,9 +37,23 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
37
37
  it "should be able to refill all pending queues" do
38
38
  response_stub = stub('response_stub', :code => 200, :parsed_response => nil)
39
39
  post_request_expected("#{FAKE_API_HOST}/api/v1/queues/refill_all").returns(response_stub)
40
-
41
40
  @adapter.refill_all_queues!
42
41
  end
42
+
43
+
44
+ it "should normalise request URI before performing real request" do
45
+ response_stub = stub('response_stub', :code => 200, :parsed_response => nil)
46
+
47
+ get_request_expected("#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d0413").once.returns(response_stub)
48
+ @adapter.send(:get, "#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d0413")
49
+
50
+ get_request_expected("#{FAKE_API_HOST}/api/v1/api_entrypoint").once.returns(response_stub)
51
+ @adapter.send(:get, '/api_entrypoint')
52
+
53
+ get_request_expected("#{FAKE_API_HOST}/api/v1/api_entrypoint_without_leading_slash").once.returns(response_stub)
54
+ @adapter.send(:get, 'api_entrypoint_without_leading_slash')
55
+ end
56
+
43
57
 
44
58
 
45
59
  describe "when asked to establish pending queues list" do
@@ -48,8 +62,8 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
48
62
  before do
49
63
  xml = <<-XML
50
64
  <pending_data>
51
- <queue name="pending_meta" items_total="24" last_insert_at="2011-02-05 21:02:22 UTC"/>
52
- <queue name="pending_stocks" items_total="1500" last_insert_at="2011-02-05 21:02:22 UTC"/>
65
+ <queue name="pending_meta" products_count="24" last_insert_at="2011-02-05 21:02:22 UTC"/>
66
+ <queue name="pending_stocks" products_count="1500" last_insert_at="2011-02-05 21:02:22 UTC"/>
53
67
  </pending_data>
54
68
  XML
55
69
 
@@ -66,10 +80,10 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
66
80
  pending_meta = pending_queues.find {|queue| queue.name == 'pending_meta' }
67
81
  pending_stocks = pending_queues.find {|queue| queue.name == 'pending_stocks' }
68
82
 
69
- assert_equal 24, pending_meta.items_total
83
+ assert_equal 24, pending_meta.products_count
70
84
  assert_kind_of Time, pending_meta.last_insert_at
71
85
 
72
- assert_equal 1500, pending_stocks.items_total
86
+ assert_equal 1500, pending_stocks.products_count
73
87
  assert_kind_of Time, pending_stocks.last_insert_at
74
88
  end
75
89
  end
@@ -79,8 +93,8 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
79
93
  before do
80
94
  xml = <<-XML
81
95
  <pending_data>
82
- <queue name="pending_meta" items_total="0" />
83
- <queue name="pending_stocks" items_total="0" />
96
+ <queue name="pending_meta" products_count="0" />
97
+ <queue name="pending_stocks" products_count="0" />
84
98
  </pending_data>
85
99
  XML
86
100
 
@@ -97,11 +111,12 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
97
111
  end
98
112
 
99
113
 
114
+
100
115
  describe "when asked to pick up queue" do
101
116
  before do
102
117
  xml = <<-XML
103
118
  <pick_up>
104
- <queue name="meta" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d04135cda2bd13a0c" items_total="24" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
119
+ <queue name="meta" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d04135cda2bd13a0c" products_count="24" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
105
120
  </pick_up>
106
121
  XML
107
122
 
@@ -112,7 +127,7 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
112
127
  it "should be able to pick it up by name" do
113
128
  post_request_expected("#{FAKE_API_HOST}/api/v1/queues/pending_meta/pick_up").at_least_once.returns(@response_stub)
114
129
  picked_up_queue = @adapter.pick_up_queue!('pending_meta')
115
- assert_equal 24, picked_up_queue.items_total
130
+ assert_equal 24, picked_up_queue.products_count
116
131
  assert_kind_of Time, picked_up_queue.picked_up_at
117
132
  end
118
133
 
@@ -121,7 +136,7 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
121
136
  post_request_expected("#{FAKE_API_HOST}/api/v1/queues/pending_meta/pick_up").at_least_once.returns(@response_stub)
122
137
  queue_to_pick_up = Elibri::ApiClient::ApiAdapters::V1::Queue.new(@api_adapter, :name => 'pending_meta')
123
138
  picked_up_queue = @adapter.pick_up_queue!(queue_to_pick_up)
124
- assert_equal 24, picked_up_queue.items_total
139
+ assert_equal 24, picked_up_queue.products_count
125
140
  assert_kind_of Time, picked_up_queue.picked_up_at
126
141
  end
127
142
 
@@ -136,31 +151,18 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
136
151
  end
137
152
 
138
153
 
139
- it "should normalise request URI before performing real request" do
140
- response_stub = stub('response_stub', :code => 200, :parsed_response => nil)
141
-
142
- get_request_expected("#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d0413").once.returns(response_stub)
143
- @adapter.send(:get, "#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d0413")
144
154
 
145
- get_request_expected("#{FAKE_API_HOST}/api/v1/api_entrypoint").once.returns(response_stub)
146
- @adapter.send(:get, '/api_entrypoint')
147
-
148
- get_request_expected("#{FAKE_API_HOST}/api/v1/api_entrypoint_without_leading_slash").once.returns(response_stub)
149
- @adapter.send(:get, 'api_entrypoint_without_leading_slash')
150
- end
151
-
152
-
153
155
  describe "when there was error reported" do
154
156
  before do
155
157
  @xml = %q{<error id="ERROR_CODE"> <message>Error message for error ERROR_CODE</message> </error>}
156
158
  @exception_classes = {
157
- '404' => Elibri::ApiClient::ApiAdapters::V1::NotFound,
158
- '403' => Elibri::ApiClient::ApiAdapters::V1::Forbidden,
159
- '500' => Elibri::ApiClient::ApiAdapters::V1::ServerError,
160
- '1001' => Elibri::ApiClient::ApiAdapters::V1::QueueDoesNotExists,
161
- '1002' => Elibri::ApiClient::ApiAdapters::V1::NoPendingData,
162
- '1003' => Elibri::ApiClient::ApiAdapters::V1::NoRecentlyPickedUpQueues,
163
- '1004' => Elibri::ApiClient::ApiAdapters::V1::InvalidPageNumber
159
+ '404' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::NotFound,
160
+ '403' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::Forbidden,
161
+ '500' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::ServerError,
162
+ '1001' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::QueueDoesNotExists,
163
+ '1002' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::NoPendingData,
164
+ '1003' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::NoRecentlyPickedUpQueues,
165
+ '1004' => Elibri::ApiClient::ApiAdapters::V1::Exceptions::InvalidPageNumber
164
166
  }
165
167
  end
166
168
 
@@ -177,19 +179,20 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
177
179
  it "should raise Unauthorized, when there is 401 response code" do
178
180
  response_stub = stub('response_stub', :code => 401, :parsed_response => nil)
179
181
  get_request_expected("#{FAKE_API_HOST}/api/v1/queues/pending_data").once.returns(response_stub)
180
- assert_raises(Elibri::ApiClient::ApiAdapters::V1::Unauthorized) { @adapter.pending_queues }
182
+ assert_raises(Elibri::ApiClient::ApiAdapters::V1::Exceptions::Unauthorized) { @adapter.pending_queues }
181
183
  end
182
184
 
183
185
 
184
186
  it "should raise RuntimeError on unknown error code" do
185
187
  response_stub = stub('response_stub', :code => 200, :parsed_response => Nokogiri::XML( @xml.gsub('ERROR_CODE', 'UNKNOWN_ERROR_CODE') ))
186
188
  get_request_expected("#{FAKE_API_HOST}/api/v1/queues/pending_data").once.returns(response_stub)
187
- assert_raises(Elibri::ApiClient::ApiAdapters::V1::UnknownError) { @adapter.pending_queues }
189
+ assert_raises(Elibri::ApiClient::ApiAdapters::V1::Exceptions::UnknownError) { @adapter.pending_queues }
188
190
  end
189
191
 
190
192
  end
191
193
 
192
194
 
195
+
193
196
  describe "when asked to get latest pickups" do
194
197
  describe "and there is no recently picked up queues" do
195
198
  before do
@@ -209,13 +212,13 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
209
212
  before do
210
213
  meta_xml = <<-XML
211
214
  <pick_up>
212
- <queue name="meta" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d04135cda2bd13a0c" items_total="24" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
215
+ <queue name="meta" id="192f134e666df34464bcc14d04135cda2bd13a0c" url="#{FAKE_API_HOST}/api/v1/queues/meta/192f134e666df34464bcc14d04135cda2bd13a0c" products_count="24" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
213
216
  </pick_up>
214
217
  XML
215
218
 
216
219
  stocks_xml = <<-XML
217
220
  <pick_up>
218
- <queue name="stocks" id="192f134e666df34464bcc14d04135cda2bd13a0d" url="#{FAKE_API_HOST}/api/v1/queues/stocks/192f134e666df34464bcc14d04135cda2bd13a0d" items_total="50" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
221
+ <queue name="stocks" id="192f134e666df34464bcc14d04135cda2bd13a0d" url="#{FAKE_API_HOST}/api/v1/queues/stocks/192f134e666df34464bcc14d04135cda2bd13a0d" products_count="50" last_insert_at="2011-02-05 21:02:22 UTC" picked_up_at="2011-02-05 21:02:22 UTC"/>
219
222
  </pick_up>
220
223
  XML
221
224
 
@@ -235,13 +238,12 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
235
238
  end
236
239
 
237
240
 
238
- describe "when asked to iterate by products" do
239
241
 
242
+ describe "when asked to iterate by products in a queue" do
240
243
  before do
241
244
  @queue = Elibri::ApiClient::ApiAdapters::V1::Queue.new(@adapter, :name => 'meta', :queue_id => 'QUEUE_ID')
242
-
243
245
  first_page_xml = <<-XML
244
- <queue name="meta" id="QUEUE_ID" items_total="54" picked_up_at="2011-02-05 21:02:22 UTC">
246
+ <queue name="meta" id="QUEUE_ID" products_count="54" picked_up_at="2011-02-05 21:02:22 UTC">
245
247
  <items paginated="true">
246
248
  <pages total="3" items_per_page="20" >
247
249
  <next_page page_no="2" url="#{FAKE_API_HOST}/api/v1/queues/meta/QUEUE_ID/2" />
@@ -252,9 +254,8 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
252
254
  </items>
253
255
  </queue>
254
256
  XML
255
-
256
257
  second_page_xml = <<-XML
257
- <queue name="meta" id="QUEUE_ID" items_total="54" picked_up_at="2011-02-05 21:02:22 UTC">
258
+ <queue name="meta" id="QUEUE_ID" products_count="54" picked_up_at="2011-02-05 21:02:22 UTC">
258
259
  <items paginated="true">
259
260
  <pages total="3" items_per_page="20" >
260
261
  <previous_page page_no="1" url="#{FAKE_API_HOST}/api/v1/queues/meta/QUEUE_ID" />
@@ -266,9 +267,8 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
266
267
  </items>
267
268
  </queue>
268
269
  XML
269
-
270
270
  third_page_xml = <<-XML
271
- <queue name="meta" id="QUEUE_ID" items_total="54" picked_up_at="2011-02-05 21:02:22 UTC">
271
+ <queue name="meta" id="QUEUE_ID" products_count="54" picked_up_at="2011-02-05 21:02:22 UTC">
272
272
  <items paginated="true">
273
273
  <pages total="3" items_per_page="20" >
274
274
  <previous_page page_no="2" url="#{FAKE_API_HOST}/api/v1/queues/meta/QUEUE_ID/2" />
@@ -290,9 +290,9 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
290
290
  end
291
291
 
292
292
 
293
- it "should be able to iterate through page products" do
293
+ it "should be able to iterate through products pages" do
294
294
  expected_content = %w{<Product>PRODUCT_FROM_PAGE_1</Product> <Product>PRODUCT_FROM_PAGE_2</Product> <Product>PRODUCT_FROM_PAGE_3</Product>}
295
- @adapter.each_page(@queue) do |page_content, page_no|
295
+ @adapter.each_page_in_queue(@queue) do |page_content, page_no|
296
296
  assert_equal expected_content[page_no-1], page_content.children.to_s
297
297
  end
298
298
  end
@@ -300,10 +300,94 @@ describe Elibri::ApiClient::ApiAdapters::V1 do
300
300
 
301
301
  it "should be able to iterate through all product records" do
302
302
  expected_records = %w{PRODUCT_FROM_PAGE_1 PRODUCT_FROM_PAGE_2 PRODUCT_FROM_PAGE_3}
303
- @adapter.each_product(@queue) do |product_xml, product_no|
303
+ @adapter.each_product_onix_in_queue(@queue) do |product_xml, product_no|
304
+ assert_kind_of Nokogiri::XML::Element, product_xml
304
305
  assert_equal expected_records[product_no-1], product_xml.text
305
306
  end
306
307
  end
307
308
  end
308
309
 
310
+
311
+
312
+ describe "when asked to establish available publishers list" do
313
+ before do
314
+ xml = <<-XML
315
+ <publishers>
316
+ <publisher name="Wydawnicta Naukowo-Techniczne" city="Kraków" company_name="WNT Polska Sp. z o.o." zip_code="30-417" id="1" street="Łagiewnicka 33a" phone1="(12) 252-85-92" phone2="(12) 252-85-80" nip="679-284-08-64" www="http://www.wnt.com" email="sprzedaz@wnt.com">
317
+ <products url="#{FAKE_API_HOST}/api/v1/publishers/1/products" count="350"/>
318
+ </publisher>
319
+ <publisher name="Abiekt.pl" city="Warszawa" www="http://www.abiekt.pl" company_name="Abiekt.pl Sp&#243;&#322;ka z o.o." zip_code="00-785" id="2" street="Grottgera 9a/7" phone1="609-626-500" nip="521-348-37-69" email="wojciech.szot@abiekt.pl">
320
+ <products url="#{FAKE_API_HOST}/api/v1/publishers/2/products" count="7"/>
321
+ </publisher>
322
+ </publishers>
323
+ XML
324
+ response_stub = stub('response_stub', :code => 200, :parsed_response => Nokogiri::XML(xml))
325
+ get_request_expected("#{FAKE_API_HOST}/api/v1/publishers").at_least_once.returns(response_stub)
326
+ end
327
+
328
+
329
+ it "should return Publisher instances with attributes filled from returned XML" do
330
+ publishers = @adapter.publishers
331
+ assert_equal 2, publishers.size
332
+ assert(publishers.all? { |publisher| publisher.kind_of? Elibri::ApiClient::ApiAdapters::V1::Publisher })
333
+
334
+ wnt = publishers.find {|publisher| publisher.publisher_id == 1}
335
+ abiekt = publishers.find {|publisher| publisher.publisher_id == 2}
336
+
337
+ # Wyrywkowo sprawdzamy atrybuty:
338
+ assert_equal 350, wnt.products_count
339
+ assert_equal 7, abiekt.products_count
340
+ assert_equal "521-348-37-69", abiekt.nip
341
+ assert_equal "Łagiewnicka 33a", wnt.street
342
+ end
343
+ end
344
+
345
+
346
+
347
+ describe "when asked to get products list for specified publisher" do
348
+ before do
349
+ @publisher = Elibri::ApiClient::ApiAdapters::V1::Publisher.new(@adapter, :publisher_id => 1234)
350
+ xml = <<-XML
351
+ <publisher id="#{@publisher.publisher_id}" name="Wydawnicta Naukowo-Techniczne">
352
+ <products count="3" url="#{FAKE_API_HOST}/api/v1/publishers/#{@publisher.publisher_id}/products">
353
+ <product main_title="Erlang Programming" record_reference="04325b31fdece145d22e" url="#{FAKE_API_HOST}/api/v1/products/04325b31fdece145d22e"/>
354
+ <product main_title="The Little Schemer" record_reference="993140a24d8202a347cc" url="#{FAKE_API_HOST}/api/v1/products/993140a24d8202a347cc"/>
355
+ <product main_title="The Rails Way" record_reference="a40f41cf67facf1876e3" url="#{FAKE_API_HOST}/api/v1/products/a40f41cf67facf1876e3"/>
356
+ </products>
357
+ </publisher>
358
+ XML
359
+ response_stub = stub('response_stub', :code => 200, :parsed_response => Nokogiri::XML(xml))
360
+ get_request_expected("#{FAKE_API_HOST}/api/v1/publishers/1234/products").at_least_once.returns(response_stub)
361
+ end
362
+
363
+
364
+ it "should return Product instances with attributes filled from returned XML" do
365
+ products = @adapter.products_for_publisher(@publisher)
366
+ assert_equal 3, products.size
367
+ assert(products.all? { |product| product.kind_of? Elibri::ApiClient::ApiAdapters::V1::Product })
368
+
369
+ erlang_programming = products.find {|product| product.record_reference == '04325b31fdece145d22e'}
370
+ assert_equal 'Erlang Programming', erlang_programming.main_title
371
+ assert_equal '04325b31fdece145d22e', erlang_programming.record_reference
372
+ assert_equal "#{FAKE_API_HOST}/api/v1/products/04325b31fdece145d22e", erlang_programming.url
373
+ end
374
+ end
375
+
376
+
377
+ describe "when asked to product ONIX XML for specified product" do
378
+ before do
379
+ @product = Elibri::ApiClient::ApiAdapters::V1::Product.new(@adapter, stub('publisher'), :record_reference => '076eb83a5f01cb03a217')
380
+ xml = %Q{<Product><RecordReference>076eb83a5f01cb03a217</RecordReference></Product>}
381
+ response_stub = stub('response_stub', :code => 200, :parsed_response => Nokogiri::XML(xml))
382
+ get_request_expected("#{FAKE_API_HOST}/api/v1/products/076eb83a5f01cb03a217").at_least_once.returns(response_stub)
383
+ end
384
+
385
+
386
+ it "should return parsed ONIX XML" do
387
+ product_xml = @adapter.onix_xml_for_product(@product)
388
+ assert_kind_of Nokogiri::XML::Element, product_xml
389
+ assert_equal '076eb83a5f01cb03a217', product_xml.css('RecordReference').text
390
+ end
391
+
392
+ end
309
393
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elibri_api_client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 3
10
- version: 1.0.3
9
+ - 4
10
+ version: 1.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Marcin Urba\xC5\x84ski"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-06 00:00:00 +02:00
18
+ date: 2011-07-13 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,17 +51,21 @@ dependencies:
51
51
  version_requirements: *id002
52
52
  prerelease: false
53
53
  - !ruby/object:Gem::Dependency
54
- type: :development
54
+ type: :runtime
55
55
  requirement: &id003 !ruby/object:Gem::Requirement
56
56
  none: false
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- hash: 3
60
+ hash: 15424103
61
61
  segments:
62
+ - 3
63
+ - 1
62
64
  - 0
63
- version: "0"
64
- name: ruby-debug
65
+ - rc
66
+ - 1
67
+ version: 3.1.0.rc1
68
+ name: activesupport
65
69
  version_requirements: *id003
66
70
  prerelease: false
67
71
  - !ruby/object:Gem::Dependency
@@ -75,7 +79,7 @@ dependencies:
75
79
  segments:
76
80
  - 0
77
81
  version: "0"
78
- name: mocha
82
+ name: ruby-debug
79
83
  version_requirements: *id004
80
84
  prerelease: false
81
85
  - !ruby/object:Gem::Dependency
@@ -89,12 +93,26 @@ dependencies:
89
93
  segments:
90
94
  - 0
91
95
  version: "0"
92
- name: minitest
96
+ name: mocha
93
97
  version_requirements: *id005
94
98
  prerelease: false
95
99
  - !ruby/object:Gem::Dependency
96
100
  type: :development
97
101
  requirement: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ name: minitest
111
+ version_requirements: *id006
112
+ prerelease: false
113
+ - !ruby/object:Gem::Dependency
114
+ type: :development
115
+ requirement: &id007 !ruby/object:Gem::Requirement
98
116
  none: false
99
117
  requirements:
100
118
  - - ~>
@@ -106,11 +124,11 @@ dependencies:
106
124
  - 0
107
125
  version: 1.0.0
108
126
  name: bundler
109
- version_requirements: *id006
127
+ version_requirements: *id007
110
128
  prerelease: false
111
129
  - !ruby/object:Gem::Dependency
112
130
  type: :development
113
- requirement: &id007 !ruby/object:Gem::Requirement
131
+ requirement: &id008 !ruby/object:Gem::Requirement
114
132
  none: false
115
133
  requirements:
116
134
  - - ~>
@@ -122,11 +140,11 @@ dependencies:
122
140
  - 2
123
141
  version: 1.6.2
124
142
  name: jeweler
125
- version_requirements: *id007
143
+ version_requirements: *id008
126
144
  prerelease: false
127
145
  - !ruby/object:Gem::Dependency
128
146
  type: :development
129
- requirement: &id008 !ruby/object:Gem::Requirement
147
+ requirement: &id009 !ruby/object:Gem::Requirement
130
148
  none: false
131
149
  requirements:
132
150
  - - ">="
@@ -136,7 +154,7 @@ dependencies:
136
154
  - 0
137
155
  version: "0"
138
156
  name: rcov
139
- version_requirements: *id008
157
+ version_requirements: *id009
140
158
  prerelease: false
141
159
  description: API client for elibri.com.pl publishing system
142
160
  email: marcin@urbanski.vdl.pl
@@ -162,6 +180,8 @@ files:
162
180
  - lib/elibri_api_client/core_extensions.rb
163
181
  - lib/elibri_api_client/version.rb
164
182
  - test/elibri_api_client_test.rb
183
+ - test/elibri_api_v1_adapter_product_test.rb
184
+ - test/elibri_api_v1_adapter_publisher_test.rb
165
185
  - test/elibri_api_v1_adapter_queue_test.rb
166
186
  - test/elibri_api_v1_adapter_test.rb
167
187
  - test/helper.rb