module Coco module ActionViewHelper include ActionView::Helpers::UrlHelper extend self def convert_options_to_data_attributes(options, html_options) if html_options html_options = html_options.stringify_keys html_options["data-remote"] = "true" if link_to_remote_options?(options) || link_to_remote_options?(html_options) method = html_options.delete("method") add_method_to_attributes!(html_options, method) if method html_options else link_to_remote_options?(options) ? {"data-remote" => "true"} : {} end end def url_target(name, options) if name.respond_to?(:model_name) && options.is_a?(Hash) && options.empty? url_for(name) else url_for(options) end end def link_to_remote_options?(options) if options.is_a?(Hash) options.delete("remote") || options.delete(:remote) end end def add_method_to_attributes!(html_options, method) if method_not_get_method?(method) && !html_options["rel"]&.match?(/nofollow/) html_options["rel"] = if html_options["rel"].blank? "nofollow" else "#{html_options["rel"]} nofollow" end end html_options["data-method"] = method end def method_for_options(options) if options.is_a?(Array) method_for_options(options.last) elsif options.respond_to?(:persisted?) options.persisted? ? :patch : :post elsif options.respond_to?(:to_model) method_for_options(options.to_model) end end STRINGIFIED_COMMON_METHODS = { get: "get", delete: "delete", patch: "patch", post: "post", put: "put" }.freeze def method_not_get_method?(method) return false unless method (STRINGIFIED_COMMON_METHODS[method] || method.to_s.downcase) != "get" end def token_tag(token = nil, form_options: {}) if token != false && defined?(protect_against_forgery?) && protect_against_forgery? token = if token == true || token.nil? form_authenticity_token(form_options: form_options.merge(authenticity_token: token)) else token end tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token, autocomplete: "off") else "" end end def method_tag(method) tag("input", type: "hidden", name: "_method", value: method.to_s, autocomplete: "off") end # Returns an array of hashes each containing :name and :value keys # suitable for use as the names and values of form input fields: # # to_form_params(name: 'David', nationality: 'Danish') # # => [{name: 'name', value: 'David'}, {name: 'nationality', value: 'Danish'}] # # to_form_params(country: { name: 'Denmark' }) # # => [{name: 'country[name]', value: 'Denmark'}] # # to_form_params(countries: ['Denmark', 'Sweden']}) # # => [{name: 'countries[]', value: 'Denmark'}, {name: 'countries[]', value: 'Sweden'}] # # An optional namespace can be passed to enclose key names: # # to_form_params({ name: 'Denmark' }, 'country') # # => [{name: 'country[name]', value: 'Denmark'}] def to_form_params(attribute, namespace = nil) attribute = if attribute.respond_to?(:permitted?) attribute.to_h else attribute end params = [] case attribute when Hash attribute.each do |key, value| prefix = namespace ? "#{namespace}[#{key}]" : key params.push(*to_form_params(value, prefix)) end when Array array_prefix = "#{namespace}[]" attribute.each do |value| params.push(*to_form_params(value, array_prefix)) end else params << {name: namespace.to_s, value: attribute.to_param} end params.sort_by { |pair| pair[:name] } end def remove_trailing_slash!(url_string) trailing_index = (url_string.index("?") || 0) - 1 url_string[trailing_index] = "" if url_string[trailing_index] == "/" end end end