Skip to content

Commit 6afdfcf

Browse files
Copilotfbacall
andcommitted
Add custom authors= setter for legacy API backwards compatibility
Co-authored-by: fbacall <503373+fbacall@users.noreply.github.com>
1 parent 4dcfbb4 commit 6afdfcf

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

app/models/material.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,41 @@ class Material < ApplicationRecord
111111
has_many :authors, -> { where(person_links: { role: 'author' }) }, through: :person_links, source: :person
112112
accepts_nested_attributes_for :person_links, allow_destroy: true, reject_if: :all_blank
113113

114+
# Custom setter for authors that accepts both strings (legacy API) and Person objects
115+
def authors=(value)
116+
return if value.nil?
117+
118+
# Convert to array if needed
119+
authors_array = Array(value).reject(&:blank?)
120+
121+
# Remove existing author links
122+
person_links.where(role: 'author').destroy_all
123+
124+
authors_array.each do |author|
125+
if author.is_a?(String)
126+
# Legacy format: parse string into first_name and last_name
127+
parts = author.strip.split(/\s+/, 2)
128+
first_name = parts.length > 1 ? parts[0] : ''
129+
last_name = parts.length > 1 ? parts[1] : parts[0]
130+
131+
person = Person.find_or_create_by!(first_name: first_name, last_name: last_name)
132+
person_links.build(person: person, role: 'author')
133+
elsif author.is_a?(Hash)
134+
# Hash format from API
135+
first_name = author[:first_name] || author['first_name'] || ''
136+
last_name = author[:last_name] || author['last_name'] || ''
137+
orcid = author[:orcid] || author['orcid']
138+
139+
person = Person.find_or_create_by!(first_name: first_name, last_name: last_name)
140+
person.update!(orcid: orcid) if orcid.present?
141+
person_links.build(person: person, role: 'author')
142+
elsif author.is_a?(Person)
143+
# Person object
144+
person_links.build(person: author, role: 'author')
145+
end
146+
end
147+
end
148+
114149
# Remove trailing and squeezes (:squish option) white spaces inside the string (before_validation):
115150
# e.g. "James Bond " => "James Bond"
116151
auto_strip_attributes :title, :description, :url, squish: false

test/models/material_test.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,61 @@ class MaterialTest < ActiveSupport::TestCase
169169
assert_equal 1, @material.authors.size
170170
end
171171

172+
test 'should set authors from array of strings (legacy API support)' do
173+
@material.authors = ['John Doe', 'Jane Smith']
174+
@material.save!
175+
@material.reload
176+
177+
assert_equal 2, @material.authors.size
178+
john = @material.authors.find { |a| a.last_name == 'Doe' }
179+
assert_not_nil john
180+
assert_equal 'John', john.first_name
181+
assert_equal 'Doe', john.last_name
182+
183+
jane = @material.authors.find { |a| a.last_name == 'Smith' }
184+
assert_not_nil jane
185+
assert_equal 'Jane', jane.first_name
186+
assert_equal 'Smith', jane.last_name
187+
end
188+
189+
test 'should set authors from array of hashes' do
190+
@material.authors = [
191+
{ first_name: 'John', last_name: 'Doe', orcid: '0000-0001-1234-5678' },
192+
{ first_name: 'Jane', last_name: 'Smith' }
193+
]
194+
@material.save!
195+
@material.reload
196+
197+
assert_equal 2, @material.authors.size
198+
john = @material.authors.find { |a| a.last_name == 'Doe' }
199+
assert_not_nil john
200+
assert_equal '0000-0001-1234-5678', john.orcid
201+
end
202+
203+
test 'should set authors from array of Person objects' do
204+
person1 = Person.create!(first_name: 'Alice', last_name: 'Wonder')
205+
person2 = Person.create!(first_name: 'Bob', last_name: 'Builder')
206+
207+
@material.authors = [person1, person2]
208+
@material.save!
209+
@material.reload
210+
211+
assert_equal 2, @material.authors.size
212+
assert @material.authors.include?(person1)
213+
assert @material.authors.include?(person2)
214+
end
215+
216+
test 'should handle single name in legacy author string' do
217+
@material.authors = ['Madonna', 'Prince']
218+
@material.save!
219+
@material.reload
220+
221+
assert_equal 2, @material.authors.size
222+
madonna = @material.authors.find { |a| a.last_name == 'Madonna' }
223+
assert_not_nil madonna
224+
assert_equal '', madonna.first_name
225+
end
226+
172227
test 'should delete material when content provider deleted' do
173228
material = @material
174229
content_provider = @material.content_provider

0 commit comments

Comments
 (0)