PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/form_column_helpers.rb

https://github.com/KyleSuttie/BASEBALL_
Ruby | 338 lines | 260 code | 47 blank | 31 comment | 43 complexity | 94f68b6950e1186571f07ee9538c1dc9 MD5 | raw file
  1. module ActiveScaffold
  2. module Helpers
  3. # Helpers that assist with the rendering of a Form Column
  4. module FormColumnHelpers
  5. # This method decides which input to use for the given column.
  6. # It does not do any rendering. It only decides which method is responsible for rendering.
  7. def active_scaffold_input_for(column, scope = nil, options = {})
  8. begin
  9. options = active_scaffold_input_options(column, scope, options)
  10. options = javascript_for_update_column(column, scope, options)
  11. # first, check if the dev has created an override for this specific field
  12. if override_form_field?(column)
  13. send(override_form_field(column), @record, options)
  14. # second, check if the dev has specified a valid form_ui for this column
  15. elsif column.form_ui and override_input?(column.form_ui)
  16. send(override_input(column.form_ui), column, options)
  17. # fallback: we get to make the decision
  18. else
  19. if column.association
  20. # if we get here, it's because the column has a form_ui but not one ActiveScaffold knows about.
  21. raise "Unknown form_ui `#{column.form_ui}' for column `#{column.name}'"
  22. elsif column.virtual?
  23. active_scaffold_input_virtual(column, options)
  24. else # regular model attribute column
  25. # if we (or someone else) have created a custom render option for the column type, use that
  26. if override_input?(column.column.type)
  27. send(override_input(column.column.type), column, options)
  28. # final ultimate fallback: use rails' generic input method
  29. else
  30. # for textual fields we pass different options
  31. text_types = [:text, :string, :integer, :float, :decimal]
  32. date_types = [:date, :datetime, :time]
  33. options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
  34. options = active_scaffold_input_date_options(column, options) if date_types.include?(column.column.type)
  35. if column.column.type == :string && options[:maxlength].blank?
  36. options[:maxlength] = column.column.limit
  37. options[:size] ||= ActionView::Helpers::InstanceTag::DEFAULT_FIELD_OPTIONS["size"]
  38. end
  39. options[:value] = format_number_value(@record.send(column.name), column.options) if column.column.number?
  40. input(:record, column.name, options.merge(column.options))
  41. end
  42. end
  43. end
  44. rescue Exception => e
  45. logger.error Time.now.to_s + "#{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{@controller.class}"
  46. raise e
  47. end
  48. end
  49. alias form_column active_scaffold_input_for
  50. # the standard active scaffold options used for textual inputs
  51. def active_scaffold_input_text_options(options = {})
  52. options[:autocomplete] = 'off'
  53. options[:class] = "#{options[:class]} text-input".strip
  54. options
  55. end
  56. # the standard active scaffold options used for date, datetime and time inputs
  57. def active_scaffold_input_date_options(column, options = {})
  58. options[:include_blank] = true if column.column.null
  59. options[:prefix] = options[:name].gsub("[#{column.name}]", '')
  60. options
  61. end
  62. # the standard active scaffold options used for class, name and scope
  63. def active_scaffold_input_options(column, scope = nil, options = {})
  64. name = scope ? "record#{scope}[#{column.name}]" : "record[#{column.name}]"
  65. # Fix for keeping unique IDs in subform
  66. id_control = "record_#{column.name}_#{[params[:eid], params[:id]].compact.join '_'}"
  67. id_control += scope.gsub(/(\[|\])/, '_').gsub('__', '_').gsub(/_$/, '') if scope
  68. { :name => name, :class => "#{column.name}-input", :id => id_control}.merge(options)
  69. end
  70. def javascript_for_update_column(column, scope, options)
  71. if column.update_column
  72. form_action = :create
  73. form_action = :update if params[:action] == 'edit'
  74. url_params = {
  75. :action => 'render_field',
  76. :id => params[:id],
  77. :column => column.name,
  78. :update_column => column.update_column,
  79. :eid => params[:eid],
  80. :scope => scope
  81. }
  82. url_params[:controller] = controller.class.active_scaffold_controller_for(@record.class).controller_path if scope
  83. ajax_options = {:method => :get,
  84. :url => url_for(url_params), :with => column.send_form_on_update_column ? "Form.serialize(this.form)" : "'value=' + this.value",
  85. :after => "$('#{loading_indicator_id(:action => form_action, :id => params[:id])}').style.visibility = 'visible'; Form.disable('#{element_form_id(:action => form_action)}');",
  86. :complete => "$('#{loading_indicator_id(:action => form_action, :id => params[:id])}').style.visibility = 'hidden'; Form.enable('#{element_form_id(:action => form_action)}');"}
  87. options[:onchange] = "#{remote_function(ajax_options)};#{options[:onchange]}"
  88. end
  89. options
  90. end
  91. ##
  92. ## Form input methods
  93. ##
  94. def active_scaffold_input_singular_association(column, html_options)
  95. associated = @record.send(column.association.name)
  96. select_options = options_for_association(column.association)
  97. select_options.unshift([ associated.to_label, associated.id ]) unless associated.nil? or select_options.find {|label, id| id == associated.id}
  98. selected = associated.nil? ? nil : associated.id
  99. method = column.name
  100. #html_options[:name] += '[id]'
  101. options = {:selected => selected, :include_blank => as_(:_select_)}
  102. html_options.update(column.options[:html_options] || {})
  103. options.update(column.options)
  104. select(:record, method, select_options.uniq, options, html_options)
  105. end
  106. def active_scaffold_input_plural_association(column, options)
  107. associated_options = @record.send(column.association.name).collect {|r| [r.to_label, r.id]}
  108. select_options = associated_options | options_for_association(column.association)
  109. return content_tag(:span, as_(:no_options), :id => options[:id]) if select_options.empty?
  110. html = "<ul class=\"checkbox-list\" id=\"#{options[:id]}\">"
  111. associated_ids = associated_options.collect {|a| a[1]}
  112. select_options.each_with_index do |option, i|
  113. label, id = option
  114. this_name = "#{options[:name]}[]"
  115. this_id = "#{options[:id]}_#{i}_id"
  116. html << "<li>"
  117. html << check_box_tag(this_name, id, associated_ids.include?(id), :id => this_id)
  118. html << "<label for='#{this_id}'>"
  119. html << label
  120. html << "</label>"
  121. html << "</li>"
  122. end
  123. html << '</ul>'
  124. html << javascript_tag("new DraggableLists('#{options[:id]}')") if column.options[:draggable_lists]
  125. html
  126. end
  127. def active_scaffold_translated_option(column, text, value = nil)
  128. value = text if value.nil?
  129. [(text.is_a?(Symbol) ? column.active_record_class.human_attribute_name(text) : text), value.to_s]
  130. end
  131. def active_scaffold_translated_options(column)
  132. column.options[:options].collect do |text, value|
  133. active_scaffold_translated_option(column, text, value)
  134. end
  135. end
  136. def active_scaffold_input_select(column, html_options)
  137. if column.singular_association?
  138. active_scaffold_input_singular_association(column, html_options)
  139. elsif column.plural_association?
  140. active_scaffold_input_plural_association(column, html_options)
  141. else
  142. options = { :selected => @record.send(column.name).to_s }
  143. options_for_select = active_scaffold_translated_options(column)
  144. html_options.update(column.options[:html_options] || {})
  145. options.update(column.options)
  146. select(:record, column.name, options_for_select, options, html_options)
  147. end
  148. end
  149. def active_scaffold_input_radio(column, html_options)
  150. html_options.update(column.options[:html_options] || {})
  151. column.options[:options].inject('') do |html, (text, value)|
  152. text, value = active_scaffold_translated_option(column, text, value)
  153. html << content_tag(:label, radio_button(:record, column.name, value, html_options.merge(:id => html_options[:id] + '-' + value.to_s)) + text)
  154. end
  155. end
  156. def active_scaffold_input_checkbox(column, options)
  157. check_box(:record, column.name, options)
  158. end
  159. def active_scaffold_input_password(column, options)
  160. options = active_scaffold_input_text_options(options)
  161. password_field :record, column.name, options.merge(column.options)
  162. end
  163. def active_scaffold_input_textarea(column, options)
  164. text_area(:record, column.name, options.merge(:cols => column.options[:cols], :rows => column.options[:rows], :size => column.options[:size]))
  165. end
  166. def active_scaffold_input_virtual(column, options)
  167. options = active_scaffold_input_text_options(options)
  168. text_field :record, column.name, options.merge(column.options)
  169. end
  170. #
  171. # Column.type-based inputs
  172. #
  173. def active_scaffold_input_boolean(column, options)
  174. select_options = []
  175. select_options << [as_(:_select_), nil] if column.column.null
  176. select_options << [as_(:true), true]
  177. select_options << [as_(:false), false]
  178. select_tag(options[:name], options_for_select(select_options, @record.send(column.name)), options)
  179. end
  180. def onsubmit
  181. end
  182. ##
  183. ## Form column override signatures
  184. ##
  185. # add functionality for overriding subform partials from association class path
  186. def override_subform_partial?(column, subform_partial)
  187. path, partial_name = partial_pieces(override_subform_partial(column, subform_partial))
  188. template_exists?(File.join(path, "_#{partial_name}"))
  189. end
  190. def override_subform_partial(column, subform_partial)
  191. File.join(active_scaffold_controller_for(column.association.klass).controller_path, subform_partial) if column_renders_as(column) == :subform
  192. end
  193. def override_form_field_partial?(column)
  194. path, partial_name = partial_pieces(override_form_field_partial(column))
  195. template_exists?(File.join(path, "_#{partial_name}"), true)
  196. end
  197. # the naming convention for overriding form fields with helpers
  198. def override_form_field_partial(column)
  199. path = active_scaffold_controller_for(column.active_record_class).controller_path
  200. File.join(path, "#{clean_column_name(column.name)}_form_column")
  201. end
  202. def override_form_field(column)
  203. method = override_form_field_name(column)
  204. return method if respond_to?(method)
  205. old_method = override_form_field_name(column, true)
  206. if respond_to?(old_method)
  207. ActiveSupport::Deprecation.warn("You are using an old naming schema for overrides, you should name the helper #{method} instead of #{old_method}")
  208. old_method
  209. end
  210. end
  211. alias_method :override_form_field?, :override_form_field
  212. # the naming convention for overriding form fields with helpers
  213. def override_form_field_name(column, old = false)
  214. "#{clean_class_name(column.active_record_class.name) + '_' unless old}#{clean_column_name(column.name)}_form_column"
  215. end
  216. def override_input?(form_ui)
  217. respond_to?(override_input(form_ui))
  218. end
  219. # the naming convention for overriding form input types with helpers
  220. def override_input(form_ui)
  221. "active_scaffold_input_#{form_ui}"
  222. end
  223. def form_partial_for_column(column)
  224. if override_form_field_partial?(column)
  225. override_form_field_partial(column)
  226. elsif column_renders_as(column) == :field or override_form_field?(column)
  227. "form_attribute"
  228. elsif column_renders_as(column) == :subform
  229. "form_association"
  230. elsif column_renders_as(column) == :hidden
  231. "form_hidden_attribute"
  232. end
  233. end
  234. def subform_partial_for_column(column)
  235. subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
  236. if override_subform_partial?(column, subform_partial)
  237. override_subform_partial(column, subform_partial)
  238. else
  239. subform_partial
  240. end
  241. end
  242. ##
  243. ## Macro-level rendering decisions for columns
  244. ##
  245. def column_renders_as(column)
  246. if column.is_a? ActiveScaffold::DataStructures::ActionColumns
  247. return :subsection
  248. elsif column.active_record_class.locking_column.to_s == column.name.to_s or column.form_ui == :hidden
  249. return :hidden
  250. elsif column.association.nil? or column.form_ui or !active_scaffold_config_for(column.association.klass).actions.include?(:subform)
  251. return :field
  252. else
  253. return :subform
  254. end
  255. end
  256. def is_subsection?(column)
  257. column_renders_as(column) == :subsection
  258. end
  259. def is_subform?(column)
  260. column_renders_as(column) == :subform
  261. end
  262. def column_scope(column)
  263. if column.plural_association?
  264. "[#{column.name}][#{@record.id || generate_temporary_id}]"
  265. else
  266. "[#{column.name}]"
  267. end
  268. end
  269. def active_scaffold_add_existing_input(options)
  270. if controller.respond_to?(:record_select_config)
  271. remote_controller = active_scaffold_controller_for(record_select_config.model).controller_path
  272. options.merge!(:controller => remote_controller)
  273. options.merge!(active_scaffold_input_text_options)
  274. record_select_field(options[:name], @record, options)
  275. else
  276. column = active_scaffold_config_for(params[:parent_model]).columns[params[:parent_column]]
  277. select_options = options_for_select(options_for_association(column.association)) unless column.through_association?
  278. select_options ||= options_for_select(active_scaffold_config.model.find(:all).collect {|c| [h(c.to_label), c.id]})
  279. select_tag 'associated_id', '<option value="">' + as_(:_select_) + '</option>' + select_options unless select_options.empty?
  280. end
  281. end
  282. def active_scaffold_add_existing_label
  283. if controller.respond_to?(:record_select_config)
  284. record_select_config.model.human_name
  285. else
  286. active_scaffold_config.model.human_name
  287. end
  288. end
  289. end
  290. end
  291. end