Created
December 24, 2016 20:33
-
-
Save MicahBrown/a3bdbf8dc776c6f6a09aeb77296edb55 to your computer and use it in GitHub Desktop.
Load and Authorize Resource
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_support/concern' | |
# Derived from cancan gem (https://github.com/ryanb/cancan) | |
# Loads current resource using controller resource. | |
# | |
# Options: | |
# :parent - If the resource symbol is specified, we'll assume that we | |
# are loading a parent object for a nested resource. Setting it | |
# to false tells the module to load the nested resource instead. | |
# | |
# :id_param - Specify the id param to find the resource with (e.g. use | |
# params[:object_id] instead of params[:id]). | |
# | |
# :param_method - Specify a method (as a symbol) to use for whitelisting with | |
# with strong params when building a new record. | |
# | |
# Example: | |
# load_resource param_method: :object_params | |
# | |
# private | |
# def object_params | |
# params.require(:object).permit(:name) | |
# end | |
# | |
# :find_by - Specify the field (as a symbol) to find the resource with. If | |
# you need to search for an object by the :token field instead | |
# of :id (the default), for example, you can do so with this option. | |
# | |
# :only, | |
# :except, | |
# :unless, | |
# :if - Typical controller callback conditional options. | |
# | |
# Default => [:show, :edit, :update, :new, :create, :destroy] # using :only | |
module LoadResource | |
extend ActiveSupport::Concern | |
class_methods do | |
def load_resource *args | |
ControllerResource.add_before_action(self, :load_resource, *args) | |
end | |
end | |
# Handle the load and authorization controller logic so we don't clutter up all controllers with non-interface methods. | |
# This class is used internally, so you do not need to call methods directly on it. | |
class ControllerResource # :nodoc: | |
def self.add_before_action(controller_class, method, *args) | |
options = args.extract_options! | |
resource_name = args.first | |
exceptions = options.slice(:only, :except, :if, :unless) | |
exceptions[:only] = [:show, :edit, :update, :new, :create, :destroy] unless exceptions.present? | |
controller_class.send(:before_action, exceptions) do |controller| | |
ControllerResource.new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method) | |
end | |
end | |
def initialize(controller, *args) | |
@controller = controller | |
@params = controller.params | |
@options = args.extract_options! | |
@name = args.first || @params[:controller].singularize.to_sym | |
end | |
def load_resource | |
self.resource_instance ||= load_resource_instance | |
end | |
def parent? | |
@options.has_key?(:parent) ? @options[:parent] : @name && @name != name_from_controller.to_sym | |
end | |
def assign_attributes? | |
@params[:action] == 'create' | |
end | |
def name_from_controller | |
@params[:controller].sub("Controller", "").underscore.split('/').last.singularize | |
end | |
def id_param | |
if @options[:id_param] | |
@params[@options[:id_param]] | |
else | |
@params[parent? ? :"#{@name}_id" : :id] | |
end.to_s | |
end | |
def load_resource_instance | |
if !parent? && new_actions.include?(@params[:action].to_sym) | |
build_resource | |
elsif id_param || @options[:singleton] | |
find_resource | |
end | |
end | |
def find_resource | |
key = @options[:find_by] || :id | |
resource_class.where(key => id_param).first! | |
end | |
def build_resource | |
resource = resource_class.new | |
resource.assign_attributes(resource_params) if assign_attributes? | |
resource | |
end | |
def resource_params | |
@options[:param_method] ? @controller.send(@options[:param_method]) : @params[@name] | |
end | |
def resource_class | |
@name.to_s.camelcase.constantize | |
end | |
def resource_instance=(instance) | |
@controller.instance_variable_set("@#{@name}", instance) | |
end | |
def resource_instance | |
@controller.instance_variable_get("@#{@name}") | |
end | |
private | |
def new_actions | |
[:new, :create] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment