enju_biblio 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/app/models2/agent.rb +331 -0
  3. data/app/models2/agent_import_file.rb +259 -0
  4. data/app/models2/agent_import_file_state_machine.rb +19 -0
  5. data/app/models2/agent_import_file_transition.rb +20 -0
  6. data/app/models2/agent_import_result.rb +20 -0
  7. data/app/models2/agent_merge.rb +17 -0
  8. data/app/models2/agent_merge_list.rb +27 -0
  9. data/app/models2/agent_relationship.rb +24 -0
  10. data/app/models2/agent_relationship_type.rb +20 -0
  11. data/app/models2/agent_type.rb +19 -0
  12. data/app/models2/carrier_type.rb +50 -0
  13. data/app/models2/content_type.rb +19 -0
  14. data/app/models2/country.rb +47 -0
  15. data/app/models2/create.rb +29 -0
  16. data/app/models2/create_type.rb +19 -0
  17. data/app/models2/doi_record.rb +36 -0
  18. data/app/models2/donate.rb +15 -0
  19. data/app/models2/form_of_work.rb +19 -0
  20. data/app/models2/frequency.rb +19 -0
  21. data/app/models2/identifier.rb +83 -0
  22. data/app/models2/identifier_type.rb +18 -0
  23. data/app/models2/import_request.rb +77 -0
  24. data/app/models2/import_request_state_machine.rb +9 -0
  25. data/app/models2/import_request_transition.rb +21 -0
  26. data/app/models2/isbn_record.rb +51 -0
  27. data/app/models2/isbn_record_and_manifestation.rb +18 -0
  28. data/app/models2/issn_record.rb +49 -0
  29. data/app/models2/issn_record_and_manifestation.rb +18 -0
  30. data/app/models2/item.rb +173 -0
  31. data/app/models2/item_custom_property.rb +18 -0
  32. data/app/models2/item_custom_value.rb +17 -0
  33. data/app/models2/language.rb +39 -0
  34. data/app/models2/license.rb +18 -0
  35. data/app/models2/manifestation.rb +764 -0
  36. data/app/models2/manifestation_custom_property.rb +18 -0
  37. data/app/models2/manifestation_custom_value.rb +17 -0
  38. data/app/models2/manifestation_relationship.rb +27 -0
  39. data/app/models2/manifestation_relationship_type.rb +20 -0
  40. data/app/models2/medium_of_performance.rb +19 -0
  41. data/app/models2/own.rb +29 -0
  42. data/app/models2/periodical.rb +33 -0
  43. data/app/models2/periodical_and_manifestation.rb +16 -0
  44. data/app/models2/picture_file.rb +60 -0
  45. data/app/models2/produce.rb +30 -0
  46. data/app/models2/produce_type.rb +19 -0
  47. data/app/models2/realize.rb +29 -0
  48. data/app/models2/realize_type.rb +19 -0
  49. data/app/models2/resource_export_file.rb +64 -0
  50. data/app/models2/resource_export_file_state_machine.rb +15 -0
  51. data/app/models2/resource_export_file_transition.rb +21 -0
  52. data/app/models2/resource_import_file.rb +909 -0
  53. data/app/models2/resource_import_file_state_machine.rb +19 -0
  54. data/app/models2/resource_import_file_transition.rb +21 -0
  55. data/app/models2/resource_import_result.rb +24 -0
  56. data/app/models2/series_statement.rb +72 -0
  57. data/app/models2/series_statement_merge.rb +17 -0
  58. data/app/models2/series_statement_merge_list.rb +17 -0
  59. data/app/views/manifestations/_book_jacket.html.erb +9 -5
  60. data/app/views/manifestations/_colorbox.html.erb +1 -1
  61. data/app/views/manifestations/_pickup.html.erb +1 -1
  62. data/lib/enju_biblio/version.rb +1 -1
  63. data/spec/dummy/yarn.lock +7560 -0
  64. metadata +61 -2
@@ -0,0 +1,764 @@
1
+ class Manifestation < ApplicationRecord
2
+ has_many :creates, -> { order('creates.position') }, dependent: :destroy, foreign_key: 'work_id', inverse_of: :work
3
+ has_many :creators, through: :creates, source: :agent
4
+ has_many :realizes, -> { order('realizes.position') }, dependent: :destroy, foreign_key: 'expression_id', inverse_of: :expression
5
+ has_many :contributors, through: :realizes, source: :agent
6
+ has_many :produces, -> { order('produces.position') }, dependent: :destroy, foreign_key: 'manifestation_id', inverse_of: :manifestation
7
+ has_many :publishers, through: :produces, source: :agent
8
+ has_many :items, dependent: :destroy, inverse_of: :manifestation
9
+ has_many :children, foreign_key: 'parent_id', class_name: 'ManifestationRelationship', dependent: :destroy
10
+ has_many :parents, foreign_key: 'child_id', class_name: 'ManifestationRelationship', dependent: :destroy
11
+ has_many :derived_manifestations, through: :children, source: :child
12
+ has_many :original_manifestations, through: :parents, source: :parent
13
+ has_many :picture_files, as: :picture_attachable, dependent: :destroy
14
+ has_many :series_statements
15
+ belongs_to :language
16
+ belongs_to :carrier_type
17
+ belongs_to :manifestation_content_type, class_name: 'ContentType', foreign_key: 'content_type_id'
18
+ belongs_to :frequency
19
+ belongs_to :required_role, class_name: 'Role', foreign_key: 'required_role_id'
20
+ belongs_to :license, required: false
21
+ has_one :resource_import_result
22
+ has_many :identifiers, dependent: :destroy
23
+ has_many :isbn_record_and_manifestations, dependent: :destroy
24
+ has_many :isbn_records, through: :isbn_record_and_manifestations
25
+ has_many :issn_record_and_manifestations, dependent: :destroy
26
+ has_many :issn_records, through: :issn_record_and_manifestations
27
+ has_one :doi_record
28
+ has_one :periodical_and_manifestation, dependent: :destroy
29
+ has_one :periodical, through: :periodical_and_manifestation
30
+ has_many :manifestation_custom_values, -> { joins(:manifestation_custom_property).order(:position) }
31
+ accepts_nested_attributes_for :creators, allow_destroy: true, reject_if: :all_blank
32
+ accepts_nested_attributes_for :contributors, allow_destroy: true, reject_if: :all_blank
33
+ accepts_nested_attributes_for :publishers, allow_destroy: true, reject_if: :all_blank
34
+ accepts_nested_attributes_for :series_statements, allow_destroy: true, reject_if: :all_blank
35
+ accepts_nested_attributes_for :isbn_records, allow_destroy: true, reject_if: :all_blank
36
+ accepts_nested_attributes_for :issn_records, allow_destroy: true, reject_if: :all_blank
37
+ accepts_nested_attributes_for :identifiers, allow_destroy: true, reject_if: :all_blank
38
+ accepts_nested_attributes_for :manifestation_custom_values, reject_if: :all_blank
39
+
40
+ searchable do
41
+ text :title, default_boost: 2 do
42
+ titles
43
+ end
44
+ [ :fulltext, :note, :creator, :contributor, :publisher, :description, :statement_of_responsibility ].each do |field|
45
+ text field do
46
+ if series_master?
47
+ derived_manifestations.map{|c| c.send(field) }.flatten.compact
48
+ else
49
+ self.send(field)
50
+ end
51
+ end
52
+ end
53
+ text :item_identifier do
54
+ if series_master?
55
+ root_series_statement.root_manifestation.items.pluck(:item_identifier, :binding_item_identifier).flatten.compact
56
+ else
57
+ items.pluck(:item_identifier, :binding_item_identifier).flatten.compact
58
+ end
59
+ end
60
+ string :call_number, multiple: true do
61
+ items.pluck(:call_number)
62
+ end
63
+ string :title, multiple: true
64
+ # text フィールドだと区切りのない文字列の index が上手く作成
65
+ #できなかったので。 downcase することにした。
66
+ #他の string 項目も同様の問題があるので、必要な項目は同様の処置が必要。
67
+ string :connect_title do
68
+ title.join('').gsub(/\s/, '').downcase
69
+ end
70
+ string :connect_creator do
71
+ creator.join('').gsub(/\s/, '').downcase
72
+ end
73
+ string :connect_publisher do
74
+ publisher.join('').gsub(/\s/, '').downcase
75
+ end
76
+ string :isbn, multiple: true do
77
+ isbn_characters
78
+ end
79
+ string :issn, multiple: true do
80
+ if series_statements.exists?
81
+ [identifier_contents(:issn), (series_statements.map{|s| s.manifestation.identifier_contents(:issn)})].flatten.uniq.compact
82
+ else
83
+ identifier_contents(:issn)
84
+ end
85
+ end
86
+ string :lccn, multiple: true do
87
+ identifier_contents(:lccn)
88
+ end
89
+ string :jpno, multiple: true do
90
+ identifier_contents(:jpno)
91
+ end
92
+ string :carrier_type do
93
+ carrier_type.name
94
+ end
95
+ string :library, multiple: true do
96
+ if series_master?
97
+ root_series_statement.root_manifestation.items.map{|i| i.shelf.library.name}.flatten.uniq
98
+ else
99
+ items.map{|i| i.shelf.library.name}
100
+ end
101
+ end
102
+ string :language do
103
+ language&.name
104
+ end
105
+ string :item_identifier, multiple: true do
106
+ if series_master?
107
+ root_series_statement.root_manifestation.items.pluck(:item_identifier, :binding_item_identifier).flatten.compact
108
+ else
109
+ items.pluck(:item_identifier, :binding_item_identifier).flatten.compact
110
+ end
111
+ end
112
+ string :shelf, multiple: true do
113
+ items.collect{|i| "#{i.shelf.library.name}_#{i.shelf.name}"}
114
+ end
115
+ time :created_at
116
+ time :updated_at
117
+ time :pub_date, multiple: true do
118
+ if series_master?
119
+ root_series_statement.root_manifestation.pub_dates
120
+ else
121
+ pub_dates
122
+ end
123
+ end
124
+ time :date_of_publication
125
+ integer :pub_year do
126
+ date_of_publication&.year
127
+ end
128
+ integer :creator_ids, multiple: true
129
+ integer :contributor_ids, multiple: true
130
+ integer :publisher_ids, multiple: true
131
+ integer :item_ids, multiple: true
132
+ integer :original_manifestation_ids, multiple: true
133
+ integer :parent_ids, multiple: true do
134
+ original_manifestations.pluck(:id)
135
+ end
136
+ integer :required_role_id
137
+ integer :height
138
+ integer :width
139
+ integer :depth
140
+ integer :volume_number
141
+ integer :issue_number
142
+ integer :serial_number
143
+ integer :start_page
144
+ integer :end_page
145
+ integer :number_of_pages
146
+ float :price
147
+ integer :series_statement_ids, multiple: true
148
+ boolean :repository_content
149
+ # for OpenURL
150
+ text :aulast do
151
+ creators.pluck(:last_name)
152
+ end
153
+ text :aufirst do
154
+ creators.pluck(:first_name)
155
+ end
156
+ # OTC start
157
+ string :creator, multiple: true do
158
+ creator.map{|au| au.gsub(' ', '')}
159
+ end
160
+ text :au do
161
+ creator
162
+ end
163
+ text :atitle do
164
+ if serial? && root_series_statement.nil?
165
+ titles
166
+ end
167
+ end
168
+ text :btitle do
169
+ title unless serial?
170
+ end
171
+ text :jtitle do
172
+ if serial?
173
+ if root_series_statement
174
+ root_series_statement.titles
175
+ else
176
+ titles
177
+ end
178
+ end
179
+ end
180
+ text :isbn do # 前方一致検索のためtext指定を追加
181
+ isbn_characters
182
+ end
183
+ text :issn do # 前方一致検索のためtext指定を追加
184
+ if series_statements.exists?
185
+ [identifier_contents(:issn), (series_statements.map{|s| s.manifestation.identifier_contents(:issn)})].flatten.uniq.compact
186
+ else
187
+ identifier_contents(:issn)
188
+ end
189
+ end
190
+ text :identifier do
191
+ other_identifiers = identifiers.joins(:identifier_type).merge(IdentifierType.where.not(name: [:isbn, :issn]))
192
+ other_identifiers.pluck(:body)
193
+ end
194
+ string :sort_title
195
+ string :doi, multiple: true do
196
+ identifier_contents(:doi)
197
+ end
198
+ boolean :serial do
199
+ serial?
200
+ end
201
+ boolean :series_master do
202
+ series_master?
203
+ end
204
+ boolean :resource_master do
205
+ if serial?
206
+ if series_master?
207
+ true
208
+ else
209
+ false
210
+ end
211
+ else
212
+ true
213
+ end
214
+ end
215
+ time :acquired_at
216
+ end
217
+
218
+ if ENV['ENJU_STORAGE'] == 's3'
219
+ has_attached_file :attachment, storage: :s3,
220
+ s3_credentials: {
221
+ access_key: ENV['AWS_ACCESS_KEY_ID'],
222
+ secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
223
+ bucket: ENV['S3_BUCKET_NAME'],
224
+ s3_host_name: ENV['S3_HOST_NAME'],
225
+ s3_region: ENV["S3_REGION"]
226
+ },
227
+ s3_permissions: :private
228
+ else
229
+ has_attached_file :attachment,
230
+ path: ":rails_root/private/system/:class/:attachment/:id_partition/:style/:filename"
231
+ end
232
+ do_not_validate_attachment_file_type :attachment
233
+
234
+ validates :original_title, presence: true
235
+ validates :start_page, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
236
+ validates :end_page, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
237
+ validates :height, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
238
+ validates :width, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
239
+ validates :depth, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
240
+ validates :manifestation_identifier, uniqueness: true, allow_blank: true
241
+ validates :pub_date, format: {with: /\A\[{0,1}\d+([\/-]\d{0,2}){0,2}\]{0,1}\z/}, allow_blank: true
242
+ validates :access_address, url: true, allow_blank: true, length: {maximum: 255}
243
+ validates :issue_number, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
244
+ validates :volume_number, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
245
+ validates :serial_number, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
246
+ validates :edition, numericality: {greater_than_or_equal_to: 0}, allow_blank: true
247
+ after_create :clear_cached_numdocs
248
+ before_save :set_date_of_publication, :set_number
249
+ after_save :index_series_statement, :extract_text!
250
+ after_destroy :index_series_statement
251
+ after_touch do |manifestation|
252
+ manifestation.index
253
+ manifestation.index_series_statement
254
+ Sunspot.commit
255
+ end
256
+ strip_attributes only: [:manifestation_identifier, :pub_date, :original_title]
257
+ paginates_per 10
258
+
259
+ attr_accessor :during_import, :parent_id
260
+
261
+ def set_date_of_publication
262
+ return if pub_date.blank?
263
+ year = Time.utc(pub_date.rjust(4, "0")).year rescue nil
264
+ begin
265
+ date = Time.zone.parse(pub_date.rjust(4, "0"))
266
+ if date.year != year
267
+ raise ArgumentError
268
+ end
269
+ rescue ArgumentError, TZInfo::AmbiguousTime
270
+ date = nil
271
+ end
272
+
273
+ pub_date_string = pub_date.rjust(4, "0").split(';').first.gsub(/[\[\]]/, '')
274
+ if pub_date_string.length == 4
275
+ date = Time.zone.parse(Time.utc(pub_date_string).to_s).beginning_of_day
276
+ else
277
+ while date.nil? do
278
+ pub_date_string += '-01'
279
+ break if pub_date_string =~ /-01-01-01$/
280
+ begin
281
+ date = Time.zone.parse(pub_date_string)
282
+ if date.year != year
283
+ raise ArgumentError
284
+ end
285
+ rescue ArgumentError
286
+ date = nil
287
+ rescue TZInfo::AmbiguousTime
288
+ date = nil
289
+ self.year_of_publication = pub_date_string.to_i if pub_date_string =~ /^\d+$/
290
+ break
291
+ end
292
+ end
293
+ end
294
+
295
+ if date
296
+ self.year_of_publication = date.year
297
+ self.month_of_publication = date.month
298
+ if date.year > 0
299
+ self.date_of_publication = date
300
+ end
301
+ end
302
+ end
303
+
304
+ def self.cached_numdocs
305
+ Rails.cache.fetch("manifestation_search_total"){Manifestation.search.total}
306
+ end
307
+
308
+ def clear_cached_numdocs
309
+ Rails.cache.delete("manifestation_search_total")
310
+ end
311
+
312
+ def parent_of_series
313
+ original_manifestations
314
+ end
315
+
316
+ def number_of_pages
317
+ if start_page && end_page
318
+ end_page.to_i - start_page.to_i + 1
319
+ end
320
+ end
321
+
322
+ def titles
323
+ title = []
324
+ title << original_title.to_s.strip
325
+ title << title_transcription.to_s.strip
326
+ title << title_alternative.to_s.strip
327
+ title << volume_number_string
328
+ title << issue_number_string
329
+ title << serial_number.to_s
330
+ title << edition_string
331
+ title << series_statements.map{|s| s.titles}
332
+ #title << original_title.wakati
333
+ #title << title_transcription.wakati rescue nil
334
+ #title << title_alternative.wakati rescue nil
335
+ title.flatten
336
+ end
337
+
338
+ def url
339
+ #access_address
340
+ "#{LibraryGroup.site_config.url}#{self.class.to_s.tableize}/#{self.id}"
341
+ end
342
+
343
+ def creator
344
+ creators.collect(&:name).flatten
345
+ end
346
+
347
+ def contributor
348
+ contributors.collect(&:name).flatten
349
+ end
350
+
351
+ def publisher
352
+ publishers.collect(&:name).flatten
353
+ end
354
+
355
+ def title
356
+ titles
357
+ end
358
+
359
+ # TODO: よりよい推薦方法
360
+ def self.pickup(keyword = nil, current_user = nil)
361
+ return nil if self.cached_numdocs < 5
362
+ if current_user&.role
363
+ current_role_id = current_user.role.id
364
+ else
365
+ current_role_id = 1
366
+ end
367
+
368
+ # TODO: ヒット件数が0件のキーワードがあるときに指摘する
369
+ response = Manifestation.search do
370
+ fulltext keyword if keyword
371
+ with(:required_role_id).less_than_or_equal_to current_role_id
372
+ order_by(:random)
373
+ paginate page: 1, per_page: 1
374
+ end
375
+ response.results.first
376
+ end
377
+
378
+ def extract_text
379
+ return nil if attachment.path.nil?
380
+ return nil unless ENV['ENJU_EXTRACT_TEXT'] == 'true'
381
+ if ENV['ENJU_STORAGE'] == 's3'
382
+ body = Faraday.get(attachment.expiring_url(10)).body.force_encoding('UTF-8')
383
+ else
384
+ body = File.open(attachment.path).read
385
+ end
386
+ client = Faraday.new(url: ENV['SOLR_URL'] || Sunspot.config.solr.url) do |conn|
387
+ conn.request :multipart
388
+ conn.adapter :net_http
389
+ end
390
+ response = client.post('update/extract?extractOnly=true&wt=json&extractFormat=text') do |req|
391
+ req.headers['Content-type'] = 'text/html'
392
+ req.body = body
393
+ end
394
+ update_column(:fulltext, JSON.parse(response.body)[""])
395
+ end
396
+
397
+ def extract_text!
398
+ extract_text
399
+ index
400
+ Sunspot.commit
401
+ end
402
+
403
+ def created(agent)
404
+ creates.find_by(agent_id: agent.id)
405
+ end
406
+
407
+ def realized(agent)
408
+ realizes.find_by(agent_id: agent.id)
409
+ end
410
+
411
+ def produced(agent)
412
+ produces.find_by(agent_id: agent.id)
413
+ end
414
+
415
+ def sort_title
416
+ if series_master?
417
+ if root_series_statement.title_transcription?
418
+ NKF.nkf('-w --katakana', root_series_statement.title_transcription)
419
+ else
420
+ root_series_statement.original_title
421
+ end
422
+ else
423
+ if title_transcription?
424
+ NKF.nkf('-w --katakana', title_transcription)
425
+ else
426
+ original_title
427
+ end
428
+ end
429
+ end
430
+
431
+ def self.find_by_isbn(isbn)
432
+ identifier_type = IdentifierType.find_by(name: 'isbn')
433
+ return nil unless identifier_type
434
+ Manifestation.includes(identifiers: :identifier_type).where("identifiers.body": isbn, "identifier_types.name": 'isbn')
435
+ end
436
+
437
+ def index_series_statement
438
+ series_statements.map{|s| s.index; s.root_manifestation&.index}
439
+ end
440
+
441
+ def acquired_at
442
+ items.order(:acquired_at).first.try(:acquired_at)
443
+ end
444
+
445
+ def series_master?
446
+ return true if root_series_statement
447
+ false
448
+ end
449
+
450
+ def web_item
451
+ items.find_by(shelf_id: Shelf.web.id)
452
+ end
453
+
454
+ def set_agent_role_type(agent_lists, options = {scope: :creator})
455
+ agent_lists.each do |agent_list|
456
+ name_and_role = agent_list[:full_name].split('||')
457
+ if agent_list[:agent_identifier].present?
458
+ agent = Agent.find_by(agent_identifier: agent_list[:agent_identifier])
459
+ end
460
+ agent = Agent.find_by(full_name: name_and_role[0]) unless agent
461
+ next unless agent
462
+ type = name_and_role[1].to_s.strip
463
+
464
+ case options[:scope]
465
+ when :creator
466
+ type = 'author' if type.blank?
467
+ role_type = CreateType.find_by(name: type)
468
+ create = Create.find_by(work_id: id, agent_id: agent.id)
469
+ if create
470
+ create.create_type = role_type
471
+ create.save(validate: false)
472
+ end
473
+ when :publisher
474
+ type = 'publisher' if role_type.blank?
475
+ produce = Produce.find_by(manifestation_id: id, agent_id: agent.id)
476
+ if produce
477
+ produce.produce_type = ProduceType.find_by(name: type)
478
+ produce.save(validate: false)
479
+ end
480
+ else
481
+ raise "#{options[:scope]} is not supported!"
482
+ end
483
+ end
484
+ end
485
+
486
+ def set_number
487
+ self.volume_number = volume_number_string.scan(/\d*/).map{|s| s.to_i if s =~ /\d/}.compact.first if volume_number_string && !volume_number?
488
+ self.issue_number = issue_number_string.scan(/\d*/).map{|s| s.to_i if s =~ /\d/}.compact.first if issue_number_string && !issue_number?
489
+ self.edition = edition_string.scan(/\d*/).map{|s| s.to_i if s =~ /\d/}.compact.first if edition_string && !edition?
490
+ end
491
+
492
+ def pub_dates
493
+ return [] unless pub_date
494
+ pub_date_array = pub_date.split(';')
495
+ pub_date_array.map{|pub_date_string|
496
+ date = nil
497
+ while date.nil? do
498
+ pub_date_string += '-01'
499
+ break if pub_date_string =~ /-01-01-01$/
500
+ begin
501
+ date = Time.zone.parse(pub_date_string)
502
+ rescue ArgumentError
503
+ rescue TZInfo::AmbiguousTime
504
+ end
505
+ end
506
+ date
507
+ }.compact
508
+ end
509
+
510
+ def latest_issue
511
+ if series_master?
512
+ derived_manifestations.where('date_of_publication IS NOT NULL').order('date_of_publication DESC').first
513
+ end
514
+ end
515
+
516
+ def first_issue
517
+ if series_master?
518
+ derived_manifestations.where('date_of_publication IS NOT NULL').order('date_of_publication DESC').first
519
+ end
520
+ end
521
+
522
+ def identifier_contents(name)
523
+ identifiers.id_type(name).order(:position).pluck(:body)
524
+ end
525
+
526
+ # CSVのヘッダ
527
+ # @param [String] role 権限
528
+ def self.csv_header(role: 'Guest')
529
+ Manifestation.new.to_hash(role: role).keys
530
+ end
531
+
532
+ # CSV出力用のハッシュ
533
+ # @param [String] role 権限
534
+ def to_hash(role: 'Guest')
535
+ record = {
536
+ manifestation_id: id,
537
+ original_title: original_title,
538
+ title_alternative: title_alternative,
539
+ title_transcription: title_transcription,
540
+ statement_of_responsibility: statement_of_responsibility,
541
+ serial: serial,
542
+ manifestation_identifier: manifestation_identifier,
543
+ creator: creates.map{|create|
544
+ if create.create_type
545
+ "#{create.agent.full_name}||#{create.create_type.name}"
546
+ else
547
+ "#{create.agent.full_name}"
548
+ end
549
+ }.join('//'),
550
+ contributor: realizes.map{|realize|
551
+ if realize.realize_type
552
+ "#{realize.agent.full_name}||#{realize.realize_type.name}"
553
+ else
554
+ "#{realize.agent.full_name}"
555
+ end
556
+ }.join('//'),
557
+ publisher: produces.map{|produce|
558
+ if produce.produce_type
559
+ "#{produce.agent.full_name}||#{produce.produce_type.name}"
560
+ else
561
+ "#{produce.agent.full_name}"
562
+ end
563
+ }.join('//'),
564
+ pub_date: date_of_publication,
565
+ year_of_publication: year_of_publication,
566
+ publication_place: publication_place,
567
+ manifestation_created_at: created_at,
568
+ manifestation_updated_at: updated_at,
569
+ carrier_type: carrier_type.name,
570
+ content_type: manifestation_content_type.name,
571
+ frequency: frequency.name,
572
+ language: language.name,
573
+ isbn: identifier_contents(:isbn).join('//'),
574
+ issn: identifier_contents(:issn).join('//'),
575
+ volume_number: volume_number,
576
+ volume_number_string: volume_number_string,
577
+ edition: edition,
578
+ edition_string: edition_string,
579
+ issue_number: issue_number,
580
+ issue_number_string: issue_number_string,
581
+ serial_number: serial_number,
582
+ extent: extent,
583
+ start_page: start_page,
584
+ end_page: end_page,
585
+ dimensions: dimensions,
586
+ height: height,
587
+ width: width,
588
+ depth: depth,
589
+ price: price,
590
+ access_address: access_address,
591
+ manifestation_required_role: required_role.name,
592
+ description: description,
593
+ note: note
594
+ }
595
+
596
+ IdentifierType.find_each do |type|
597
+ record[:"identifier:#{type.name.to_sym}"] = identifiers.where(identifier_type: type).pluck(:body).join('//')
598
+ end
599
+
600
+ series = series_statements.order(:position)
601
+ record.merge!(
602
+ series_statement_id: series.pluck(:id).join('//'),
603
+ series_statement_original_title: series.pluck(:original_title).join('.//'),
604
+ series_statement_title_subseries: series.pluck(:title_subseries).join('//'),
605
+ series_statement_title_subseries_transcription: series.pluck(:title_subseries_transcription).join('//'),
606
+ series_statement_title_transcription: series.pluck(:title_transcription).join('//'),
607
+ series_statement_creator: series.pluck(:creator_string).join('//'),
608
+ series_statement_volume_number: series.pluck(:volume_number_string).join('//'),
609
+ series_statement_series_master: series.pluck(:series_master).join('//'),
610
+ series_statement_root_manifestation_id: series.pluck(:root_manifestation_id).join('//'),
611
+ series_statement_manifestation_id: series.pluck(:manifestation_id).join('//'),
612
+ series_statement_position: series.pluck(:position).join('//'),
613
+ series_statement_note: series.pluck(:note).join('//'),
614
+ series_statement_created_at: series.pluck(:created_at).join('//'),
615
+ series_statement_updated_at: series.pluck(:updated_at).join('//')
616
+ )
617
+
618
+ if ['Administrator', 'Librarian'].include?(role)
619
+ record.merge!({
620
+ memo: memo
621
+ })
622
+ ManifestationCustomProperty.order(:position).each do |custom_property|
623
+ custom_value = manifestation_custom_values.find_by(manifestation_custom_property: custom_property)
624
+ record[:"manifestation:#{custom_property.name}"] = custom_value&.value
625
+ end
626
+ end
627
+
628
+ if defined?(EnjuSubject)
629
+ SubjectHeadingType.find_each do |type|
630
+ record[:"subject:#{type.name}"] = subjects.where(subject_heading_type: type).pluck(:term).join('//')
631
+ end
632
+ ClassificationType.find_each do |type|
633
+ record[:"classification:#{type.name}"] = classifications.where(classification_type: type).pluck(:category).join('//')
634
+ end
635
+ end
636
+
637
+ if defined?(EnjuNdl)
638
+ record["jpno"] = identifier_contents(:jpno).first
639
+ end
640
+
641
+ if defined?(EnjuNii)
642
+ record["ncid"] = identifier_contents(:ncid).first
643
+ end
644
+
645
+ record
646
+ end
647
+
648
+ # TSVでのエクスポート
649
+ # @param [String] role 権限
650
+ # @param [String] col_sep 区切り文字
651
+ def self.export(role: 'Guest', col_sep: "\t")
652
+ file = Tempfile.create('manifestation_export') do |f|
653
+ f.write (Manifestation.csv_header(role: role) + Item.csv_header(role: role)).to_csv(col_sep: col_sep)
654
+ Manifestation.find_each do |manifestation|
655
+ if manifestation.items.exists?
656
+ manifestation.items.each do |item|
657
+ f.write (manifestation.to_hash(role: role).values + item.to_hash(role: role).values).to_csv(col_sep: col_sep)
658
+ end
659
+ else
660
+ f.write manifestation.to_hash(role: role).values.to_csv(col_sep: col_sep)
661
+ end
662
+ end
663
+
664
+ f.rewind
665
+ f.read
666
+ end
667
+
668
+ file
669
+ end
670
+
671
+ def root_series_statement
672
+ series_statements.find_by(root_manifestation_id: id)
673
+ end
674
+
675
+ def isbn_characters
676
+ identifier_contents(:isbn).map{|i|
677
+ isbn10 = isbn13 = isbn10_dash = isbn13_dash = nil
678
+ isbn10 = Lisbn.new(i).isbn10
679
+ isbn13 = Lisbn.new(i).isbn13
680
+ isbn10_dash = Lisbn.new(isbn10).isbn_with_dash if isbn10
681
+ isbn13_dash = Lisbn.new(isbn13).isbn_with_dash if isbn13
682
+ [
683
+ isbn10, isbn13, isbn10_dash, isbn13_dash
684
+ ]
685
+ }.flatten
686
+ end
687
+
688
+ def set_custom_property(row)
689
+ ManifestationCustomProperty.all.each do |property|
690
+ if row[property]
691
+ custom_value = ManifestationCustomValue.new(
692
+ manifestation: self,
693
+ manifestation_custom_property: property,
694
+ value: row[property]
695
+ )
696
+ end
697
+ end
698
+ end
699
+ end
700
+
701
+ # == Schema Information
702
+ #
703
+ # Table name: manifestations
704
+ #
705
+ # id :integer not null, primary key
706
+ # original_title :text not null
707
+ # title_alternative :text
708
+ # title_transcription :text
709
+ # classification_number :string
710
+ # manifestation_identifier :string
711
+ # date_of_publication :datetime
712
+ # date_copyrighted :datetime
713
+ # created_at :datetime
714
+ # updated_at :datetime
715
+ # access_address :string
716
+ # language_id :integer default(1), not null
717
+ # carrier_type_id :integer default(1), not null
718
+ # start_page :integer
719
+ # end_page :integer
720
+ # height :integer
721
+ # width :integer
722
+ # depth :integer
723
+ # price :integer
724
+ # fulltext :text
725
+ # volume_number_string :string
726
+ # issue_number_string :string
727
+ # serial_number_string :string
728
+ # edition :integer
729
+ # note :text
730
+ # repository_content :boolean default(FALSE), not null
731
+ # lock_version :integer default(0), not null
732
+ # required_role_id :integer default(1), not null
733
+ # required_score :integer default(0), not null
734
+ # frequency_id :integer default(1), not null
735
+ # subscription_master :boolean default(FALSE), not null
736
+ # attachment_file_name :string
737
+ # attachment_content_type :string
738
+ # attachment_file_size :integer
739
+ # attachment_updated_at :datetime
740
+ # title_alternative_transcription :text
741
+ # description :text
742
+ # abstract :text
743
+ # available_at :datetime
744
+ # valid_until :datetime
745
+ # date_submitted :datetime
746
+ # date_accepted :datetime
747
+ # date_captured :datetime
748
+ # pub_date :string
749
+ # edition_string :string
750
+ # volume_number :integer
751
+ # issue_number :integer
752
+ # serial_number :integer
753
+ # content_type_id :integer default(1)
754
+ # year_of_publication :integer
755
+ # attachment_meta :text
756
+ # month_of_publication :integer
757
+ # fulltext_content :boolean
758
+ # serial :boolean
759
+ # statement_of_responsibility :text
760
+ # publication_place :text
761
+ # extent :text
762
+ # dimensions :text
763
+ # memo :text
764
+ #