-
-
Save leemour/6916189 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
# A formtastic input which incorporates carrierwave uploader functionality. | |
# | |
# Intelligently adds the cache field, displays and links to the current | |
# value if there is one, adds a class to the wrapper when replacing an | |
# existing value, allows removing an existing value with the checkbox | |
# taking into account validation requirements. | |
# | |
# There are several options: | |
# | |
# * Toggle the replacement field with `replaceable: true/false`. | |
# * The replace file label is translatable as `replace_label` or using option `replace_label: "value"` (like `label`). | |
# * Toggle the remove checkbox with `removable: true/false` (`true` overrides `required`). | |
# * The remove checkbox label is translatable as `remove_label` or using option `remove_label: "value"` (like `label`). | |
# * Override existing file display and links using `existing_html` and `existing_link_html` (like `wrapper_html`). | |
# | |
# Example: `form.input :file, as: "uploader"` | |
# | |
# Copyright (c) Samuel Cochran 2012, under the [MIT license](http://www.opensource.org/licenses/mit-license). | |
class UploaderInput < Formtastic::Inputs::FileInput | |
def linkable? | |
options[:linkable] != false | |
end | |
def replaceable? | |
options[:replaceable] != false | |
end | |
def removable? | |
options[:removable] != false and (options[:removable] == true or not required?) | |
end | |
def method_present? | |
if object.respond_to?("#{method}?") | |
object.send("#{method}?") | |
else | |
object.send(method).present? | |
end | |
end | |
def method_changed? | |
if object.respond_to? "#{method}_changed?" | |
object.send "#{method}_changed?" | |
else | |
false | |
end | |
end | |
def method_was_present? | |
if not method_changed? | |
method_present? | |
else | |
object.send("#{method}_was").present? | |
end | |
end | |
def wrapper_html_options | |
super.tap do |options| | |
options[:class] << " replaceable" if replaceable? | |
options[:class] << " removable" if removable? | |
options[:class] << " present" if method_present? | |
options[:class] << " changed" if method_changed? | |
options[:class] << " was_present" if method_was_present? | |
end | |
end | |
def cache_html | |
if method_changed? | |
builder.hidden_field("#{method}_cache") | |
end or "".html_safe | |
end | |
def file_html | |
builder.file_field(method, input_html_options) | |
end | |
def existing_html_options | |
expand_html_options(options[:existing_html]) do |opts| | |
opts[:class] << "existing" | |
end | |
end | |
def existing_link_html_options | |
expand_html_options(options[:existing_link_html]) do |opts| | |
opts[:class] << "existing" | |
end | |
end | |
def existing_html | |
if method_present? | |
# TODO: Add classes based on mime type for icons, etc. | |
existing = template.content_tag(:span, object.send(method).file.filename, existing_html_options) | |
template.link_to_if linkable?, existing, object.send(method).url, existing_link_html_options | |
end or "".html_safe | |
end | |
def replace_label_html | |
template.content_tag(:label, class: "replace_label") do | |
template.content_tag(:span, localize_action('replace')) | |
end | |
end | |
def replace_html | |
if replaceable? | |
replace_label_html << | |
file_html | |
end or "".html_safe | |
end | |
def remove_html | |
if removable? | |
template.content_tag(:label, class: "remove_label") do | |
template.check_box_tag("#{object_name}[remove_#{method}]", "1", false, id: "#{sanitized_object_name}_remove_#{sanitized_method_name}") << | |
# XXX: There are probably better ways to do these translations using defaults. | |
template.content_tag(:span, localize_action('remove')) | |
end | |
end or "".html_safe | |
end | |
def to_html | |
input_wrapping do | |
label_html << | |
cache_html << | |
if method_was_present? | |
existing_html << | |
replace_html << | |
remove_html | |
else | |
existing_html << | |
file_html | |
end | |
end | |
end | |
protected | |
def expand_html_options opts | |
(opts || {}).dup.tap do |opts| | |
opts[:class] = | |
case opts[:class] | |
when Array | |
opts[:class].dup | |
when nil | |
[] | |
else | |
[opts[:class].to_s] | |
end | |
opts[:data] = | |
case opts[:data] | |
when Hash | |
opts[:data].dup | |
when nil | |
{} | |
else | |
{"" => opts[:data].to_s} | |
end | |
yield opts if block_given? | |
opts[:class] = opts[:class].join(' ') | |
end | |
end | |
private | |
def localize_action(action) | |
attr_scope = "activerecord.attributes.#{object.class.to_s.downcase}" | |
action_scope = "activerecord.attributes.common" | |
attribute = I18n.t(method.to_s, scope: attr_scope) | |
I18n.t(action, scope: action_scope, attribute: attribute) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment