skala 0.3.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -4
  3. data/Gemfile +10 -1
  4. data/LICENSE.txt +17 -18
  5. data/README.md +1 -34
  6. data/README.primo_adapter.md +42 -0
  7. data/bin/console +11 -0
  8. data/config/initializers/skala.rb +5 -0
  9. data/config/skala.yml +65 -0
  10. data/db/migrate/20141006133522_create_skala_users.rb +13 -0
  11. data/db/migrate/20141006133649_create_skala_user_watch_lists.rb +14 -0
  12. data/db/migrate/20141006135644_create_skala_user_watch_list_entries.rb +13 -0
  13. data/db/migrate/20141006140435_create_skala_user_notes.rb +16 -0
  14. data/lib/skala.rb +36 -3
  15. data/lib/skala/adapter.rb +122 -4
  16. data/lib/skala/adapter/authenticate_user.rb +4 -0
  17. data/lib/skala/adapter/create_user_hold_request.rb +7 -0
  18. data/lib/skala/adapter/create_user_hold_request/result.rb +10 -0
  19. data/lib/skala/adapter/delete_user_hold_request.rb +7 -0
  20. data/lib/skala/adapter/get_record_holdable_items.rb +5 -0
  21. data/lib/skala/adapter/get_record_holdable_items/result.rb +14 -0
  22. data/lib/skala/adapter/get_record_items.rb +5 -0
  23. data/lib/skala/adapter/get_record_items/result.rb +14 -0
  24. data/lib/skala/adapter/get_records.rb +5 -0
  25. data/lib/skala/adapter/get_records/result.rb +28 -0
  26. data/lib/skala/adapter/get_user.rb +4 -0
  27. data/lib/skala/adapter/get_user_former_loans.rb +5 -0
  28. data/lib/skala/adapter/get_user_former_loans/result.rb +14 -0
  29. data/lib/skala/adapter/get_user_hold_requests.rb +5 -0
  30. data/lib/skala/adapter/get_user_hold_requests/result.rb +14 -0
  31. data/lib/skala/adapter/get_user_inter_library_loans.rb +5 -0
  32. data/lib/skala/adapter/get_user_inter_library_loans/result.rb +14 -0
  33. data/lib/skala/adapter/get_user_loans.rb +5 -0
  34. data/lib/skala/adapter/get_user_loans/result.rb +14 -0
  35. data/lib/skala/adapter/get_user_transactions.rb +5 -0
  36. data/lib/skala/adapter/get_user_transactions/result.rb +14 -0
  37. data/lib/skala/adapter/operation.rb +2 -0
  38. data/lib/skala/adapter/operation/request.rb +6 -0
  39. data/lib/skala/adapter/operation/result.rb +7 -0
  40. data/lib/skala/adapter/renew_user_loan.rb +7 -0
  41. data/lib/skala/adapter/renew_user_loan/result.rb +7 -0
  42. data/lib/skala/adapter/renew_user_loans.rb +5 -0
  43. data/lib/skala/adapter/renew_user_loans/result.rb +9 -0
  44. data/lib/skala/adapter/search.rb +6 -0
  45. data/lib/skala/adapter/search/request.rb +91 -0
  46. data/lib/skala/adapter/search/request/date_histogram_facet.rb +5 -0
  47. data/lib/skala/adapter/search/request/facet.rb +29 -0
  48. data/lib/skala/adapter/search/request/histogram_facet.rb +8 -0
  49. data/lib/skala/adapter/search/request/ids_query.rb +6 -0
  50. data/lib/skala/adapter/search/request/match_query.rb +7 -0
  51. data/lib/skala/adapter/search/request/ordered_terms_query.rb +7 -0
  52. data/lib/skala/adapter/search/request/query.rb +18 -0
  53. data/lib/skala/adapter/search/request/query_string_query.rb +9 -0
  54. data/lib/skala/adapter/search/request/range_facet.rb +10 -0
  55. data/lib/skala/adapter/search/request/range_facet/range.rb +9 -0
  56. data/lib/skala/adapter/search/request/range_query.rb +8 -0
  57. data/lib/skala/adapter/search/request/simple_query_string_query.rb +8 -0
  58. data/lib/skala/adapter/search/request/sort_request.rb +15 -0
  59. data/lib/skala/adapter/search/request/terms_facet.rb +8 -0
  60. data/lib/skala/adapter/search/request/unscored_terms_query.rb +7 -0
  61. data/lib/skala/adapter/search/result.rb +22 -0
  62. data/lib/skala/adapter/search/result/facet.rb +15 -0
  63. data/lib/skala/adapter/search/result/histogram_facet.rb +12 -0
  64. data/lib/skala/adapter/search/result/histogram_facet/entry.rb +8 -0
  65. data/lib/skala/adapter/search/result/hit.rb +13 -0
  66. data/lib/skala/adapter/search/result/terms_facet.rb +14 -0
  67. data/lib/skala/adapter/search/result/terms_facet/term.rb +8 -0
  68. data/lib/skala/adapter/update_user.rb +4 -0
  69. data/lib/skala/aleph_adapter.rb +47 -0
  70. data/lib/skala/aleph_adapter/authenticate_user.rb +27 -0
  71. data/lib/skala/aleph_adapter/create_user_hold_request.rb +63 -0
  72. data/lib/skala/aleph_adapter/delete_user_hold_request.rb +29 -0
  73. data/lib/skala/aleph_adapter/get_record.rb +22 -0
  74. data/lib/skala/aleph_adapter/get_record_holdable_items.rb +29 -0
  75. data/lib/skala/aleph_adapter/get_record_items.rb +111 -0
  76. data/lib/skala/aleph_adapter/get_user.rb +49 -0
  77. data/lib/skala/aleph_adapter/get_user_former_loans.rb +21 -0
  78. data/lib/skala/aleph_adapter/get_user_hold_requests.rb +102 -0
  79. data/lib/skala/aleph_adapter/get_user_inter_library_loans.rb +66 -0
  80. data/lib/skala/aleph_adapter/get_user_loans.rb +93 -0
  81. data/lib/skala/aleph_adapter/get_user_transactions.rb +96 -0
  82. data/lib/skala/aleph_adapter/renew_user_loan.rb +27 -0
  83. data/lib/skala/aleph_adapter/renew_user_loans.rb +39 -0
  84. data/lib/skala/aleph_adapter/resolve_user.rb +19 -0
  85. data/lib/skala/aleph_adapter/update_user.rb +105 -0
  86. data/lib/skala/common_attributes.rb +19 -0
  87. data/lib/skala/elasticsearch_adapter.rb +33 -0
  88. data/lib/skala/elasticsearch_adapter/search.rb +20 -0
  89. data/lib/skala/elasticsearch_adapter/search/request_transformation.rb +20 -0
  90. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_aggregations.rb +50 -0
  91. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_from.rb +10 -0
  92. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_query.rb +107 -0
  93. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_size.rb +12 -0
  94. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_sort.rb +18 -0
  95. data/lib/skala/elasticsearch_adapter/search/request_transformation/add_version.rb +10 -0
  96. data/lib/skala/elasticsearch_adapter/search/result_transformation.rb +21 -0
  97. data/lib/skala/elasticsearch_adapter/search/result_transformation/set_facets.rb +44 -0
  98. data/lib/skala/elasticsearch_adapter/search/result_transformation/set_hits.rb +18 -0
  99. data/lib/skala/elasticsearch_adapter/search/result_transformation/set_total_hits.rb +10 -0
  100. data/lib/skala/engine.rb +14 -0
  101. data/lib/skala/get_user_result.rb +14 -0
  102. data/lib/skala/hold_request.rb +24 -0
  103. data/lib/skala/item.rb +15 -0
  104. data/lib/skala/loan.rb +18 -0
  105. data/lib/skala/primo_adapter.rb +34 -0
  106. data/lib/skala/primo_adapter/get_records.rb +24 -0
  107. data/lib/skala/primo_adapter/search.rb +13 -0
  108. data/lib/skala/primo_adapter/search/request_transformation.rb +40 -0
  109. data/lib/skala/primo_adapter/search/request_transformation/add_queries.rb +97 -0
  110. data/lib/skala/primo_adapter/search/request_transformation/add_sort_by_list.rb +37 -0
  111. data/lib/skala/primo_adapter/search/request_transformation/embed_inner_search_request.rb +13 -0
  112. data/lib/skala/primo_adapter/search/request_transformation/serialize_target_as_xml.rb +11 -0
  113. data/lib/skala/primo_adapter/search/request_transformation/set_bulk_size.rb +12 -0
  114. data/lib/skala/primo_adapter/search/request_transformation/set_institution.rb +12 -0
  115. data/lib/skala/primo_adapter/search/request_transformation/set_languages.rb +15 -0
  116. data/lib/skala/primo_adapter/search/request_transformation/set_locations.rb +19 -0
  117. data/lib/skala/primo_adapter/search/request_transformation/set_on_campus.rb +13 -0
  118. data/lib/skala/primo_adapter/search/request_transformation/set_start_index.rb +12 -0
  119. data/lib/skala/primo_adapter/search/request_transformation/setup_inner_search_request.rb +33 -0
  120. data/lib/skala/primo_adapter/search/request_transformation/setup_target.rb +28 -0
  121. data/lib/skala/primo_adapter/search/request_transformation/toggle_bool_operator.rb +13 -0
  122. data/lib/skala/primo_adapter/search/result_transformation.rb +30 -0
  123. data/lib/skala/primo_adapter/search/result_transformation/add_hits.rb +13 -0
  124. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation.rb +46 -0
  125. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_creator.rb +10 -0
  126. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_description.rb +10 -0
  127. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_edition.rb +10 -0
  128. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_fulltext_available.rb +12 -0
  129. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_id.rb +11 -0
  130. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_identifier.rb +46 -0
  131. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_is_part_of.rb +14 -0
  132. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_language.rb +10 -0
  133. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_metadata.rb +13 -0
  134. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_openurl.rb +23 -0
  135. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_publisher.rb +10 -0
  136. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_source.rb +10 -0
  137. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_subject.rb +10 -0
  138. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_title.rb +10 -0
  139. data/lib/skala/primo_adapter/search/result_transformation/doc_transformation/set_year_of_publication.rb +10 -0
  140. data/lib/skala/primo_adapter/search/result_transformation/fix_primo_facets_bugs.rb +108 -0
  141. data/lib/skala/primo_adapter/search/result_transformation/parse_search_brief_response.rb +20 -0
  142. data/lib/skala/primo_adapter/search/result_transformation/set_facets.rb +71 -0
  143. data/lib/skala/primo_adapter/search/result_transformation/set_total_hits.rb +13 -0
  144. data/lib/skala/primo_adapter/search/result_transformation/sort_terms_facets_terms.rb +14 -0
  145. data/lib/skala/primo_adapter/soap_api.rb +15 -0
  146. data/lib/skala/primo_adapter/soap_api/search_brief.rb +25 -0
  147. data/lib/skala/record.rb +85 -0
  148. data/lib/skala/record/identifier.rb +9 -0
  149. data/lib/skala/record/is_part_of.rb +11 -0
  150. data/lib/skala/record/link.rb +9 -0
  151. data/lib/skala/record/relation.rb +9 -0
  152. data/lib/skala/transaction.rb +13 -0
  153. data/lib/skala/version.rb +1 -1
  154. data/skala.gemspec +21 -12
  155. data/spec/skala/search_request/ordered_terms_query_spec.rb +6 -0
  156. data/spec/spec_helper.rb +7 -28
  157. metadata +237 -85
  158. data/lib/skala/i18n.rb +0 -46
  159. data/lib/skala/transformation.rb +0 -54
  160. data/lib/skala/transformation/step.rb +0 -24
  161. data/spec/assets/locales/de.yml +0 -14
  162. data/spec/assets/locales/en.yml +0 -9
  163. data/spec/assets/transformation/some_class.rb +0 -2
  164. data/spec/skala/adapter/operation_spec.rb +0 -19
  165. data/spec/skala/adapter_spec.rb +0 -2
  166. data/spec/skala/i18n_spec.rb +0 -95
  167. data/spec/skala/transformation/step_spec.rb +0 -36
  168. data/spec/skala/transformation_spec.rb +0 -89
  169. data/spec/skala_spec.rb +0 -2
@@ -0,0 +1,96 @@
1
+ require "nokogiri"
2
+ require "skala/adapter/get_user_transactions"
3
+ require_relative "../aleph_adapter"
4
+ require_relative "./resolve_user"
5
+
6
+ class Skala::AlephAdapter::GetUserTransactions < Skala::Adapter::GetUserTransactions
7
+ include parent::ResolveUser
8
+
9
+ def call(username, options = {})
10
+ resolved_user_id = resolve_user(username)
11
+
12
+ patron_cash_list = @adapter.restful_api.patron(resolved_user_id).circulationActions.cash.get(view: :full)
13
+ patron_loan_list = @adapter.restful_api.patron(resolved_user_id).circulationActions.loans.get(view: :full)
14
+
15
+ if [patron_cash_list, patron_loan_list].any? { |_response| _response.include?("<error>") }
16
+ return nil
17
+ else
18
+ transactions = []
19
+
20
+ # regular credits/debits
21
+ Nokogiri::XML(patron_cash_list).xpath("//cash").each do |_cash|
22
+ credit_or_debit = {
23
+ id: id(_cash),
24
+ creation_date: creation_date(_cash),
25
+ record: {
26
+ id: record_id(_cash)
27
+ },
28
+ reason: reason(_cash),
29
+ type: type(_cash),
30
+ value: value(_cash),
31
+ description: description(_cash)
32
+ }
33
+
34
+ transactions << credit_or_debit
35
+ end
36
+
37
+ # unentered debits from loans
38
+ Nokogiri::XML(patron_loan_list).xpath("//loan").each do |_loan|
39
+ if fine = _loan.at_xpath("./fine").try(:content).presence
40
+ transactions << {
41
+ id: nil,
42
+ record: {
43
+ id: record_id(_loan)
44
+ },
45
+ reason: :overdue_fine,
46
+ type: :debit,
47
+ value: fine.to_f
48
+ }
49
+ end
50
+ end
51
+
52
+ self.class::Result.new(
53
+ transactions: transactions,
54
+ source: [patron_cash_list, patron_loan_list]
55
+ )
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def creation_date(cash)
62
+ if date = cash.at_xpath("./z31/z31-date").try(:content).presence
63
+ Date.strptime(date, "%Y%m%d")
64
+ end
65
+ end
66
+
67
+ def id(cash)
68
+ cash.attr("href")[/[^\/]+\Z/][/\A[^?]+/]
69
+ end
70
+
71
+ def record_id(element)
72
+ element.at_xpath("./z13/z13-doc-number").try(:content).presence
73
+ end
74
+
75
+ def reason(cash)
76
+ case cash.at_xpath("./z31/z31-type").try(:content).presence
77
+ when /Kopierauftrag/ then :photocopy_request
78
+ when /Überfällig/ then :overdue_fine
79
+ end
80
+ end
81
+
82
+ def type(cash)
83
+ case cash.attr("type")
84
+ when "credit" then :credit
85
+ when "debit" then :debit
86
+ end
87
+ end
88
+
89
+ def description(cash)
90
+ cash.at_xpath("./z31/z31-description").try(:content).presence
91
+ end
92
+
93
+ def value(cash)
94
+ cash.at_xpath("./z31/z31-sum").try(:content).try(:[], /\d+.\d+/).try(:to_f)
95
+ end
96
+ end
@@ -0,0 +1,27 @@
1
+ require "nokogiri"
2
+ require "skala/adapter/renew_user_loan"
3
+ require_relative "../aleph_adapter"
4
+ require_relative "./resolve_user"
5
+
6
+ class Skala::AlephAdapter::RenewUserLoan < Skala::Adapter::RenewUserLoan
7
+ include parent::ResolveUser
8
+
9
+ def call(username, loan_id, options = {})
10
+ resolved_user_id = resolve_user(username)
11
+
12
+ raw_aleph_response = adapter.restful_api.patron(resolved_user_id).circulationActions.loans(loan_id).post
13
+ reply_code = Nokogiri::XML(raw_aleph_response).at_xpath("//reply-code").try(:content).try(:to_i)
14
+
15
+ if reply_code == 0
16
+ adapter.class::RenewUserLoan::Result.new(
17
+ source: raw_aleph_response
18
+ )
19
+ else
20
+ if reply_code == 28
21
+ raise self.class::RenewFailedError
22
+ else
23
+ raise adapter.class::RequestFailedError
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require "nokogiri"
2
+ require "skala/adapter/renew_user_loans"
3
+ require_relative "../aleph_adapter"
4
+ require_relative "./resolve_user"
5
+
6
+ class Skala::AlephAdapter::RenewUserLoans < Skala::Adapter::RenewUserLoans
7
+ include parent::ResolveUser
8
+
9
+ def call(username, loan_ids = nil, options = {})
10
+ resolved_user_id = resolve_user(username)
11
+
12
+ if loan_ids.blank? # renew all
13
+ raw_aleph_response = adapter.restful_api.patron(resolved_user_id).circulationActions.loans.post
14
+ successfully_renewed_loans_xpath = "//loan/status[contains(text(), 'success')]/parent::*"
15
+
16
+ adapter.class::RenewUserLoans::Result.new(
17
+ renewed_loans: begin
18
+ Nokogiri::XML(raw_aleph_response).xpath(successfully_renewed_loans_xpath).map do |_loan|
19
+ {
20
+ id: _loan.attr("id"),
21
+ due_date: new_due_date(_loan)
22
+ }
23
+ end
24
+ end,
25
+ source: raw_aleph_response
26
+ )
27
+ else
28
+ raise "Unimplemented"
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def new_due_date(loan)
35
+ if date = loan.at_xpath("./new-due-date").try(:content)
36
+ Date.strptime(date, "%Y%m%d")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../aleph_adapter"
2
+
3
+ module Skala::AlephAdapter::ResolveUser
4
+ # @depends_on instance methode #adapter
5
+ def resolve_user(username, options = {})
6
+ username = username.upcase
7
+ user_library = options[:user_library] || adapter.default_user_library
8
+
9
+ x_services_result = adapter.x_services.post(
10
+ op: "bor-by-key",
11
+ bor_id: username,
12
+ library: user_library
13
+ )
14
+
15
+ x_services_result.match(/<internal-id>(.*)<\/internal-id>/) do |_match_data|
16
+ _match_data.captures.first
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,105 @@
1
+ require "skala/adapter/update_user"
2
+ require_relative "../aleph_adapter"
3
+ require_relative "./resolve_user"
4
+
5
+ class Skala::AlephAdapter::UpdateUser < Skala::Adapter::UpdateUser
6
+ include parent::ResolveUser
7
+
8
+ def call(username, options = {})
9
+ username = username.upcase # ensure that username/id is always upcased
10
+ valid_update_options = options.select { |_key, _| respond_to?("update_#{_key}", true) }.to_h
11
+
12
+ #
13
+ # Updating multiple properties in one go is a non trivial task, especially
14
+ # if one of n updates fails, which implies rollbacks or partial update
15
+ #
16
+ if valid_update_options.keys.length > 1
17
+ raise ArgumentError.new("Only one property can be changed within one call!")
18
+ elsif valid_update_options.keys.length < 1
19
+ raise ArgumentError.new("Unknown property to update!")
20
+ end
21
+
22
+ property_name, new_value = [valid_update_options.keys.first, valid_update_options.values.first]
23
+ send("update_#{property_name}", username, new_value, options)
24
+ end
25
+
26
+ private
27
+
28
+ def update_email_address(user_id, new_email_address, options = {})
29
+ user_library = options[:user_library] || adapter.default_user_library
30
+ resolved_user_id = resolve_user(user_id)
31
+
32
+ raw_aleph_responses = ["01", "02"].map do |_z304_address_type|
33
+ adapter.x_services.post(
34
+ op: :update_bor,
35
+ update_flag: "Y",
36
+ library: user_library,
37
+ xml_full_req: <<-XML.strip_heredoc
38
+ <?xml version="1.0"?>
39
+ <p-file-20>
40
+ <patron-record>
41
+ <z303>
42
+ <match-id-type>00</match-id-type>
43
+ <match-id>#{resolved_user_id}</match-id>
44
+ <record-action>X</record-action>
45
+ </z303>
46
+ <z304>
47
+ <record-action>U</record-action>
48
+ <z304-id>#{resolved_user_id}</z304-id>
49
+ <z304-address-type>#{_z304_address_type}</z304-address-type>
50
+ <z304-sequence>01</z304-sequence>
51
+ <z304-email-address>#{new_email_address}</z304-email-address>
52
+ </z304>
53
+ </patron-record>
54
+ </p-file-20>
55
+ XML
56
+ )
57
+ end
58
+
59
+ if raw_aleph_responses.none? { |_raw_aleph_response| _raw_aleph_response[/Succeeded to REWRITE table z304/] }
60
+ raise Skala::Adapter::Error
61
+ end
62
+
63
+ return true # if no exception was thrown so far
64
+ end
65
+
66
+ def update_password(user_id, new_password, options = {})
67
+ user_library = options[:user_library] || adapter.default_user_library
68
+ resolved_user_id = resolve_user(user_id)
69
+
70
+ # we have to change the password for all ids
71
+ [resolved_user_id, user_id].uniq.each do |_user_id|
72
+ _id_type = (_user_id == resolved_user_id) ? "00" : "01"
73
+
74
+ raw_aleph_response = adapter.x_services.post(
75
+ op: :update_bor,
76
+ update_flag: "Y",
77
+ library: user_library,
78
+ xml_full_req: <<-XML.strip_heredoc
79
+ <?xml version="1.0"?>
80
+ <p-file-20>
81
+ <patron-record>
82
+ <z303>
83
+ <match-id-type>#{_id_type}</match-id-type>
84
+ <match-id>#{_user_id}</match-id>
85
+ <record-action>X</record-action>
86
+ </z303>
87
+ <z308>
88
+ <record-action>U</record-action>
89
+ <z308-key-type>#{_id_type}</z308-key-type>
90
+ <z308-key-data>#{_user_id}</z308-key-data>
91
+ <z308-verification>#{new_password}</z308-verification>
92
+ </z308>
93
+ </patron-record>
94
+ </p-file-20>
95
+ XML
96
+ )
97
+
98
+ unless raw_aleph_response[/Succeeded to REWRITE table z308/]
99
+ raise Skala::Adapter::Error
100
+ end
101
+ end
102
+
103
+ return true # if no exception was thrown so far
104
+ end
105
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../skala"
2
+
3
+ module Skala::CommonAttributes
4
+ include Virtus.model
5
+
6
+ attribute :ils_record_id
7
+ attribute :search_engine_record_id
8
+
9
+ attribute :contributor
10
+ attribute :created
11
+ attribute :creator
12
+ attribute :creation_date
13
+ attribute :edition
14
+ attribute :language
15
+ attribute :place_of_publication
16
+ attribute :publisher
17
+ attribute :signature
18
+ attribute :title
19
+ end
@@ -0,0 +1,33 @@
1
+ require "active_support"
2
+ require "active_support/core_ext"
3
+ require "elasticsearch"
4
+ require "skala/adapter"
5
+
6
+ class Skala::ElasticsearchAdapter < Skala::Adapter
7
+ require_relative "elasticsearch_adapter/search"
8
+
9
+ attr_accessor :hosts
10
+ attr_accessor :index
11
+ attr_accessor :timeout
12
+ attr_accessor :type
13
+
14
+ def hosts=(value)
15
+ @hosts = value.try(:map) { |host| host.deep_symbolize_keys }
16
+ end
17
+
18
+ def initialize(options = {})
19
+ HashWithIndifferentAccess.new(options).try do |_options|
20
+ self.hosts = _options[:hosts] || _options[:host] || _options[:urls] || _options[:url]
21
+ self.index = _options[:index]
22
+ self.timeout = _options[:timeout]
23
+ self.type = _options[:type]
24
+ end
25
+ end
26
+
27
+ #
28
+ # internal api between adapter and operations
29
+ #
30
+ def elasticsearch_client
31
+ Elasticsearch::Client.new hosts: @hosts
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ require "skala/adapter/search"
2
+ require_relative "../elasticsearch_adapter"
3
+
4
+ class Skala::ElasticsearchAdapter::Search < Skala::Adapter::Search
5
+ require_relative "./search/request_transformation"
6
+ require_relative "./search/result_transformation"
7
+
8
+ def call(search_request, options = {})
9
+ elasticsearch_request = {
10
+ body: RequestTransformation.new.call(search_request),
11
+ index: @adapter.index
12
+ }
13
+
14
+ elasticsearch_result = @adapter.elasticsearch_client.search(elasticsearch_request)
15
+
16
+ ResultTransformation.new.call(elasticsearch_result, search_request: search_request)
17
+ rescue Elasticsearch::Transport::Transport::Errors::BadRequest
18
+ raise Skala::Adapter::BadRequestError
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require "transformator/transformation"
2
+ require_relative "../search"
3
+
4
+ class Skala::ElasticsearchAdapter::Search::RequestTransformation < Transformator::Transformation
5
+ require_directory "#{File.dirname(__FILE__)}/request_transformation"
6
+
7
+ def call(source, options = {})
8
+ options[:target] ||= {}
9
+ super(source, options)
10
+ end
11
+
12
+ sequence [
13
+ AddAggregations,
14
+ AddFrom,
15
+ AddQuery,
16
+ AddSize,
17
+ AddSort,
18
+ AddVersion
19
+ ]
20
+ end
@@ -0,0 +1,50 @@
1
+ require "transformator/transformation/step"
2
+ require_relative "../request_transformation"
3
+
4
+ class Skala::ElasticsearchAdapter::Search::RequestTransformation::
5
+ AddAggregations < Transformator::Transformation::Step
6
+
7
+ def call
8
+ source.facets.try(:each) do |_facet|
9
+ target["aggregations"] ||= {}
10
+
11
+ elasticsearch_aggregation =
12
+ if _facet.is_a?(Skala::Adapter::Search::Request::HistogramFacet)
13
+ {
14
+ "histogram" => {
15
+ "field" => _facet.field,
16
+ "interval" => _facet.interval
17
+ }
18
+ .compact
19
+ }
20
+ elsif _facet.is_a?(Skala::Adapter::Search::Request::RangeFacet)
21
+ {
22
+ "range" => {
23
+ "field" => _facet.field,
24
+ "ranges" => _facet.ranges.map do |_range|
25
+ {
26
+ "key" => _range.key,
27
+ "from" => _range.from,
28
+ "to" => _range.to
29
+ }
30
+ .compact
31
+ end
32
+ }
33
+ }
34
+ elsif _facet.is_a?(Skala::Adapter::Search::Request::TermsFacet)
35
+ {
36
+ "terms" => {
37
+ "field" => _facet.field,
38
+ "size" => _facet.size,
39
+ "shard_size" => (_facet.size * 3 if _facet.size)
40
+ }
41
+ .compact
42
+ }
43
+ end
44
+
45
+ if elasticsearch_aggregation
46
+ target["aggregations"][_facet.name] = elasticsearch_aggregation
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+ require "transformator/transformation/step"
2
+ require_relative "../request_transformation"
3
+
4
+ class Skala::ElasticsearchAdapter::Search::RequestTransformation::
5
+ AddFrom < Transformator::Transformation::Step
6
+
7
+ def call
8
+ target["from"] = source.from
9
+ end
10
+ end