elibri_api_client 1.0.3 → 1.0.4

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