Skip to content

Commit 23068a4

Browse files
committed
added contributors controller
1 parent e388d22 commit 23068a4

File tree

2 files changed

+231
-2
lines changed

2 files changed

+231
-2
lines changed
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# frozen_string_literal: true
2+
3+
module Nova
4+
# Controller for the Contributors page
5+
class ContributorsController < ApplicationController
6+
include OrgSelectable
7+
helper PaginableHelper
8+
9+
before_action :fetch_plan
10+
before_action :fetch_contributor, only: %i[edit update destroy]
11+
after_action :verify_authorized
12+
13+
# GET /plans/:plan_id/contributors
14+
def index
15+
authorize @plan, :show?
16+
@contributors = @plan.contributors
17+
end
18+
19+
# GET /plans/:plan_id/contributors/new
20+
def new
21+
authorize @plan
22+
default_org = @plan.org.present? ? @plan.org : current_user.org
23+
@contributor = Contributor.new(plan: @plan, org: default_org)
24+
end
25+
26+
# GET /plans/:plan_id/contributors/:id/edit
27+
def edit
28+
authorize @plan
29+
end
30+
31+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
32+
# POST /plans/:plan_id/contributors
33+
def create
34+
authorize @plan, :edit?
35+
36+
args = translate_roles(hash: contributor_params)
37+
args = process_org(hash: args)
38+
if args.blank?
39+
@contributor = Contributor.new(args)
40+
@contributor.errors.add(:affiliation, 'invalid')
41+
flash[:alert] = failure_message(@contributor, _('add'))
42+
render :new
43+
else
44+
args = process_orcid_for_create(hash: args)
45+
46+
# Check if ORCID exists and validate using the orcid_validator class method
47+
if args[:identifiers_attributes].present?
48+
orcid_value = args[:identifiers_attributes][:'0'][:value]
49+
orcid_id = OrcidValidator.extract_orcid_id(orcid_value)
50+
51+
unless orcid_id && OrcidValidator.orcid_id_is_valid?(orcid_id)
52+
@contributor = Contributor.new(args)
53+
@contributor.errors.add(:base, 'ORCID iD is invalid')
54+
flash[:alert] = failure_message(@contributor, _('add'))
55+
render :new
56+
return
57+
end
58+
end
59+
60+
args[:plan_id] = @plan.id
61+
@contributor = Contributor.new(args)
62+
stash_orcid
63+
64+
if @contributor.save
65+
# Now that the model has been ssaved, go ahead and save the identifiers
66+
save_orcid
67+
redirect_to plan_contributors_path(@plan),
68+
notice: success_message(@contributor, _('added'))
69+
else
70+
flash[:alert] = failure_message(@contributor, _('add'))
71+
render :new
72+
end
73+
end
74+
end
75+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
76+
77+
# PUT /plans/:plan_id/contributors/:id
78+
def update
79+
authorize @plan
80+
args = translate_roles(hash: contributor_params)
81+
args = process_org(hash: args)
82+
args = process_orcid_for_update(hash: args)
83+
84+
# Check if ORCID exists and validate using the orcid_validator class method
85+
if args[:identifiers_attributes].present?
86+
orcid_value = args[:identifiers_attributes][:'0'][:value]
87+
orcid_id = OrcidValidator.extract_orcid_id(orcid_value)
88+
89+
unless orcid_id && OrcidValidator.orcid_id_is_valid?(orcid_id)
90+
@contributor = Contributor.new(args)
91+
@contributor.errors.add(:base, 'ORCID iD is invalid')
92+
flash[:alert] = failure_message(@contributor, _('add'))
93+
render :new
94+
return
95+
end
96+
end
97+
98+
if @contributor.update(args)
99+
redirect_to edit_plan_contributor_path(@plan, @contributor),
100+
notice: success_message(@contributor, _('saved'))
101+
else
102+
flash.now[:alert] = failure_message(@contributor, _('save'))
103+
render :edit
104+
end
105+
end
106+
# rubocop:enable
107+
108+
# DELETE /plans/:plan_id/contributors/:id
109+
def destroy
110+
authorize @plan
111+
if @contributor.destroy
112+
msg = success_message(@contributor, _('removed'))
113+
redirect_to plan_contributors_path(@plan), notice: msg
114+
else
115+
flash.now[:alert] = failure_message(@contributor, _('remove'))
116+
render :edit
117+
end
118+
end
119+
120+
private
121+
122+
def contributor_params
123+
base_params = %i[name email phone org_id org_name org_crosswalk]
124+
role_params = Contributor.new.all_roles
125+
126+
params.require(:contributor).permit(
127+
base_params,
128+
role_params,
129+
identifiers_attributes: %i[id identifier_scheme_id value attrs]
130+
)
131+
end
132+
133+
# Translate the check boxes values of "1" and "0" to true/false
134+
def translate_roles(hash:)
135+
roles = Contributor.new.all_roles
136+
roles.each { |role| hash[role.to_sym] = hash[role.to_sym] == '1' }
137+
hash
138+
end
139+
140+
# Convert the Org Hash into an Org object (creating it if allowed)
141+
# and then remove all of the Org args
142+
def process_org(hash:)
143+
return hash unless hash.present? && hash[:org_id].present?
144+
145+
allow = !Rails.configuration.x.application.restrict_orgs
146+
org = org_from_params(params_in: hash,
147+
allow_create: allow)
148+
149+
hash = remove_org_selection_params(params_in: hash)
150+
151+
return hash if org.blank? && !allow
152+
return hash unless org.present?
153+
154+
hash[:org_id] = org.id
155+
hash
156+
end
157+
158+
# When creating, just remove the ORCID if it was left blank
159+
def process_orcid_for_create(hash:)
160+
return hash unless hash[:identifiers_attributes].present?
161+
162+
id_hash = hash[:identifiers_attributes][:'0']
163+
return hash unless id_hash[:value].blank?
164+
165+
hash.delete(:identifiers_attributes)
166+
hash
167+
end
168+
169+
# When updating, destroy the ORCID if it was blanked out on form
170+
def process_orcid_for_update(hash:)
171+
return hash unless hash[:identifiers_attributes].present?
172+
173+
id_hash = hash[:identifiers_attributes][:'0']
174+
return hash unless id_hash[:value].blank?
175+
176+
existing = @contributor.identifier_for_scheme(scheme: 'orcid')
177+
existing.destroy if existing.present?
178+
hash.delete(:identifiers_attributes)
179+
hash
180+
end
181+
182+
# =============
183+
# = Callbacks =
184+
# =============
185+
def fetch_plan
186+
@plan = Plan.find_by(id: params[:plan_id])
187+
return true if @plan.present?
188+
189+
redirect_to root_path, alert: _('plan not found')
190+
end
191+
192+
def fetch_contributor
193+
@contributor = Contributor.find_by(id: params[:id])
194+
return true if @contributor.present? &&
195+
@plan.contributors.include?(@contributor)
196+
197+
redirect_to plan_contributors_path, alert: _('contributor not found')
198+
end
199+
200+
# The following 2 methods address an issue with using Rails normal
201+
# accepts_nested_attributes_for on polymorphic relationships.
202+
#
203+
# Currently, when creating the underlying model, the `.valid?` method is
204+
# called prior to the `save`. This causes all `identifiers` to report that
205+
# the `identifiable_id` is nil. Because Rails forces the `belong_to` relation
206+
# to be present.
207+
#
208+
# To get around it we stash the identifiers during the creation step
209+
# and then save them after the model has been created
210+
#
211+
# Supposedly this is fixed in Rails 5+ by designating `optional: true`
212+
# on the `belong_to` side of the relationship
213+
def stash_orcid
214+
return false unless @contributor.identifiers.any?
215+
216+
@cached_orcid = @contributor.identifiers.first
217+
@contributor.identifiers = []
218+
end
219+
220+
def save_orcid
221+
return true unless @cached_orcid.present?
222+
223+
@cached_orcid.identifiable = @contributor
224+
@cached_orcid.save
225+
@contributor.reload
226+
end
227+
end
228+
end

config/routes.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Nova::Engine.routes.draw do
2-
# get orcid record for contributor
3-
get "orcid_records(/:orcid_id)", to: "orcid_records#show"
2+
resources: contributors, to: "nova/contributors"
3+
4+
get "orcid_records(/:orcid_id)", to: "nova/orcid_records#show"
45
end

0 commit comments

Comments
 (0)