@@ -21,6 +21,7 @@ class Material < ApplicationRecord
2121 include HasDifficultyLevel
2222 include HasEdamTerms
2323 include InSpace
24+ include HasPeople
2425
2526 if TeSS ::Config . solr_enabled
2627 # :nocov:
@@ -33,7 +34,9 @@ class Material < ApplicationRecord
3334 text :authors do
3435 authors . map ( &:full_name )
3536 end
36- text :contributors
37+ text :contributors do
38+ contributors . map ( &:full_name )
39+ end
3740 text :target_audience
3841 text :keywords
3942 text :resource_type
@@ -66,7 +69,9 @@ class Material < ApplicationRecord
6669 string :keywords , multiple : true
6770 string :fields , multiple : true
6871 string :resource_type , multiple : true
69- string :contributors , multiple : true
72+ string :contributors , multiple : true do
73+ contributors . map ( &:full_name )
74+ end
7075 string :content_provider do
7176 content_provider . try ( :title )
7277 end
@@ -106,45 +111,9 @@ class Material < ApplicationRecord
106111
107112 has_many :stars , as : :resource , dependent : :destroy
108113
109- has_many :person_links , as : :resource , dependent : :destroy
110- has_many :people , through : :person_links
111- has_many :authors , -> { where ( person_links : { role : 'author' } ) } , through : :person_links , source : :person
112- accepts_nested_attributes_for :person_links , allow_destroy : true , reject_if : :all_blank
113-
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
114+ # Use HasPeople concern for authors and contributors
115+ has_person_role :authors , role_key : 'author'
116+ has_person_role :contributors , role_key : 'contributor'
148117
149118 # Remove trailing and squeezes (:squish option) white spaces inside the string (before_validation):
150119 # e.g. "James Bond " => "James Bond"
@@ -155,10 +124,10 @@ def authors=(value)
155124 validates :other_types , presence : true , if : proc { |m | m . resource_type . include? ( 'other' ) }
156125 validates :keywords , length : { maximum : 20 }
157126
158- clean_array_fields ( :keywords , :fields , :contributors ,
127+ clean_array_fields ( :keywords , :fields ,
159128 :target_audience , :resource_type , :subsets )
160129
161- update_suggestions ( :keywords , :contributors , : target_audience,
130+ update_suggestions ( :keywords , :target_audience ,
162131 :resource_type )
163132
164133 def description = ( desc )
@@ -257,7 +226,7 @@ def to_oai_dc
257226 xml . tag! ( 'dc:title' , title )
258227 xml . tag! ( 'dc:description' , description )
259228 authors . each { |a | xml . tag! ( 'dc:creator' , a . full_name ) }
260- contributors . each { |a | xml . tag! ( 'dc:contributor' , a ) }
229+ contributors . each { |c | xml . tag! ( 'dc:contributor' , c . full_name ) }
261230 xml . tag! ( 'dc:publisher' , content_provider . title ) if content_provider
262231
263232 xml . tag! ( 'dc:format' , 'text/html' )
0 commit comments