module ActiveScaffold::DataStructures class ActionLink # provides a quick way to set any property of the object from a hash def initialize(action, options = {}) # set defaults self.action = action.to_s self.label = action self.confirm = false self.type = :table self.inline = true self.method = :get self.crud_type = :destroy if [:destroy].include?(action.to_sym) self.crud_type = :create if [:create, :new].include?(action.to_sym) self.crud_type = :update if [:edit, :update].include?(action.to_sym) self.crud_type ||= :read self.html_options = {} # apply quick properties options.each_pair do |k, v| setter = "#{k}=" self.send(setter, v) if self.respond_to? setter end end # the action-path for this link. what page to request? this is required! attr_accessor :action # the controller for this action link. if nil, the current controller should be assumed. attr_accessor :controller # a hash of request parameters attr_accessor :parameters # the RESTful method attr_accessor :method # what string to use to represent this action attr_writer :label def label @label.is_a?(Symbol) ? as_(@label) : @label end # if the action requires confirmation attr_writer :confirm def confirm @confirm.is_a?(String) ? as_(@confirm) : @confirm end def confirm? @confirm ? true : false end # if the action uses a DHTML based (i.e. 2-phase) confirmation attr_writer :dhtml_confirm def dhtml_confirm @dhtml_confirm end def dhtml_confirm? @dhtml_confirm end # what method to call on the controller to see if this action_link should be visible # note that this is only the UI part of the security. to prevent URL hax0rz, you also need security on requests (e.g. don't execute update method unless authorized). attr_writer :security_method def security_method @security_method || "#{self.label.underscore.downcase.gsub(/ /, '_')}_authorized?" end # the crud type of the (eventual?) action. different than :method, because this crud action may not be imminent. # this is used to determine record-level authorization (e.g. record.authorized_for?(:action => link.crud_type). # options are :create, :read, :update, and :destroy attr_accessor :crud_type # an "inline" link is inserted into the existing page # exclusive with popup? and page? def inline=(val) @inline = (val == true) self.popup = self.page = false if @inline end def inline?; @inline end # a "popup" link displays in a separate (browser?) window. this will eventually take arguments. # exclusive with inline? and page? def popup=(val) @popup = (val == true) if @popup self.inline = self.page = false # the :method parameter doesn't mix with the :popup parameter # when/if we start using DHTML popups, we can bring :method back self.method = nil end end def popup?; @popup end # a "page" link displays by reloading the current page # exclusive with inline? and popup? def page=(val) @page = (val == true) if @page self.inline = self.popup = false # when :method is defined, ActionView adds an onclick to use a form ... # so it's best to just empty out :method whenever possible. # we only ever need to know @method = :get for things that default to POST. # the only things that default to POST are forms and ajax calls. # when @page = true, we don't use ajax. self.method = nil if method == :get end end def page?; @page end # where the result of this action should insert in the display. # for :type => :table, supported values are: # :top # :bottom # :replace (for updating the entire table) # false (no attempt at positioning) # for :type => :record, supported values are: # :before # :replace # :after # false (no attempt at positioning) attr_writer :position def position return @position unless @position.nil? or @position == true return :replace if self.type == :record return :top if self.type == :table raise "what should the default position be for #{self.type}?" end # what type of link this is. currently supported values are :table and :record. attr_accessor :type # html options for the link attr_accessor :html_options end end