module ActiveScaffold::Helpers::FormColumnHelpers

Helpers that assist with the rendering of a Form Column

Helpers that assist with the rendering of a Form Column

Public Instance Methods

active_scaffold_add_existing_input(options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 328
def active_scaffold_add_existing_input(options)
  if ActiveScaffold.js_framework == :prototype && controller.respond_to?(:record_select_config)
    remote_controller = active_scaffold_controller_for(record_select_config.model).controller_path
    options.merge!(:controller => remote_controller)
    options.merge!(active_scaffold_input_text_options)
    record_select_field(options[:name], @record, options)
  else
    select_options = options_for_select(options_for_association(nested.association)) #unless column.through_association?
    select_options ||= options_for_select(active_scaffold_config.model.all.collect {|c| [h(c.to_label), c.id]})
    select_tag 'associated_id', ('<option value="">' + as_(:_select_) + '</option>' + select_options).html_safe unless select_options.empty?
  end
end
active_scaffold_add_existing_label() click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 341
def active_scaffold_add_existing_label
  if controller.respond_to?(:record_select_config)
    record_select_config.model.model_name.human
  else
    active_scaffold_config.model.model_name.human
  end
end
active_scaffold_checkbox_list(column, select_options, associated_ids, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 122
def active_scaffold_checkbox_list(column, select_options, associated_ids, options)
  html = "<ul class=\"checkbox-list\" id=\"#{options[:id]}\">"
  
  select_options.each_with_index do |option, i|
    label, id = option
    this_id = "#{options[:id]}_#{i}_id"
    html << content_tag(:li) do 
      check_box_tag("#{options[:name]}[]", id, associated_ids.include?(id), :id => this_id) <<
      content_tag(:label, h(label), :for => this_id)
    end
  end
  html << '</ul>'
  html << javascript_tag("new DraggableLists('#{options[:id]}')") if column.options[:draggable_lists]
  html.html_safe
end
active_scaffold_input_boolean(column, options) click to toggle source

Column.type-based inputs

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 228
def active_scaffold_input_boolean(column, options)
  select_options = []
  select_options << [as_(:_select_), nil] if !column.virtual? && column.column.null
  select_options << [as_(:true), true]
  select_options << [as_(:false), false]

  select_tag(options[:name], options_for_select(select_options, @record.send(column.name)), options)
end
active_scaffold_input_carrierwave(column, options) click to toggle source
# File lib/active_scaffold/bridges/carrierwave/lib/form_ui.rb, line 4
def active_scaffold_input_carrierwave(column, options)
  options = active_scaffold_input_text_options(options)
  carrierwave = @record.send("#{column.name}")
  if !carrierwave.file.blank?

    remove_field_options = {
      :name => options[:name].gsub(/\[#{column.name}\]$/, "[remove_#{column.name}]"),
      :id => 'remove_' + options[:id],
      :value => false
    }

    cache_field_options = {
      :name => options[:name].gsub(/\[#{column.name}\]$/, "[#{column.name}_cache]"),
      :id => options[:id] + '_cache'
    }

    if ActiveScaffold.js_framework == :jquery
      js_remove_file_code = "$(this).prev('input#remove_#{options[:id]}').val('true'); $(this).parent().hide().next().show(); return false;";
      js_dont_remove_file_code = "$(this).parents('div.carrierwave_controls').find('input#remove_#{options[:id]}').val('false'); return false;";
    else
      js_remove_file_code = "$(this).previous('input#remove_#{options[:id]}').value='true'; $(this).up().hide().next().show(); return false;";
      js_dont_remove_file_code = "$(this).up('div.carrierwave_controls').down('input#remove_#{options[:id]}').value='false'; return false;";
    end

    input = file_field(:record, column.name, options.merge(:onchange => js_dont_remove_file_code))
    content_tag( :div,
      content_tag(:div, (
          get_column_value(@record, column) + " | " +
            hidden_field(:record, "#{column.name}_cache", cache_field_options) +
            hidden_field(:record, "remove_#{column.name}", remove_field_options) +
            content_tag(:a, as_(:remove_file), {:href => '#', :onclick => js_remove_file_code})
        ).html_safe
      ) + content_tag(:div, input, :style => "display: none"),
      :class => 'carrierwave_controls'
    )
  else
    file_field(:record, column.name, options)
  end
end
active_scaffold_input_checkbox(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 206
def active_scaffold_input_checkbox(column, options)
  check_box(:record, column.name, options)
end
active_scaffold_input_country(column, options) click to toggle source
# File lib/active_scaffold/helpers/country_helpers.rb, line 325
def active_scaffold_input_country(column, options)
  select_options = {:prompt => as_(:_select_)}
  select_options.merge!(options)
  options.reverse_merge!(column.options).except!(:prompt, :priority)
  options[:name] += '[]' if options[:multiple]
  country_select(:record, column.name, column.options[:priority] || [:united_states], select_options, options)
end
active_scaffold_input_enum(column, html_options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 143
def active_scaffold_input_enum(column, html_options)
  options = { :selected => @record.send(column.name) }
  options_for_select = column.options[:options].collect do |text, value|
    active_scaffold_translated_option(column, text, value)
  end
  html_options.update(column.options[:html_options] || {})
  options.update(column.options)
  select(:record, column.name, options_for_select, options, html_options)
end
active_scaffold_input_file_column(column, options) click to toggle source
# File lib/active_scaffold/bridges/file_column/lib/form_ui.rb, line 5
def active_scaffold_input_file_column(column, options)
  if @record.send(column.name) 
    # we already have a value?  display the form for deletion.
    if ActiveScaffold.js_framework == :jquery
      js_remove_file_code = "$(this).prev().val('true'); $(this).parent().hide().next().show(); return false;";
    else
      js_remove_file_code = "$(this).previous().value='true'; p=$(this).up(); p.hide(); p.next().show(); return false;";
    end
    content_tag(
      :div, 
      content_tag(
        :div, 
        get_column_value(@record, column) + " " +
        hidden_field(:record, "delete_#{column.name}", :value => "false") +
        " | " +
          content_tag(:a, as_(:remove_file), {:href => '#', :onclick => js_remove_file_code}),
        {}
      ) +
      content_tag(
        :div,
        file_column_field("record", column.name, options),
        :style => "display: none"
      ),
      {}
    )
  else
    # no, just display the file_column_field
    file_column_field("record", column.name, options)
  end
end
active_scaffold_input_for(column, scope = nil, options = {}) click to toggle source

This method decides which input to use for the given column. It does not do any rendering. It only decides which method is responsible for rendering.

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 7
def active_scaffold_input_for(column, scope = nil, options = {})
  options = active_scaffold_input_options(column, scope, options)
  options = update_columns_options(column, scope, options)
  active_scaffold_render_input(column, options)
end
Also aliased as: form_column
active_scaffold_input_options(column, scope = nil, options = {}) click to toggle source

the standard active scaffold options used for class, name and scope

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 69
def active_scaffold_input_options(column, scope = nil, options = {})
  name = scope ? "record#{scope}[#{column.name}]" : "record[#{column.name}]"

  # Fix for keeping unique IDs in subform
  id_control = "record_#{column.name}_#{[params[:eid], params[:id]].compact.join '_'}"
  id_control += scope.gsub(/(\[|\])/, '_').gsub('__', '_').gsub(/_$/, '') if scope

  { :name => name, :class => "#{column.name}-input", :id => id_control}.merge(options)
end
active_scaffold_input_paperclip(column, options) click to toggle source
# File lib/active_scaffold/bridges/paperclip/lib/form_ui.rb, line 4
def active_scaffold_input_paperclip(column, options)
  options = active_scaffold_input_text_options(options)
  input = file_field(:record, column.name, options)
  paperclip = @record.send("#{column.name}")
  if paperclip.file?
    if ActiveScaffold.js_framework == :jquery
      js_remove_file_code = "$(this).prev().val('true'); $(this).parent().hide().next().show(); return false;";
    else
      js_remove_file_code = "$(this).previous().value='true'; $(this).up().hide().next().show(); return false;";
    end
    
    content = active_scaffold_column_paperclip(column, @record)
    content_tag(:div,
      content + " | " +
        hidden_field(:record, "delete_#{column.name}", :value => "false") +
        content_tag(:a, as_(:remove_file), {:href => '#', :onclick => js_remove_file_code}) 
    ) + content_tag(:div, input, :style => "display: none")
  else
    input
  end
end
active_scaffold_input_password(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 210
def active_scaffold_input_password(column, options)
  options = active_scaffold_input_text_options(options)
  password_field :record, column.name, options.merge(column.options)
end
active_scaffold_input_plural_association(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 114
def active_scaffold_input_plural_association(column, options)
  associated_options = @record.send(column.association.name).collect {|r| [r.to_label, r.id]}
  select_options = associated_options | options_for_association(column.association)
  return content_tag(:span, as_(:no_options), :id => options[:id]) if select_options.empty?

  active_scaffold_checkbox_list(column, select_options, associated_options.collect {|a| a[1]}, options)
end
active_scaffold_input_radio(column, html_options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 163
def active_scaffold_input_radio(column, html_options)
  html_options.update(column.options[:html_options] || {})
  column.options[:options].inject('') do |html, (text, value)|
    text, value = active_scaffold_translated_option(column, text, value)
    html << content_tag(:label, radio_button(:record, column.name, value, html_options.merge(:id => html_options[:id] + '-' + value.to_s)) + text)
  end.html_safe
end
active_scaffold_input_record_select(column, options) click to toggle source

requires RecordSelect plugin to be installed and configured. … maybe this should be provided in a bridge?

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 173
def active_scaffold_input_record_select(column, options)
  if column.singular_association?
    multiple = false
    multiple = column.options[:html_options][:multiple] if column.options[:html_options] &&  column.options[:html_options][:multiple]
    active_scaffold_record_select(column, options, @record.send(column.name), multiple)
  elsif column.plural_association?
    active_scaffold_record_select(column, options, @record.send(column.name), true)
  end
end
active_scaffold_input_select(column, html_options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 153
def active_scaffold_input_select(column, html_options)
  if column.singular_association?
    active_scaffold_input_singular_association(column, html_options)
  elsif column.plural_association?
    active_scaffold_input_plural_association(column, html_options)
  else
    active_scaffold_input_enum(column, html_options)
  end
end
active_scaffold_input_singular_association(column, html_options) click to toggle source

Form input methods

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 97
def active_scaffold_input_singular_association(column, html_options)
  associated = @record.send(column.association.name)

  select_options = options_for_association(column.association)
  select_options.unshift([ associated.to_label, associated.id ]) unless associated.nil? or select_options.find {|label, id| id == associated.id}

  selected = associated.nil? ? nil : associated.id
  method = column.name
  #html_options[:name] += '[id]'
  options = {:selected => selected, :include_blank => as_(:_select_)}

  html_options.update(column.options[:html_options] || {})
  options.update(column.options)
  html_options[:name] = "#{html_options[:name]}[]" if (html_options[:multiple] == true && !html_options[:name].to_s.ends_with?("[]"))
  select(:record, method, select_options.uniq, options, html_options)
end
active_scaffold_input_text_options(options = {}) click to toggle source

the standard active scaffold options used for textual inputs

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 62
def active_scaffold_input_text_options(options = {})
  options[:autocomplete] = 'off'
  options[:class] = "#{options[:class]} text-input".strip
  options
end
active_scaffold_input_textarea(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 215
def active_scaffold_input_textarea(column, options)
  text_area(:record, column.name, options.merge(:cols => column.options[:cols], :rows => column.options[:rows], :size => column.options[:size]))
end
active_scaffold_input_usa_state(column, options) click to toggle source
# File lib/active_scaffold/helpers/country_helpers.rb, line 333
def active_scaffold_input_usa_state(column, options)
  select_options = {:prompt => as_(:_select_)}
  select_options.merge!(options)
  options.reverse_merge!(column.options).except!(:prompt, :priority)
  options[:name] += '[]' if options[:multiple]
  usa_state_select(:record, column.name, column.options[:priority], select_options, options)
end
active_scaffold_input_virtual(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 219
def active_scaffold_input_virtual(column, options)
  options = active_scaffold_input_text_options(options)
  text_field :record, column.name, options.merge(column.options)
end
active_scaffold_record_select(column, options, value, multiple) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 183
def active_scaffold_record_select(column, options, value, multiple)
  unless column.association
    raise ArgumentError, "record_select can only work against associations (and #{column.name} is not).  A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user)."
  end
  remote_controller = active_scaffold_controller_for(column.association.klass).controller_path

  # if the opposite association is a :belongs_to (in that case association in this class must be has_one or has_many)
  # then only show records that have not been associated yet
  if [:has_one, :has_many].include?(column.association.macro)
    params.merge!({column.association.primary_key_name => ''})
  end
 
  record_select_options = {:controller => remote_controller, :id => options[:id]}
  record_select_options.merge!(active_scaffold_input_text_options)
  record_select_options.merge!(column.options)

  if multiple
    record_multi_select_field(options[:name], value || [], record_select_options)
  else
    record_select_field(options[:name], value || column.association.klass.new, record_select_options)
  end
end
active_scaffold_render_input(column, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 15
def active_scaffold_render_input(column, options)
  begin
    # first, check if the dev has created an override for this specific field
    if override_form_field?(column)
      send(override_form_field(column), @record, options)
    # second, check if the dev has specified a valid form_ui for this column
    elsif column.form_ui and override_input?(column.form_ui)
      send(override_input(column.form_ui), column, options)
    # fallback: we get to make the decision
    else
      if column.association
        if column.form_ui.nil?
          # its an association and nothing is specified, we will assume form_ui :select
          active_scaffold_input_select(column, options)
        else
          # if we get here, it's because the column has a form_ui but not one ActiveScaffold knows about.
          raise "Unknown form_ui `#{column.form_ui}' for column `#{column.name}'"
        end
      elsif column.virtual?
        active_scaffold_input_virtual(column, options)

      else # regular model attribute column
        # if we (or someone else) have created a custom render option for the column type, use that
        if override_input?(column.column.type)
          send(override_input(column.column.type), column, options)
        # final ultimate fallback: use rails' generic input method
        else
          # for textual fields we pass different options
          text_types = [:text, :string, :integer, :float, :decimal, :date, :time, :datetime]
          options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
          if column.column.type == :string && options[:maxlength].blank?
            options[:maxlength] = column.column.limit
            options[:size] ||= ActionView::Helpers::InstanceTag::DEFAULT_FIELD_OPTIONS["size"]
          end
          options[:include_blank] = true if column.column.null and [:date, :datetime, :time].include?(column.column.type)
          options[:value] = format_number_value(@record.send(column.name), column.options) if column.column.number?
          text_field(:record, column.name, options.merge(column.options))
        end
      end
    end
  rescue Exception => e
    logger.error Time.now.to_s + "#{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}"
    raise e
  end
end
active_scaffold_translated_option(column, text, value = nil) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 138
def active_scaffold_translated_option(column, text, value = nil)
  value = text if value.nil?
  [(text.is_a?(Symbol) ? column.active_record_class.human_attribute_name(text) : text), value]
end
column_renders_as(column) click to toggle source

Macro-level rendering decisions for columns

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 308
def column_renders_as(column)
  if column.is_a? ActiveScaffold::DataStructures::ActionColumns
    return :subsection
  elsif column.active_record_class.locking_column.to_s == column.name.to_s or column.form_ui == :hidden
    return :hidden
  elsif column.association.nil? or column.form_ui or !active_scaffold_config_for(column.association.klass).actions.include?(:subform)
    return :field
  else
    return :subform
  end
end
column_scope(column) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 320
def column_scope(column)
  if column.plural_association?
    "[#{column.name}][#{@record.id || generate_temporary_id}]"
  else
    "[#{column.name}]"
  end
end
form_column(column, scope = nil, options = {})
form_partial_for_column(column, renders_as = nil) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 282
def form_partial_for_column(column, renders_as = nil)
  renders_as ||= column_renders_as(column)
  if override_form_field_partial?(column)
    override_form_field_partial(column)
  elsif renders_as == :field or override_form_field?(column)
    "form_attribute"
  elsif renders_as == :subform
    "form_association"
  elsif renders_as == :hidden
    "form_hidden_attribute"
  end
end
onsubmit() click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 237
def onsubmit
end
override_form_field(column) click to toggle source

the naming convention for overriding form fields with helpers

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 269
def override_form_field(column)
  "#{column.name}_form_column"
end
override_form_field?(column) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 264
def override_form_field?(column)
  respond_to?(override_form_field(column))
end
override_form_field_partial(column) click to toggle source

the naming convention for overriding form fields with partials

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 260
def override_form_field_partial(column)
  "#{column.name}_form_column"
end
override_form_field_partial?(column) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 254
def override_form_field_partial?(column)
  path, partial_name = partial_pieces(override_form_field_partial(column))
  template_exists?(partial_name, path, true)
end
override_input(form_ui) click to toggle source

the naming convention for overriding form input types with helpers

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 278
def override_input(form_ui)
  "active_scaffold_input_#{form_ui}"
end
override_input?(form_ui) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 273
def override_input?(form_ui)
  respond_to?(override_input(form_ui))
end
override_subform_partial(column, subform_partial) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 250
def override_subform_partial(column, subform_partial)
  File.join(active_scaffold_controller_for(column.association.klass).controller_path, subform_partial) if column_renders_as(column) == :subform
end
override_subform_partial?(column, subform_partial) click to toggle source

add functionality for overriding subform partials from association class path

# File lib/active_scaffold/helpers/form_column_helpers.rb, line 245
def override_subform_partial?(column, subform_partial)
  path, partial_name = partial_pieces(override_subform_partial(column, subform_partial))
  template_exists?(partial_name, path, true)
end
subform_partial_for_column(column) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 295
def subform_partial_for_column(column)
  subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
  if override_subform_partial?(column, subform_partial)
    override_subform_partial(column, subform_partial)
  else
    subform_partial
  end
end
update_columns_options(column, scope, options) click to toggle source
# File lib/active_scaffold/helpers/form_column_helpers.rb, line 79
def update_columns_options(column, scope, options)
  if column.update_columns
    form_action = params[:action] == 'edit' ? :update : :create
    url_params = {:action => 'render_field', :id => params[:id], :column => column.name, :update_columns => column.update_columns}
    url_params[:eid] = params[:eid] if params[:eid]
    url_params[:controller] = controller.class.active_scaffold_controller_for(@record.class).controller_path if scope
    url_params[:scope] = params[:scope] if scope

    options[:class] = "#{options[:class]} update_form".strip
    options['data-update_url'] = url_for(url_params)
  end
  options
end