Created
March 12, 2014 10:01
-
-
Save scarfacedeb/9504029 to your computer and use it in GitHub Desktop.
Polymorphic association for simple_form: 2 implementations
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
class AlbumFormBuilder < SimpleForm::FormBuilder | |
def polymorphic(association, options={}) | |
options = options.dup | |
raise ArgumentError, "Association cannot be used in forms not associated with an object" unless @object | |
raise ArgumentError, "You need to pass types for select" unless options[:types] | |
reflection = find_association_reflection(association) | |
raise "Association #{association.inspect} not found" unless reflection | |
@association = association | |
# Convert symbols into constants | |
types = options.delete(:types).map {|type| type.to_s.classify.constantize } | |
types_options = { | |
as: :select, | |
collection: types.map {|klass| [klass.model_name.human, klass.to_s] }, | |
input_html: { class: "js-polymorphic-type" } | |
} | |
# Get records for select tags | |
@attribute = (reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id" | |
collections ||= options.fetch(:collections) { | |
types.reduce({}) do |h, klass| | |
h[klass.to_s] = collection(klass) | |
h | |
end | |
} | |
collection_options = { | |
class: "select form-control", | |
include_blank: true | |
} | |
# Render tags | |
out = "" | |
out << input("#{association}_type", types_options) | |
out << template.content_tag(:div, class: "form-group form-polymorphic-select js-polymorphic-select") do | |
collections.map do |type, collection| | |
template.select_tag("#{type.downcase}_id", select_options(collection, type), collection_options.dup) | |
end.join.html_safe | |
end | |
out.html_safe | |
end | |
private | |
def collection(klass) | |
klass.pluck(:title, :id) | |
end | |
def select_options(collection, type) | |
template.options_for_select collection, selected?(type) | |
end | |
def selected?(type) | |
object.send("#{@association}_type") == type && object.send(@attribute) | |
end | |
end |
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
class PolymorphicInput < SimpleForm::Inputs::Base | |
def input | |
raise ArgumentError, "You need to pass types for select" unless input_options[:types] | |
# Convert symbols into constants | |
types = input_options.delete(:types).map {|type| type.to_s.classify.constantize } | |
types_options = { | |
as: :select, | |
collection: types.map {|klass| [klass.model_name.human, klass.to_s] }, | |
class: "js-polymorphic-type" | |
} | |
# Get records for select tags | |
collections ||= options.fetch(:collections) { | |
types.reduce({}) do |h, klass| | |
h[klass.to_s] = collection(klass) | |
h | |
end | |
} | |
collection_options = { | |
class: "select form-control", | |
include_blank: true | |
} | |
# Render tags | |
out = "" | |
out << @builder.input_field("#{attribute_name}_type", types_options) | |
out << template.content_tag(:div, class: "form-group form-polymorphic-select js-polymorphic-select") do | |
collections.map do |type, collection| | |
template.select_tag("#{type.downcase}_id", select_options(collection, type), collection_options.dup) | |
end.join.html_safe | |
end | |
out.html_safe | |
end | |
private | |
def collection(klass) | |
klass.pluck(:title, :id) | |
end | |
def select_options(collection, type) | |
template.options_for_select collection, selected?(type) | |
end | |
def selected?(type) | |
object.send("#{attribute_name}_type") == type && object.send("#{attribute_name}_id") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment