aboutsummaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/classification.rb2
-rw-r--r--app/models/resource.rb11
-rw-r--r--app/models/resource_form.rb138
3 files changed, 146 insertions, 5 deletions
diff --git a/app/models/classification.rb b/app/models/classification.rb
index 0754054..e2b180f 100644
--- a/app/models/classification.rb
+++ b/app/models/classification.rb
@@ -5,4 +5,6 @@
class Classification < ApplicationRecord
belongs_to :resource
belongs_to :section
+
+ self.primary_key = :resource_id
end
diff --git a/app/models/resource.rb b/app/models/resource.rb
index c603978..b803afb 100644
--- a/app/models/resource.rb
+++ b/app/models/resource.rb
@@ -21,7 +21,7 @@ class Resource < ApplicationRecord
length: { in: 3..64 }
validates :email,
- with: { format: URI::MailTo::EMAIL_REGEXP },
+ format: { with: URI::MailTo::EMAIL_REGEXP },
allow_blank: true
validates :source,
@@ -31,7 +31,8 @@ class Resource < ApplicationRecord
phony_normalize :phone_number, default_country_code: 'BE', normalize_when_valid: true
validates :phone_number,
- phony_plausible: { ignore_record_country_code: true, ignore_record_country_number: true }
+ phony_plausible: { ignore_record_country_code: true, ignore_record_country_number: true },
+ allow_blank: true
# Depends on validate_url Gem
validates :website,
@@ -47,19 +48,19 @@ class Resource < ApplicationRecord
format('%<lon>3.7f', lon: feature['geometry']['coordinates'][0]).to_f
end
def longitude=(value)
- feature['geometry']['coordinates'][0] = format('%<lon>3.7f', lon: value).to_f
+ feature['geometry']['coordinates'][0] = format('%<lon>3.7f', lon: value.to_f).to_f
end
# You can use, e.g.: res.latitude = 0.123
def latitude
format('%<lat>2.7f', lat: feature['geometry']['coordinates'][1]).to_f
end
def latitude=(value)
- feature['geometry']['coordinates'][1] = format('%<lat>2.7f', lat: value).to_f
+ feature['geometry']['coordinates'][1] = format('%<lat>2.7f', lat: value.to_f).to_f
end
# Properties
- [:name, :summary, :description, :email, :source, :address, :postal_code, :city, :phone_number, :website].each do |prop|
+ [:name, :summary, :description, :email, :source, :address, :postal_code, :city, :phone_number, :website, :entry_number].each do |prop|
# Define a reader
define_method prop do
properties[prop.to_s]
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