Created
April 2, 2019 03:20
-
-
Save xhocquet/8b58685ac4d97177e960be2fda044f08 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveLinkTo | |
extend ActiveSupport::Concern | |
included do | |
helper_method :active_link_to | |
def active_link_to(name = nil, options = nil, html_options = nil, &block) | |
html_options, options, name = options, name, block if block_given? | |
options ||= {} | |
html_options = convert_options_to_data_attributes(options, html_options) | |
url = url_for(options) | |
html_options["href".freeze] ||= url | |
if url == request.path | |
existing_class = html_options["class".freeze] ||= "" | |
new_class = "#{existing_class} active" | |
html_options["class".freeze] = new_class | |
end | |
view_context.link_to(name, options, html_options, &block) | |
end | |
private | |
def convert_options_to_data_attributes(options, html_options) | |
if html_options | |
html_options = html_options.stringify_keys | |
html_options["data-remote"] = "true".freeze if link_to_remote_options?(options) || link_to_remote_options?(html_options) | |
method = html_options.delete("method".freeze) | |
add_method_to_attributes!(html_options, method) if method | |
html_options | |
else | |
link_to_remote_options?(options) ? { "data-remote" => "true".freeze } : {} | |
end | |
end | |
def link_to_remote_options?(options) | |
if options.is_a?(Hash) | |
options.delete("remote".freeze) || options.delete(:remote) | |
end | |
end | |
def add_method_to_attributes!(html_options, method) | |
if method_not_get_method?(method) && html_options["rel"] !~ /nofollow/ | |
if html_options["rel"].blank? | |
html_options["rel"] = "nofollow" | |
else | |
html_options["rel"] = "#{html_options["rel"]} nofollow" | |
end | |
end | |
html_options["data-method"] = method | |
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 && protect_against_forgery? | |
token ||= form_authenticity_token(form_options: form_options) | |
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token) | |
else | |
"".freeze | |
end | |
end | |
def method_tag(method) | |
tag("input", type: "hidden", name: "_method", value: method.to_s) | |
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 | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment