require "action_view" module ActionView module Helpers class FormBuilder class PropertySetFormBuilderProxy attr_reader :property_set, :template, :object_name, :object def initialize(property_set, template, object_name, object) @property_set = property_set @template = template @object_name = object_name @object = object end def check_box(property, options = {}, checked_value = "1", unchecked_value = "0") options = prepare_options(property, options) do |properties| properties.send(:"#{property}?") end template.check_box(object_name, property, options, checked_value, unchecked_value) end def radio_button(property, checked_value = "1", options = {}) options[:id] ||= "#{object_name}_#{property_set}_#{property}_#{checked_value}" options = prepare_options(property, options) do |properties| properties.send(property.to_s) == checked_value end template.radio_button(object_name, property, checked_value, options) end def text_field(property, options = {}) template.text_field(object_name, property, prepare_id_name(property, options)) end def hidden_field(property, options = {}) options = prepare_id_name(property, options) unless options.key?(:value) options[:value] = cast_boolean(options[:object].send(property_set).send(property)) end template.hidden_field(object_name, property, options) end def select(property, choices, options = {}, html_options = {}) options = prepare_id_name(property, options) current_value = options[:object].send(property_set).send(property) template.select("#{object_name}[#{property_set}]", property, choices, {selected: current_value}, html_options) end private def prepare_id_name(property, options) throw "Invalid options type #{options.inspect}" unless options.is_a?(Hash) options.clone.tap do |prepared_options| prepared_options[:object] = object || fetch_target_object prepared_options[:id] ||= "#{object_name}_#{property_set}_#{property}" prepared_options[:name] = "#{object_name}[#{property_set}][#{property}]" end end def fetch_target_object instance = template.instance_variable_get(:"@#{object_name}") throw "No @#{object_name} in scope" if instance.nil? throw "The property_set_check_box only works on models with property set #{property_set}" unless instance.respond_to?(property_set) instance end def prepare_options(property, options, &block) options = prepare_id_name(property, options) options[:checked] = yield(options[:object].send(property_set)) options end def cast_boolean(value) case value when TrueClass then "1" when FalseClass then "0" else value end end end def property_set(identifier) PropertySetFormBuilderProxy.new(identifier, @template, object_name, object) end end end end