app/concerns/form_configurable.rb
module FormConfigurable
extend ActiveSupport::Concern
included do
class_attribute :_form_configurable_fields
self._form_configurable_fields = HashWithIndifferentAccess.new { |h, k| h[k] = [] }
end
delegate :form_configurable_attributes, to: :class
delegate :form_configurable_fields, to: :class
def is_form_configurable?
true
end
def validate_option(method)
if self.respond_to? "validate_#{method}".to_sym
self.send("validate_#{method}".to_sym)
else
false
end
end
def complete_option(method)
if self.respond_to? "complete_#{method}".to_sym
self.send("complete_#{method}".to_sym)
end
end
module ClassMethods
def form_configurable(name, *args)
options = args.extract_options!.reverse_merge(roles: [], type: :string)
if args.all?(Symbol)
options.assert_valid_keys([:type, :roles, :values, :ace, :cache_response, :html_options])
end
if options[:type] == :array && (options[:values].blank? || !options[:values].is_a?(Array))
raise ArgumentError.new('When using :array as :type you need to provide the :values as an Array')
end
if options[:roles].is_a?(Symbol)
options[:roles] = [options[:roles]]
end
case options[:type]
when :array
options[:roles] << :completable
class_eval <<-EOF, __FILE__, __LINE__ + 1
def complete_#{name}
#{options[:values]}.map { |v| {text: v, id: v} }
end
EOF
when :json
class_eval <<-EOF, __FILE__, __LINE__ + 1
before_validation :decode_#{name}_json
private def decode_#{name}_json
case value = options[:#{name}]
when String
options[:#{name}] =
begin
JSON.parse(value)
rescue StandardError
value
end
end
end
EOF
end
_form_configurable_fields[name] = options
end
def form_configurable_fields
self._form_configurable_fields
end
def form_configurable_attributes
form_configurable_fields.keys
end
end
end