Skip to content

Instantly share code, notes, and snippets.

@futura
Created February 20, 2012 14:46
Show Gist options
  • Save futura/1869526 to your computer and use it in GitHub Desktop.
Save futura/1869526 to your computer and use it in GitHub Desktop.
Custom inputs for Formtastic: CheckBoxesWithOtherInput and StringAsOtherInput
# Assumes serialized attribute (can use ActiveRecord Store with Rails 3.2+)
# Splits attribute into hash with key for checkboxes (default 'checks')
# Use with TextFieldsWithOther to add 'other' key for text values ...
#
# symptoms[checks] <-- Array
# symptoms[other] <-- String
#
# For a nested hash, define a top-level method (or with ActiveRecord::Store, define an accessor)
# In model ...
# class Patient < ActiveRecord::Base
# store :symptoms, accessors: [ 'attention', ... ]
# end
#
# Gives you access to ...
# <%= f.input 'attention', :as => :check_boxes_with_other, :collection => my_predefined_values %>
# attention[checks]
# <%= f.input 'attention', :as => :string_as_other %>
# attention[other]
# <%= f.input 'attention', :attr => 'age_of_onset', :as => :string_as_other %>
# attention[age_of_onset]
class CheckBoxesWithOtherInput < Formtastic::Inputs::CheckBoxesInput
# Optional key to use for 'checks' hash; defaults to 'checks'
def key_for_checked_hash
options[:checked_key] || 'checks'
end
# Override CheckBoxesInput to add key_for_checked_hash subhash
def input_name
"#{object_name}[#{association_primary_key || method}][#{key_for_checked_hash}][]"
end
# Override CheckBoxesInput to add key_for_checked_hash subhash; returns an array
def selected_values
if object.respond_to?(method)
checked_hash = object.send(method) || { key_for_checked_hash => [] }
selected_items = [checked_hash[key_for_checked_hash]].compact.flatten
[*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
else
[]
end
end
end
# Assumes serialized attribute (can use ActiveRecord Store with Rails 3.2+)
# Works with CheckBoxesWithOtherInput to split attribute into hash with its own attr key (defaults to 'other') for text values ...
# symptoms[checks] <-- Array
# symptoms[other] <-- String
#
# For a nested hash, define a top-level method (or with ActiveRecord::Store, define an accessor)
# In model ...
# class Patient < ActiveRecord::Base
# store :symptoms, accessors: [ 'attention', ... ]
# end
#
# Gives you access to ...
# <%= f.input 'attention', :as => :check_boxes_with_other, :collection => my_predefined_values %>
# attention[checks]
# <%= f.input 'attention', :as => :string_as_other %>
# attention[other]
# <%= f.input 'attention', :attr => 'age_of_onset', :as => :string_as_other %>
# attention[age_of_onset]
class StringAsOtherInput < Formtastic::Inputs::StringInput
def attr_key
options[:attr] || 'other'
end
# Overrides `input_html_options` to provide a `name` and `value` attribute.
def input_html_options
{
:name => "#{object_name}[#{association_primary_key || method}][#{attr_key}]",
:value => value
}.merge(super)
end
# Returns a string
def value
if object.respond_to?(method)
attr_hash = object.send(method) || { attr_key => '' }
val = attr_hash[attr_key]
else
''
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment