module BulletTrain::LoadsAndAuthorizesResource

def account_load_and_authorize_resource(model, positional_through = nil, through: positional_through, collection_actions: [], member_actions: [], except: [], **options)

and `model` is something like `project`.
to help you understand the code below, usually `through` is `team`

namespacing our `Oauth::` models and controllers.)
for namespaced models and controllers. (we introduced this complexity in support of
there are also some complications that were introduced into this method by our support

controllers in the account namespace, including our shallow nested routes.
implements a lot of the options required to make that method work very well for our
cancancan's `load_and_authorize_resource` method, which is awesome, but it also
tied together. we've taken the liberty of doing this because it's heavily based on
for you in your controllers beyond that is provided by the underlying gems that we've
this is one of the few pieces of 'magical' functionality that bullet train implements
def account_load_and_authorize_resource(model, positional_through = nil, through: positional_through, collection_actions: [], member_actions: [], except: [], **options)
  # options are now required, because you have to have at least a 'through' setting.
  # we used to support calling this method with a signature like this:
  #
  #   `account_load_and_authorize_resource [:oauth, :twitter_account], :team`
  #
  # however this abstraction was too short-sighted so we've updated this method to accept the exact same method
  # signature as cancancan's original `load_and_authorize_resource` method.
  if model.is_a?(Array)
    raise "Bullet Train has depreciated this method of calling `account_load_and_authorize_resource`. Read the comments on this line of source for more details."
  end
  # fetch the namespace of the controller. this should generally match the namespace of the model, except for the
  # `account` part.
  namespace = model_namespace_from_controller_namespace
  model_class_names = namespace.size.downto(0).map do
    [*namespace, model.to_s.classify].join("::").tap { namespace.pop }
  end
  model_class = model_class_names.find(&:safe_constantize)&.safe_constantize
  unless model_class
    raise "Your 'account_load_and_authorize_resource' is broken. We tried #{model_class_names.join(" and ")}, but didn't find a valid class name."
  end
  through_as_symbols = Array(through)
  through_class_names = through_as_symbols.map do |through_as_symbol|
    # reflect on the belongs_to association of the child model to figure out the class names of the parents.
    association = model_class.reflect_on_association(through_as_symbol)
    unless association
      raise "Your 'account_load_and_authorize_resource' is broken. Tried to reflect on the `#{through_as_symbol}` association of #{model_class_names}, but didn't find one."
    end
    association.klass.name
  end
  if through_as_symbols.count > 1 && !options[:polymorphic]
    raise "When a resource can be loaded through multiple parents, please specify the 'polymorphic' option to tell us what that controller calls the parent, e.g. `polymorphic: :imageable`."
  end
  instance_variable_name = "@#{options[:polymorphic] || through_as_symbols.first}"
  # `collection_actions:` and `member_actions:` provide support for shallow nested resources, which
  # keep our routes tidy even after many levels of nesting. most people
  # i talk to don't actually know about this feature in rails, but it's
  # actually the recommended approach in the rails routing documentation.
  #
  # also, similar to `load_and_authorize_resource`, people can pass in additional
  # actions for which the resource should be loaded, but because we're making
  # separate calls to `load_and_authorize_resource` for member and collection
  # actions, we ask controllers to specify these actions separately, e.g.:
  #   `account_load_and_authorize_resource :invitation, :team, member_actions: [:accept, :promote]`
  #
  # `except:` is native to cancancan and allows you to skip account_load_and_authorize_resource
  # for a specific action that would otherwise run it (e.g. see invitations#show.)
  collection_actions = (%i[index new create reorder] + collection_actions) - except
  member_actions = (%i[show edit update destroy] + member_actions) - except
  # NOTE: because we're using prepend for all of these, these are written in backwards order
  # of how they'll be executed during a request!
  # 4. finally, load the team and parent resource if we can.
  prepend_before_action :load_team
  # x. this and the thing below it are only here to make a sortable concern possible.
  prepend_before_action only: member_actions do
    @child_object = instance_variable_get(:"@#{model}")
    @parent_object = instance_variable_get instance_variable_name
  end
  prepend_before_action only: collection_actions do
    @parent_object = instance_variable_get instance_variable_name
    @child_collection = options[:through_association].presence&.to_sym || model.to_s.pluralize.to_sym
  end
  prepend_before_action only: member_actions do
    model_instance = instance_variable_get(:"@#{model}")
    if model_instance && !instance_variable_defined?(instance_variable_name)
      parent = through_as_symbols.lazy.filter_map { model_instance.public_send(_1) }.first
      instance_variable_set instance_variable_name, parent
    end
  end
  if options[:polymorphic]
    prepend_before_action only: collection_actions do
      unless instance_variable_defined?(:"@#{options[:polymorphic]}")
        parent = through_as_symbols.lazy.filter_map { instance_variable_get :"@#{_1}" }.first
        instance_variable_set :"@#{options[:polymorphic]}", parent
      end
    end
  end
  # 3. on action resource, we have a specific id for the child resource, so load it directly.
  load_and_authorize_resource model,
    options.merge(
      class: model_class.name,
      only: member_actions,
      prepend: true,
      shallow: true
    )
  # 2. only load the child resource through the parent resource for collection actions.
  load_and_authorize_resource model,
    options.merge(
      class: model_class.name,
      through: through_as_symbols,
      only: collection_actions,
      prepend: true,
      shallow: true
    )
  # 1. load the parent resource for collection actions only. (we're using shallow routes.)
  # since a controller can have multiple potential parents, we have to run this as a loop on every possible
  # parent. (the vast majority of controllers only have one parent.)
  through_class_names.each_with_index do |through_class_name, index|
    load_and_authorize_resource through_as_symbols[index],
      options.merge(
        class: through_class_name,
        only: collection_actions,
        prepend: true,
        shallow: true
      )
  end
end

def create

def create
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end

def edit

def edit
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end

def load_team

def load_team
  @team ||= @child_object&.try(:team) || @parent_object&.try(:team)
  return unless @team
  if defined?(Current) && Current.respond_to?(:team=)
    Current.team = @team
  end
  # If the currently loaded team is saved to the database, make that the user's new current team.
  if @team.try(:persisted?)
    if can? :show, @team
      current_user.update_column(:current_team_id, @team.id)
    end
  end
end

def model_namespace_from_controller_namespace

Returns an array of module names based on the classes namespace minus regex_to_remove_controller_namespace
def model_namespace_from_controller_namespace
  name
    .gsub(regex_to_remove_controller_namespace || //, "")
    .split("::")
    .tap(&:pop) # drops actual class name
end

def new

def new
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end

def regex_to_remove_controller_namespace

def regex_to_remove_controller_namespace
  return super if defined?(super)
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end

def reorder

that it would be if an empty method were called and it appears that nothing happens.
just defining empty methods, so that if these methods are ever reached it will be more obvious what's happening
will implement real versions of these methods (if needed) to override these dummy methods. We raise, instead of
that they will exist at the time that `account_load_and_authorize_resource` is called. We assume that controllers
we need to have these methods defined on any controller that includes this module. We define them here so
that call that method. In order to use the new Rails default for `config.raise_on_missing_callback_actions = true`
These are methods that `account_load_and_authorize_resource` assumes will be present on any controllers
def reorder
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end

def update

def update
  raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
end