module BootstrapFormExtensions # Extend help text to allow translations to be specified under 'helpers.help' def get_help_text_by_i18n_key(name) return if object.nil? HelpText.new(object, name).to_s end def required_attribute?(obj, attribute) RequiredAttribute.new(obj, attribute, options[:validation_context]).required? end private class RequiredAttribute def initialize(obj, attribute, context) @obj = obj @attribute = attribute @context = context end def required? return false unless obj and attribute presence_validator.present? && validates_in_context? end private attr_reader :obj, :attribute, :context def model_validation_context if presence_validator presence_validator.options[:on] end end def presence_validator target_validators.detect { |validator| validator.class.in? [ActiveModel::Validations::PresenceValidator, ActiveRecord::Validations::PresenceValidator] } end def target (obj.class == Class) ? obj : obj.class end def target_validators if target.respond_to? :validators_on target.validators_on(attribute) else [] end end def validates_in_context? (model_validation_context.blank? || model_validation_context == context) end end class HelpText attr_reader :object, :name def initialize(object, name) @object = object @name = name end def to_s namespaces.map { |namespace| help_text_for(namespace) }.compact.first end private def help_text_for(namespace) underscored_scope = "#{namespace}.#{partial_scope.underscore}" downcased_scope = "#{namespace}.#{partial_scope.downcase}" help_text = I18n.t(name, scope: underscored_scope, default: '').presence help_text ||= if text = I18n.t(name, scope: downcased_scope, default: '').presence warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead" text end help_text end def partial_scope # ActiveModel::Naming 3.X.X does not support .name; it is supported as of 4.X.X @partial_scope ||= object.class.model_name.respond_to?(:name) ? object.class.model_name.name : object.class.model_name end def namespaces %w(activerecord.help helpers.help) end end end