module ActiveScaffold::Actions::Core

Public Class Methods

included(base) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 3
def self.included(base)
  base.class_eval do
    before_filter :handle_user_settings
    before_filter :check_input_device
    before_filter :register_constraints_with_action_columns, :unless => :nested?
    after_filter :clear_flashes
    after_filter :clear_storage
    rescue_from ActiveScaffold::RecordNotAllowed, ActiveScaffold::ActionNotAllowed, :with => :deny_access
  end
  base.helper_method :successful?
  base.helper_method :nested?
  base.helper_method :embedded?
  base.helper_method :loading_embedded?
  base.helper_method :calculate_query
  base.helper_method :new_model
  base.helper_method :touch_device?
  base.helper_method :hover_via_click?
end

Public Instance Methods

render_field() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 21
def render_field
  if request.get?
    render_field_for_inplace_editing
    respond_to do |format|
      format.js { render :action => 'render_field_inplace', :layout => false }
    end
  else
    render_field_for_update_columns
    respond_to { |format| format.js }
  end
end

Protected Instance Methods

accepts?(*types) click to toggle source

Returns true if the client accepts one of the MIME types passed to it ex: accepts? :html, :xml

# File lib/active_scaffold/actions/core.rb, line 157
def accepts?(*types)
  request.accepts.compact.each do |priority|
    if priority == Mime::ALL
      # Because IE always sends */* in the accepts header and we assume
      # that if you really wanted XML or something else you would say so
      # explicitly, we will assume */* to only ask for :html
      return types.include?(:html)
    elsif types.include?(priority.to_sym)
      return true
    end
  end
  false
end
action_confirmation_respond_to_html(confirm_action = action_name.to_sym) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 321
def action_confirmation_respond_to_html(confirm_action = action_name.to_sym)
  link = active_scaffold_config.action_links[confirm_action]
  render :action => 'action_confirmation', :locals => {:record => @record, :link => link}
end
action_update_respond_to_html() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 326
def action_update_respond_to_html
  redirect_to :action => 'index'
end
action_update_respond_to_js() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 330
def action_update_respond_to_js
  render(:action => 'on_action_update')
end
action_update_respond_to_json() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 338
def action_update_respond_to_json
  render :json => successful? ? '' : response_object, :only => list_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(list_columns_names), :methods => virtual_columns(list_columns_names), :status => response_status
end
action_update_respond_to_xml() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 334
def action_update_respond_to_xml
  render :xml => successful? ? '' : response_object, :only => list_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(list_columns_names), :methods => virtual_columns(list_columns_names), :status => response_status
end
active_scaffold_session_storage(id = nil) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 252
def active_scaffold_session_storage(id = nil)
  session_index = active_scaffold_session_storage_key(id)
  session[session_index] ||= {}
  session[session_index]
end
active_scaffold_session_storage_key(id = nil) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 247
def active_scaffold_session_storage_key(id = nil)
  id ||= params[:eid] || "#{params[:controller]}#{"_#{nested_parent_id}" if nested?}"
  "as:#{id}"
end
after_render_field(record, column) click to toggle source

override this method if you want to do something after #render_field

# File lib/active_scaffold/actions/core.rb, line 133
def after_render_field(record, column); end
association_columns(columns) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 368
def association_columns(columns)
  columns.select { |col| active_scaffold_config.model.reflect_on_association(col) }
end
authorized_for?(options = {}) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 135
def authorized_for?(options = {})
  active_scaffold_config.model.authorized_for?(options)
end
beginning_of_chain() click to toggle source

Overide this method on your controller to provide model with named scopes

# File lib/active_scaffold/actions/core.rb, line 204
def beginning_of_chain
  active_scaffold_config.model
end
check_input_device() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 273
def check_input_device
  if request.env['HTTP_USER_AGENT'] && request.env['HTTP_USER_AGENT'][/(iPhone|iPod|iPad)/i]
    session[:input_device_type] = 'TOUCH'
    session[:hover_supported] = false
  else
    session[:input_device_type] = 'MOUSE'
    session[:hover_supported] = true
  end if session[:input_device_type].nil?
end
clear_flashes() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 139
def clear_flashes
  flash.clear if request.xhr?
end
clear_storage() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 258
def clear_storage
  session_index = active_scaffold_session_storage_key
  session.delete(session_index) unless session[session_index].present?
end
conditional_get_support?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 360
def conditional_get_support?
  request.get? && active_scaffold_config.conditional_get_support
end
conditions_from_params() click to toggle source

Builds search conditions by search params for column names. This allows urls like “contacts/list?company_id=5”.

# File lib/active_scaffold/actions/core.rb, line 209
def conditions_from_params
  @conditions_from_params ||= begin
    conditions = {}
    params.except(:controller, :action, :page, :sort, :sort_direction, :format, :id).each do |key, value|
      column = active_scaffold_config.model.columns_hash[key.to_s]
      next unless column
      key = key.to_sym
      not_string = [:string, :text].exclude?(column.type)
      next if active_scaffold_constraints[key]
      next if nested? && nested.param_name == key
      conditions[key] =
        if value.is_a?(Array)
          value.map { |v| v == '' && not_string ? nil : ActiveScaffold::Core.column_type_cast(v, column) }
        else
          value == '' && not_string ? nil : ActiveScaffold::Core.column_type_cast(value, column)
        end
    end
    conditions
  end
end
copy_attributes(orig, dst = nil) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 118
def copy_attributes(orig, dst = nil)
  dst ||= orig.class.new
  attributes = orig.attributes
  if orig.class.respond_to?(:accessible_attributes) && orig.class.accessible_attributes.present?
    attributes.each { |attr, value| dst.send :write_attribute, attr, value if orig.class.accessible_attributes.deny? attr }
    attributes = attributes.slice(*orig.class.accessible_attributes)
  elsif orig.class.respond_to? :protected_attributes
    orig.class.protected_attributes.each { |attr| dst.send :write_attribute, attr, orig[attr] if attr.present? }
    attributes = attributes.except(*orig.class.protected_attributes)
  end
  dst.attributes = attributes
  dst
end
default_formats() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 151
def default_formats
  [:html, :js, :json, :xml]
end
each_marked_record(&block) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 143
def each_marked_record(&block)
  active_scaffold_config.model.as_marked.each(&block)
end
embedded?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 39
def embedded?
  params[:eid]
end
get_row(crud_type_or_security_options = :read) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 242
def get_row(crud_type_or_security_options = :read)
  klass = beginning_of_chain.preload(active_scaffold_preload)
  @record = find_if_allowed(params[:id], crud_type_or_security_options, klass)
end
handle_user_settings() click to toggle source

at some point we need to pass the session and params into config. we'll just take care of that before any particular action occurs by passing those hashes off to the UserSettings class of each action.

# File lib/active_scaffold/actions/core.rb, line 264
def handle_user_settings
  storage = active_scaffold_config.store_user_settings ? active_scaffold_session_storage : {}
  active_scaffold_config.actions.each do |action_name|
    conf_instance = active_scaffold_config.send(action_name) rescue next
    next if conf_instance.class::UserSettings == ActiveScaffold::Config::Base::UserSettings # if it hasn't been extended, skip it
    conf_instance.user = conf_instance.class::UserSettings.new(conf_instance, storage, params)
  end
end
hover_via_click?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 287
def hover_via_click?
  session[:hover_supported] == false
end
loading_embedded?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 35
def loading_embedded?
  @loading_embedded ||= params.delete(:embedded)
end
marked_records() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 147
def marked_records
  active_scaffold_session_storage['marked_records'] ||= {}
end
nested?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 43
def nested?
  false
end
new_model() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 230
def new_model
  model = beginning_of_chain
  if nested? && nested.association && nested.association.collection? && model.columns_hash[column = model.inheritance_column]
    model_name = params.delete(column) # in new action inheritance_column must be in params
    model_name ||= params[:record].delete(column) unless params[:record].blank? # in create action must be inside record key
    model_name = model_name.camelize if model_name
    model_name ||= active_scaffold_config.model.name
    build_options = {column.to_sym => model_name} if model_name
  end
  model.respond_to?(:build) ? model.build(build_options || {}) : model.new
end
objects_for_etag() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 342
def objects_for_etag
  @last_modified ||= @record.updated_at
  [@record, ('xhr' if request.xhr?)]
end
render_field_for_inplace_editing() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 47
def render_field_for_inplace_editing
  @column = active_scaffold_config.columns[params[:update_column]]
  @record = find_if_allowed(params[:id], :crud_type => :update, :column => params[:update_column])
end
render_field_for_update_columns() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 52
def render_field_for_update_columns
  return if (@column = active_scaffold_config.columns[params.delete(:column)]).nil?
  @source_id = params.delete(:source_id)
  @columns = @column.update_columns || []
  @scope = params.delete(:scope)
  action = :subform if @scope
  action ||= params[:id] ? :update : :create
  @main_columns = active_scaffold_config.send(action).columns
  @columns << @column.name if @column.options[:refresh_link] && @columns.exclude?(@column.name)

  @record =
    if @column.send_form_on_update_column
      updated_record_with_form(@main_columns, params[:record], @scope)
    else
      updated_record_with_column(@column, params.delete(:value), @scope)
    end
  set_parent(@record) if params[:parent_controller] && @scope
  after_render_field(@record, @column)
end
response_object() click to toggle source

API response object that will be converted to XML/JSON using to_xxx

# File lib/active_scaffold/actions/core.rb, line 180
def response_object
  @response_object ||= successful? ? (@record || @records) : @record.errors
end
response_status() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 171
def response_status
  if successful?
    action_name == 'create' ? 201 : 200
  else
    422
  end
end
return_to_main() click to toggle source

Redirect to the main page (override if the ActiveScaffold is used as a component on another controllers page) for Javascript degradation

# File lib/active_scaffold/actions/core.rb, line 199
def return_to_main
  redirect_to main_path_to_return
end
set_parent(record) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 99
def set_parent(record)
  controller = "#{params[:parent_controller].camelize}Controller".constantize
  parent_model = controller.active_scaffold_config.model
  child_association = params[:child_association].presence || @scope.split(']').first.sub(/^\[/, '')
  association = parent_model.reflect_on_association(child_association.to_sym).try(:reverse)
  return if association.nil?

  parent = parent_model.new
  copy_attributes(parent_model.find(params[:parent_id]), parent) if params[:parent_id]
  parent.id = params[:parent_id]
  parent = update_record_from_params(parent, active_scaffold_config_for(parent_model).send(params[:parent_id] ? :update : :create).columns, params[:record], true) if @column.send_form_on_update_column
  apply_constraints_to_record(parent) unless params[:parent_id]
  if record.class.reflect_on_association(association).collection?
    record.send(association) << parent
  else
    record.send("#{association}=", parent)
  end
end
successful=(val) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 194
def successful=(val)
  @successful = (val) ? true : false
end
successful?() click to toggle source

Success is the existence of one or more model objects. Most actions circumvent this method by setting @success directly.

# File lib/active_scaffold/actions/core.rb, line 186
def successful?
  if @successful.nil?
    true
  else
    @successful
  end
end
touch_device?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 283
def touch_device?
  session[:input_device_type] == 'TOUCH'
end
updated_record_with_column(column, value, scope) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 90
def updated_record_with_column(column, value, scope)
  record = params[:id] ? find_if_allowed(params[:id], :read).dup : new_model
  apply_constraints_to_record(record) unless scope || params[:id]
  value = column_value_from_param_value(record, column, value)
  record.send "#{column.name}=", value
  record.id = params[:id]
  record
end
updated_record_with_form(columns, attributes, scope) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 72
def updated_record_with_form(columns, attributes, scope)
  if attributes && scope
    attributes = scope.gsub('[', '').split(']').inject(attributes) { |h, idx| h[idx] }
    id = attributes[:id]
  else
    id = params[:id]
  end

  # check permissions and support overriding to_param
  saved_record = find_if_allowed(id, :read) if id
  # call update_record_from_params with new_model
  # in other case some associations can be saved
  record = new_model
  copy_attributes(saved_record, record) if saved_record
  apply_constraints_to_record(record) unless scope
  update_record_from_params(record, columns, attributes || {}, true)
end
view_stale?() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 347
def view_stale?
  objects = objects_for_etag
  if objects.is_a?(Array)
    args = {:etag => objects.to_a}
    args[:last_modified] = @last_modified if @last_modified
  elsif objects.is_a?(Hash)
    args = {:last_modified => @last_modified}.merge(objects)
  else
    args = objects
  end
  stale?(args)
end
virtual_columns(columns) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 364
def virtual_columns(columns)
  columns.reject { |col| active_scaffold_config.model.columns_hash[col.to_s] || active_scaffold_config.model.reflect_on_association(col) }
end

Private Instance Methods

action_formats() click to toggle source
# File lib/active_scaffold/actions/core.rb, line 387
def action_formats
  @action_formats ||=
    if respond_to? "#{action_name}_formats", true
      send("#{action_name}_formats")
    else
      (default_formats + active_scaffold_config.formats).uniq
    end
end
respond_to_action(action) click to toggle source
# File lib/active_scaffold/actions/core.rb, line 374
def respond_to_action(action)
  return unless !conditional_get_support? || view_stale?
  respond_to do |type|
    action_formats.each do |format|
      type.send(format) do
        if respond_to?(method_name = "#{action}_respond_to_#{format}", true)
          send(method_name)
        end
      end
    end
  end
end