Vendor Foundation form builder to remove gem dependency
The "foundation_rails_helper" gem is no longer maintained and is incompatible with Rails 7.1. To avoid blocking the upgrade, we've vendored the vendor/foundation_rails_helper/form_builder.rb as a copy of the original FormBuilder class. To mantain compatibility with auto_labels and button_class variables, that are used in the original builder, we are overwriting in the foundation form builder initializer. The gem has been removed from the Gemfile and replaced with this vendored fallback. This workaround is safe to remove once legacy Foundation CSS support is dropped. All vendored code retains the original MIT license and attribution.
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -25,7 +25,6 @@ gem "devise-security", "~> 0.18.0"
|
||||
gem "exiftool_vendored", "~> 12.97.0"
|
||||
gem "file_validators", "~> 3.0.0"
|
||||
gem "font-awesome-sass", "~> 5.15.1" # Remember to update vendor/assets/images/fontawesome when updating this gem
|
||||
gem "foundation_rails_helper", "~> 4.0.1"
|
||||
gem "globalize", "~> 7.0.0"
|
||||
gem "globalize-accessors", "~> 0.3.0"
|
||||
gem "graphiql-rails", "~> 1.8.0"
|
||||
|
||||
@@ -239,11 +239,6 @@ GEM
|
||||
mime-types (>= 1.0)
|
||||
font-awesome-sass (5.15.1)
|
||||
sassc (>= 1.11)
|
||||
foundation_rails_helper (4.0.1)
|
||||
actionpack (>= 4.1, < 7.1)
|
||||
activemodel (>= 4.1, < 7.1)
|
||||
activesupport (>= 4.1, < 7.1)
|
||||
railties (>= 4.1, < 7.1)
|
||||
gitlab (4.20.1)
|
||||
httparty (~> 0.20)
|
||||
terminal-table (>= 1.5.1)
|
||||
@@ -753,7 +748,6 @@ DEPENDENCIES
|
||||
faraday-retry (~> 2.2.1)
|
||||
file_validators (~> 3.0.0)
|
||||
font-awesome-sass (~> 5.15.1)
|
||||
foundation_rails_helper (~> 4.0.1)
|
||||
globalize (~> 7.0.0)
|
||||
globalize-accessors (~> 0.3.0)
|
||||
graphiql-rails (~> 1.8.0)
|
||||
|
||||
16
config/initializers/foundation_form_builder.rb
Normal file
16
config/initializers/foundation_form_builder.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require Rails.root.join("vendor/foundation_rails_helper/form_builder.rb")
|
||||
|
||||
class FoundationRailsHelper::FormBuilder
|
||||
def column_classes(...)
|
||||
""
|
||||
end
|
||||
|
||||
def auto_labels
|
||||
true
|
||||
end
|
||||
|
||||
def submit(value = nil, options = {})
|
||||
options[:class] ||= "success button"
|
||||
super
|
||||
end
|
||||
end
|
||||
22
vendor/foundation_rails_helper/LICENSE
vendored
Normal file
22
vendor/foundation_rails_helper/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2015 Sébastien Gruhier
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
245
vendor/foundation_rails_helper/form_builder.rb
vendored
Normal file
245
vendor/foundation_rails_helper/form_builder.rb
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Copyright (c) 2015 Sébastien Gruhier (http://xilinus.com/)
|
||||
# MIT License
|
||||
# Vendored copy from https://github.com/sgruhier/foundation_rails_helper/blob/master/lib/foundation_rails_helper/form_builder.rb
|
||||
#
|
||||
# This file was vendored to work around the Rails 7.1 incompatibility,
|
||||
# since the `foundation_rails_helper` gem is no longer maintained.
|
||||
#
|
||||
# See LICENSE in vendor/foundation_rails_helper/LICENSE
|
||||
|
||||
require 'action_view/helpers'
|
||||
|
||||
module FoundationRailsHelper
|
||||
class FormBuilder < ActionView::Helpers::FormBuilder
|
||||
include ActionView::Helpers::TagHelper
|
||||
include ActionView::Helpers::OutputSafetyHelper
|
||||
%w(file_field email_field text_field text_area telephone_field phone_field
|
||||
url_field number_field date_field datetime_field datetime_local_field
|
||||
month_field week_field time_field range_field search_field color_field)
|
||||
.each do |method_name|
|
||||
define_method(method_name) do |*args|
|
||||
attribute = args[0]
|
||||
options = args[1] || {}
|
||||
field(attribute, options) do |opts|
|
||||
super(attribute, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def label(attribute, text = nil, options = {})
|
||||
if error?(attribute)
|
||||
options[:class] ||= ''
|
||||
options[:class] += ' is-invalid-label'
|
||||
end
|
||||
|
||||
super(attribute, (text || '').html_safe, options)
|
||||
end
|
||||
|
||||
# rubocop:disable LineLength
|
||||
def check_box(attribute, options = {}, checked_value = '1', unchecked_value = '0')
|
||||
custom_label(attribute, options[:label], options[:label_options]) do
|
||||
options.delete(:label)
|
||||
options.delete(:label_options)
|
||||
super(attribute, options, checked_value, unchecked_value)
|
||||
end + error_and_help_text(attribute, options)
|
||||
end
|
||||
# rubocop:enable LineLength
|
||||
|
||||
def radio_button(attribute, tag_value, options = {})
|
||||
options[:label_options] ||= {}
|
||||
label_options = options.delete(:label_options).merge!(value: tag_value)
|
||||
label_text = options.delete(:label)
|
||||
l = label(attribute, label_text, label_options) unless label_text == false
|
||||
r = @template.radio_button(@object_name, attribute, tag_value,
|
||||
objectify_options(options))
|
||||
|
||||
"#{r}#{l}".html_safe
|
||||
end
|
||||
|
||||
def password_field(attribute, options = {})
|
||||
field attribute, options do |opts|
|
||||
super(attribute, opts.merge(autocomplete: :off))
|
||||
end
|
||||
end
|
||||
|
||||
def datetime_select(attribute, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
super(attribute, options, html_opts.merge(autocomplete: :off))
|
||||
end
|
||||
end
|
||||
|
||||
def date_select(attribute, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
super(attribute, options, html_opts.merge(autocomplete: :off))
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:disable LineLength
|
||||
def time_zone_select(attribute, priorities = nil, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
super(attribute, priorities, options,
|
||||
html_opts.merge(autocomplete: :off))
|
||||
end
|
||||
end
|
||||
# rubocop:enable LineLength
|
||||
|
||||
def select(attribute, choices, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
html_options[:autocomplete] ||= :off
|
||||
super(attribute, choices, options, html_opts)
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:disable LineLength, ParameterLists
|
||||
def collection_select(attribute, collection, value_method, text_method, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
html_options[:autocomplete] ||= :off
|
||||
super(attribute, collection, value_method, text_method, options,
|
||||
html_opts)
|
||||
end
|
||||
end
|
||||
|
||||
def grouped_collection_select(attribute, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
|
||||
field attribute, options, html_options do |html_opts|
|
||||
html_options[:autocomplete] ||= :off
|
||||
super(attribute, collection, group_method, group_label_method,
|
||||
option_key_method, option_value_method, options, html_opts)
|
||||
end
|
||||
end
|
||||
# rubocop:enable LineLength, ParameterLists
|
||||
|
||||
def autocomplete(attribute, url, options = {})
|
||||
field attribute, options do |opts|
|
||||
opts.merge!(update_elements: opts[:update_elements],
|
||||
min_length: 0, value: object.send(attribute))
|
||||
autocomplete_field(attribute, url, opts)
|
||||
end
|
||||
end
|
||||
|
||||
def submit(value = nil, options = {})
|
||||
options[:class] ||= FoundationRailsHelper.configuration.button_class
|
||||
super(value, options)
|
||||
end
|
||||
|
||||
def error_for(attribute, options = {})
|
||||
return unless error?(attribute)
|
||||
|
||||
class_name = 'form-error is-visible'
|
||||
class_name += " #{options[:class]}" if options[:class]
|
||||
|
||||
error_messages = object.errors[attribute].join(', ')
|
||||
error_messages = error_messages.html_safe if options[:html_safe_errors]
|
||||
content_tag(:small, error_messages,
|
||||
class: class_name.sub('is-invalid-input', ''))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def error?(attribute)
|
||||
object.respond_to?(:errors) && !object.errors[attribute].blank?
|
||||
end
|
||||
|
||||
def default_label_text(object, attribute)
|
||||
if object.class.respond_to?(:human_attribute_name)
|
||||
return object.class.human_attribute_name(attribute)
|
||||
end
|
||||
|
||||
attribute.to_s.humanize
|
||||
end
|
||||
|
||||
def custom_label(attribute, text, options)
|
||||
return block_given? ? yield.html_safe : ''.html_safe if text == false
|
||||
|
||||
text = default_label_text(object, attribute) if text.nil? || text == true
|
||||
text = safe_join([yield, text.html_safe]) if block_given?
|
||||
label(attribute, text, options || {})
|
||||
end
|
||||
|
||||
def column_classes(options)
|
||||
classes = SizeClassCalculator.new(options).classes
|
||||
classes + ' columns'
|
||||
end
|
||||
|
||||
def tag_from_options(name, options)
|
||||
return ''.html_safe unless options && options[:value].present?
|
||||
|
||||
content_tag(:div,
|
||||
content_tag(:span, options[:value], class: name),
|
||||
class: column_classes(options).to_s)
|
||||
end
|
||||
|
||||
def decrement_input_size(input, column, options)
|
||||
return unless options.present? && options.key?(column)
|
||||
|
||||
input.send("#{column}=",
|
||||
(input.send(column) - options.fetch(column).to_i))
|
||||
input.send('changed?=', true)
|
||||
end
|
||||
|
||||
def calculate_input_size(prefix_options, postfix_options)
|
||||
input_size =
|
||||
OpenStruct.new(changed?: false, small: 12, medium: 12, large: 12)
|
||||
%w(small medium large).each do |size|
|
||||
decrement_input_size(input_size, size.to_sym, prefix_options)
|
||||
decrement_input_size(input_size, size.to_sym, postfix_options)
|
||||
end
|
||||
|
||||
input_size
|
||||
end
|
||||
|
||||
def wrap_prefix_and_postfix(block, prefix_options, postfix_options)
|
||||
prefix = tag_from_options('prefix', prefix_options)
|
||||
postfix = tag_from_options('postfix', postfix_options)
|
||||
|
||||
input_size = calculate_input_size(prefix_options, postfix_options)
|
||||
klass = column_classes(input_size.marshal_dump).to_s
|
||||
input = content_tag(:div, block, class: klass)
|
||||
|
||||
return block unless input_size.changed?
|
||||
content_tag(:div, prefix + input + postfix, class: 'row collapse')
|
||||
end
|
||||
|
||||
def error_and_help_text(attribute, options = {})
|
||||
html = ''
|
||||
if options[:help_text]
|
||||
html += content_tag(:p, options[:help_text], class: 'help-text')
|
||||
end
|
||||
html += error_for(attribute, options) || ''
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
def field_label(attribute, options)
|
||||
return ''.html_safe unless auto_labels || options[:label]
|
||||
custom_label(attribute, options[:label], options[:label_options])
|
||||
end
|
||||
|
||||
def field(attribute, options, html_options = nil)
|
||||
html = field_label(attribute, options)
|
||||
class_options = html_options || options
|
||||
|
||||
if error?(attribute)
|
||||
class_options[:class] = class_options[:class].to_s
|
||||
class_options[:class] += ' is-invalid-input'
|
||||
end
|
||||
|
||||
options.delete(:label)
|
||||
options.delete(:label_options)
|
||||
help_text = options.delete(:help_text)
|
||||
prefix = options.delete(:prefix)
|
||||
postfix = options.delete(:postfix)
|
||||
|
||||
html += wrap_prefix_and_postfix(yield(class_options), prefix, postfix)
|
||||
html + error_and_help_text(attribute, options.merge(help_text: help_text))
|
||||
end
|
||||
|
||||
def auto_labels
|
||||
if @options[:auto_labels].nil?
|
||||
FoundationRailsHelper.configuration.auto_labels
|
||||
else
|
||||
@options[:auto_labels]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user