module BTech module Rest module Actions # Default index action. Feel free to override. def index build_resources if @resources.size > 1 # Records for a nested resource (act on the second-to-last parent). parent = @resources[@resources.size - 2][:record] records_name = parent.class.name.underscore.pluralize records = parent.instance_eval("#{@resources.last[:parent_resource_method] || @resources.last[:name]}").paginate :page => params[:page], :per_page => 10 else # Records for single resource. records_name = get_model_name.pluralize records = @resources.last[:model].all.paginate(:page => params[:page], :per_page => 10) end instance_variable_set "@#{records_name}", records end # Default show action. Feel free to override. def show build_resources render :partial => @resources.last[:show_partial], :layout => true, :locals => {get_model_symbol => get_record, :resources => @resources} end # Default new action. Feel free to override. def new build_resources render_new_or_edit end # Default edit action. Feel free to override. def edit build_resources render_new_or_edit end # Default create action. Feel free to override. def create build_resources if get_record.update_attributes params[get_model_symbol] redirect_to build_resource_url(@resources) else render_new_or_edit end end # Default update action. Feel free to override. def update build_resources if get_record.update_attributes params[get_model_symbol] redirect_to build_resource_url(@resources) else render_new_or_edit end end # Default destroy action. Feel free to override. def destroy build_resources get_record.destroy @resources.last.delete :record redirect_to build_resource_url(@resources) end protected # Convenience method for rendering the new or edit partial. def render_new_or_edit render :partial => @resources.last[:new_or_edit_partial], :layout => true, :locals => {get_model_symbol => get_record, :resources => @resources} end # Builds the RESTful parent URL based on an array of resources. def build_parent_url resources = [] namespaces = resources.last[:namespaces] url = namespaces && !namespaces.empty? ? '/' + resources.last[:namespaces].join('/') : nil if resources.size > 1 resources.slice(0...resources.size - 1).each do |resource| url = [url, resource[:name], resource[:parent_id]].join('/') end end url end # A convenience method for builing RESTful URLs based on an array of resources with the # option to override the default action. This is also defined as a helper method (see base.rb). def build_resource_url resources = [], action = :index name = resources.last[:name] id = resources.last[:record].id if resources.last[:record] parent_url = build_parent_url(resources) url = parent_url ? [parent_url, name].join('/') : '/' + name case action when :show then url = [url, id].compact.join('/') when :new then url = [url, "new"].compact.join('/') when :edit then url = [url, id, "edit"].compact.join('/') when :update then url = [url, id].compact.join('/') if name == name.pluralize when :destroy then url = [url, id].compact.join('/') if name == name.pluralize end logger.debug "Resource URL: #{url}" url end private # Answers the name of the current model. def get_model_name @resources.last[:model].name.underscore end # Answers the symbol of the current model. def get_model_symbol get_model_name.to_sym end # Answers the current record (a.k.a. the record of the last resource). def get_record instance_variable_get "@#{get_model_name}" end # Builds all resources for the controller(s). def build_resources @resources ||= [] if @resources.empty? controller_name = self.class.name add_resource controller_name, @resources @resources.reverse! end # Convenience for accessing the current record. instance_variable_set "@#{get_model_name}", @resources.last[:record] end # Convenience method for answering back a properly camelized controller name. def camelize_controller_name name name = name.gsub(/^(\w)/) {|c| c.capitalize} name += "Controller" unless name.include? "Controller" name end # Answers the child or parent controller namespaces (array) and name (string). # Accepts the following argruments: # * *full_name* - The fully namespaced controller (i.e. PostsController) or parent name (i.e. protected_pages). # Usage: # * Input: Public::PostsController, Output: [Public], "PostsController" # * Input: member_manage_posts, Output: [Member, Manage], "PostsController" # * Input: posts, Output: nil, "PostsController" def get_controller_namespaces_and_name full_name if full_name delimiter = full_name.include?("Controller") ? "::" : '_' if full_name.include? delimiter namespaces = full_name.split delimiter name = camelize_controller_name namespaces.pop return namespaces.collect(&:capitalize), name else return nil, camelize_controller_name(full_name) end end end # Recursively walks the controller belongs_to hierarchy (if any) adding new resources along the way. def add_resource controller_name, resources logger.debug "Adding resource '#{controller_name}' to resources (size = #{resources.size})." resource = configure_resource controller_name if resource resources << resource # Recursively add parents (if any). if resource[:controller].methods.include? "parent_resource" add_resource resource[:controller].parent_resource, resources end end end # Configures a resource via belongs_to name refrence in controller. By default the controller and model # are assumed to use the same root name regardless of singular or plural context. def configure_resource controller_name namespaces, name = get_controller_namespaces_and_name controller_name controller = [namespaces, name].compact.join("::").constantize name = name.chomp("Controller").underscore parent_key = name.singularize + "_id" resource = controller.resource_options || {} resource.reverse_merge! :parent_key => parent_key, :parent_id => params[parent_key], :name => name, :controller => controller, :label => name.capitalize, :namespaces => (namespaces.collect(&:downcase) if namespaces), :show_partial => '/' + [namespaces, name, "show"].compact.join('/').downcase, :new_or_edit_partial => '/' + [namespaces, name, "new_or_edit"].compact.join('/').downcase begin resource.reverse_merge! :model => name.singularize.camelize.constantize rescue NameError logger.warn "Unable to constantize: " + name end add_record resource end # Adds the current record to the resource based on position in chain. def add_record resource if resource[:model] if params.include? resource[:parent_key] # Nested parent. resource[:record] = resource[:model].find resource[:parent_id] if resource[:parent_id] else # Single resource and/or end of nested chain. resource[:record] = params[:id] ? resource[:model].find(params[:id]) : resource[:model].new end else logger.error "Invalid model. Check that your controller and model are of the same name, otherwise specify the model as a resource option." end resource end end end end