aboutsummaryrefslogtreecommitdiff
path: root/app/models/resource_form.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/resource_form.rb')
-rw-r--r--app/models/resource_form.rb138
1 files changed, 138 insertions, 0 deletions
diff --git a/app/models/resource_form.rb b/app/models/resource_form.rb
new file mode 100644
index 0000000..14275a4
--- /dev/null
+++ b/app/models/resource_form.rb
@@ -0,0 +1,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