1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
class ResourceForm
include ActiveModel::Model
attr_accessor :agent, :resource
attr_accessor :agent_id, :uuid, :name, :summary, :description, :email,
:website, :phone_number, :address, :postal_code, :city,
:entry_number, :latitude, :longitude, :section_ids, :source
with_options presence: true do
validates :name
validates :email, allow_blank: true
# validates :source
validates :phone_number, allow_blank: true
validates :website, allow_blank: true
end
validate :validate_models
def initialize(agent, attributes = nil)
@agent = agent
@attributes = attributes || default_attributes
raise ArgumentError "Attributes must be permitted" unless @attributes.permitted?
# We use an empty hidden field to ensure this is always set, even if no
# section is selected, so let's remove the empty value
@section_ids = @attributes.extract!(:section_ids)[:section_ids].filter_map { |x| x.presence } rescue []
# We may have an existing and correct source, but anyway we must have one
@resource = @agent.resources.build({ source: @agent.name }.merge(@attributes))
end
def new_record?
resource&.new_record? || true
end
# New forms can provide an existing classification,
# and updates can prefer passed arguments to ensure correct changes
def section_ids
resource.present? && @section_ids.empty? ? resource.section_ids : @section_ids
end
# Ensure field values stick around
# OMG this is ugly
# TODO: use delegator or metaprog
def name
@name ||= resource&.name
end
def summary
@summary ||= resource&.summary
end
def description
@description ||= resource&.description
end
def email
@email ||= resource&.email
end
def website
@website ||= resource&.website
end
def phone_number
@phone_number ||= resource&.phone_number
end
def address
@address ||= resource&.address
end
def postal_code
@postal_code ||= resource&.postal_code
end
def city
@city ||= resource&.city
end
def longitude
@longitude ||= resource&.longitude
end
def latitude
@latitude ||= resource&.latitude
end
def save
Rails.logger.info "--- Calling SAVE ---"
return false if invalid?
ActiveRecord::Base.transaction do
resource.save! && \
@section_ids.each do |sec_id|
Rails.logger.info("section " + sec_id)
resource.categories << resource.classifications.find_or_create_by!(section_id: sec_id)
end
true
rescue ActiveRecord::StatementInvalid => e
errors.add(:base, e.message)
false
end
rescue Exception => e
Rails.logger.info "Unhandled Exception #{e.class}: #{e.message}"
false
end
private
def default_attributes
ActionController::Parameters.new(
{
agent_id: @agent.id,
uuid: '',
name: '',
summary: '',
description: '',
email: '',
website: '',
phone_number: '',
address: '',
postal_code: '',
city: '',
entry_number: nil,
latitude: 0.0,
longitude: 0.0,
source: @agent.name,
section_ids: []
}).permit!
end
# Validate underlying models
def validate_models
Rails.logger.info('--- validate_models ---')
resource.valid? || promote_errors(resource.errors)
end
# Promote an error from the Model to the Form
def promote_errors(model_errors)
model_errors.each do |attribute, error|
errors.add(attribute, error.full_message)
end
end
end
|