moving accessible_by out into ModelAdditions module

This commit is contained in:
Ryan Bates 2010-12-30 15:40:53 -08:00
parent f7a494dc51
commit ec616ae75b
9 changed files with 52 additions and 104 deletions

View File

@ -2,6 +2,7 @@ require 'cancan/ability'
require 'cancan/rule' require 'cancan/rule'
require 'cancan/controller_resource' require 'cancan/controller_resource'
require 'cancan/controller_additions' require 'cancan/controller_additions'
require 'cancan/model_additions'
require 'cancan/exceptions' require 'cancan/exceptions'
require 'cancan/query' require 'cancan/query'
require 'cancan/inherited_resource' require 'cancan/inherited_resource'

View File

@ -2,6 +2,9 @@ module CanCan
# A general CanCan exception # A general CanCan exception
class Error < StandardError; end class Error < StandardError; end
# Raised when behavior is not implemented, usually used in an abstract class.
class NotImplemented < Error; end
# Raised when removed code is called, an alternative solution is provided in message. # Raised when removed code is called, an alternative solution is provided in message.
class ImplementationRemoved < Error; end class ImplementationRemoved < Error; end

View File

@ -19,6 +19,11 @@ module CanCan
@model_class = model_class @model_class = model_class
@rules = rules @rules = rules
end end
def database_records
# This should be overridden in a subclass to return records which match @rules
raise NotImplemented, "This model adapter does not support fetching records from the database."
end
end end
end end
end end

View File

@ -6,7 +6,7 @@ module CanCan
end end
# Returns conditions intended to be used inside a database query. Normally you will not call this # Returns conditions intended to be used inside a database query. Normally you will not call this
# method directly, but instead go through ActiveRecordAdditions#accessible_by. # method directly, but instead go through ModelAdditions#accessible_by.
# #
# If there is only one "can" definition, a hash of conditions will be returned matching the one defined. # If there is only one "can" definition, a hash of conditions will be returned matching the one defined.
# #
@ -44,7 +44,7 @@ module CanCan
end end
# Returns the associations used in conditions for the :joins option of a search. # Returns the associations used in conditions for the :joins option of a search.
# See ActiveRecordAdditions#accessible_by for use in Active Record. # See ModelAdditions#accessible_by
def joins def joins
joins_hash = {} joins_hash = {}
@rules.each do |rule| @rules.each do |rule|
@ -114,40 +114,6 @@ module CanCan
end end
end end
module CanCan ActiveRecord::Base.class_eval do
# This module is automatically included into all Active Record models. include CanCan::ModelAdditions
module ActiveRecordAdditions
module ClassMethods
# Returns a scope which fetches only the records that the passed ability
# can perform a given action on. The action defaults to :read. This
# is usually called from a controller and passed the +current_ability+.
#
# @articles = Article.accessible_by(current_ability)
#
# Here only the articles which the user is able to read will be returned.
# If the user does not have permission to read any articles then an empty
# result is returned. Since this is a scope it can be combined with any
# other scopes or pagination.
#
# An alternative action can optionally be passed as a second argument.
#
# @articles = Article.accessible_by(current_ability, :update)
#
# Here only the articles which the user can update are returned. This
# internally uses Ability#conditions method, see that for more information.
def accessible_by(ability, action = :read)
ability.model_adapter(self, action).database_records
end
end
def self.included(base)
base.extend ClassMethods
end
end
end
if defined? ActiveRecord
ActiveRecord::Base.class_eval do
include CanCan::ActiveRecordAdditions
end
end end

View File

@ -20,35 +20,6 @@ module CanCan
end end
end end
module CanCan DataMapper::Model.class_eval do
module DataMapperAdditions include CanCan::ModelAdditions::ClassMethods
module ClassMethods
# Returns a scope which fetches only the records that the passed ability
# can perform a given action on. The action defaults to :read. This
# is usually called from a controller and passed the +current_ability+.
#
# @articles = Article.accessible_by(current_ability)
#
# Here only the articles which the user is able to read will be returned.
# If the user does not have permission to read any articles then an empty
# result is returned. Since this is a scope it can be combined with any
# other scopes or pagination.
#
# An alternative action can optionally be passed as a second argument.
#
# @articles = Article.accessible_by(current_ability, :update)
#
# Here only the articles which the user can update are returned. This
# internally uses Ability#conditions method, see that for more information.
def accessible_by(ability, action = :read)
ability.model_adapter(self, action).database_records
end
end
end
end
if Object.const_defined?('DataMapper')
DataMapper::Model.class_eval do
include CanCan::DataMapperAdditions::ClassMethods
end
end end

View File

@ -2,7 +2,7 @@ module CanCan
module ModelAdapters module ModelAdapters
class MongoidAdapter < AbstractAdapter class MongoidAdapter < AbstractAdapter
def self.for_class?(model_class) def self.for_class?(model_class)
model_class <= CanCan::MongoidAdditions # there should be a better class to detect with this model_class <= Mongoid::Document
end end
def database_records def database_records
@ -50,35 +50,6 @@ module CanCan
alias_method :matches_conditions_hash_without_mongoid_subject?, :matches_conditions_hash? alias_method :matches_conditions_hash_without_mongoid_subject?, :matches_conditions_hash?
alias_method :matches_conditions_hash?, :matches_conditions_hash_with_mongoid_subject? alias_method :matches_conditions_hash?, :matches_conditions_hash_with_mongoid_subject?
end end
module MongoidAdditions
module ClassMethods
# Returns a scope which fetches only the records that the passed ability
# can perform a given action on. The action defaults to :read. This
# is usually called from a controller and passed the +current_ability+.
#
# @articles = Article.accessible_by(current_ability)
#
# Here only the articles which the user is able to read will be returned.
# If the user does not have permission to read any articles then an empty
# result is returned. Since this is a scope it can be combined with any
# other scopes or pagination.
#
# An alternative action can optionally be passed as a second argument.
#
# @articles = Article.accessible_by(current_ability, :update)
#
# Here only the articles which the user can update are returned. This
# internally uses Ability#conditions method, see that for more information.
def accessible_by(ability, action = :read)
ability.model_adapter(self, action).database_records
end
end
def self.included(base)
base.extend ClassMethods
end
end
end end
# Info on monkeypatching Mongoid : # Info on monkeypatching Mongoid :
@ -90,7 +61,7 @@ if defined?(::Mongoid)
old_block = @_included_block old_block = @_included_block
@_included_block = Proc.new do @_included_block = Proc.new do
class_eval(&old_block) if old_block class_eval(&old_block) if old_block
include CanCan::MongoidAdditions include CanCan::ModelAdditions
end end
end end
end end

View File

@ -0,0 +1,31 @@
module CanCan
# This module adds the accessible_by class method to a model. It is included in the model adapters.
module ModelAdditions
module ClassMethods
# Returns a scope which fetches only the records that the passed ability
# can perform a given action on. The action defaults to :read. This
# is usually called from a controller and passed the +current_ability+.
#
# @articles = Article.accessible_by(current_ability)
#
# Here only the articles which the user is able to read will be returned.
# If the user does not have permission to read any articles then an empty
# result is returned. Since this is a scope it can be combined with any
# other scopes or pagination.
#
# An alternative action can optionally be passed as a second argument.
#
# @articles = Article.accessible_by(current_ability, :update)
#
# Here only the articles which the user can update are returned.
def accessible_by(ability, action = :read)
ability.model_adapter(self, action).database_records
end
end
def self.included(base)
base.extend ClassMethods
end
end
end

View File

@ -1,7 +1,7 @@
module CanCan module CanCan
# Generates the sql conditions and association joins for use in ActiveRecord queries. # Generates the sql conditions and association joins for use in ActiveRecord queries.
# Normally you will not use this class directly, but instead through ActiveRecordAdditions#accessible_by. # Normally you will not use this class directly, but instead through ModelAdditions#accessible_by.
class Query class Query
def initialize(sanitizer, rules) def initialize(sanitizer, rules)
@sanitizer = sanitizer @sanitizer = sanitizer
@ -9,7 +9,7 @@ module CanCan
end end
# Returns conditions intended to be used inside a database query. Normally you will not call this # Returns conditions intended to be used inside a database query. Normally you will not call this
# method directly, but instead go through ActiveRecordAdditions#accessible_by. # method directly, but instead go through ModelAdditions#accessible_by.
# #
# If there is only one "can" definition, a hash of conditions will be returned matching the one defined. # If there is only one "can" definition, a hash of conditions will be returned matching the one defined.
# #

View File

@ -3,14 +3,14 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
class MongoidCategory class MongoidCategory
include Mongoid::Document include Mongoid::Document
include CanCan::MongoidAdditions include CanCan::ModelAdditions
references_many :mongoid_projects references_many :mongoid_projects
end end
class MongoidProject class MongoidProject
include Mongoid::Document include Mongoid::Document
include CanCan::MongoidAdditions include CanCan::ModelAdditions
referenced_in :mongoid_category referenced_in :mongoid_category