module Authlogic
module Session
# Authentication can be scoped, and it's easy, you just need to define how you want to scope everything. This should help you:
#
# 1. Want to scope by a parent object? Ex: An account has many users. Checkout Authlogic::AuthenticatesMany
# 2. Want to scope the validations in your model? Ex: 2 users can have the same login under different accounts. See Authlogic::ActsAsAuthentic::Scope
module Scopes # :nodoc:
def self.included(klass)
klass.class_eval do
extend ClassMethods
include InstanceMethods
attr_writer :scope
end
end
# = Scopes
module ClassMethods
# The current scope set, should be used in the block passed to with_scope.
def scope
Thread.current[:authlogic_scope]
end
# What with_scopes focuses on is scoping the query when finding the object and the name of the cookie / session. It works very similar to
# ActiveRecord::Base#with_scopes. It accepts a hash with any of the following options:
#
# * find_options: any options you can pass into ActiveRecord::Base.find. This is used when trying to find the record.
# * id: The id of the session, this gets merged with the real id. For information ids see the id method.
#
# Here is how you use it:
#
# UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
# UserSession.find
# end
#
# Eseentially what the above does is scope the searching of the object with the sql you provided. So instead of:
#
# User.find(:first, :conditions => "login = 'ben'")
#
# it would be:
#
# User.find(:first, :conditions => "login = 'ben' and account_id = 2")
#
# You will also notice the :id option. This works just like the id method. It scopes your cookies. So the name of your cookie will be:
#
# account_2_user_credentials
#
# instead of:
#
# user_credentials
#
# What is also nifty about scoping with an :id is that it merges your id's. So if you do:
#
# UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
# session = UserSession.new
# session.id = :secure
# end
#
# The name of your cookies will be:
#
# secure_account_2_user_credentials
def with_scope(options = {}, &block)
raise ArgumentError.new("You must provide a block") unless block_given?
self.scope = options
result = yield
self.scope = nil
result
end
private
def scope=(value)
Thread.current[:authlogic_scope] = value
end
end
module InstanceMethods
# Setting the scope if it exists upon instantiation.
def initialize(*args)
self.scope = self.class.scope
super
end
# The scope of the current object
def scope
@scope ||= {}
end
private
# Used for things like cookie_key, session_key, etc.
def build_key(last_part)
[scope[:id], super].compact.join("_")
end
def search_for_record(*args)
# klass.send(:with_scope, :find => (scope[:find_options] || {})) do
klass.send(*args)
# end
end
end
end
end
end