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/controller_resource'
require 'cancan/controller_additions'
require 'cancan/model_additions'
require 'cancan/exceptions'
require 'cancan/query'
require 'cancan/inherited_resource'

View File

@ -2,6 +2,9 @@ module CanCan
# A general CanCan exception
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.
class ImplementationRemoved < Error; end

View File

@ -19,6 +19,11 @@ module CanCan
@model_class = model_class
@rules = rules
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

View File

@ -6,7 +6,7 @@ module CanCan
end
# 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.
#
@ -44,7 +44,7 @@ module CanCan
end
# 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
joins_hash = {}
@rules.each do |rule|
@ -114,40 +114,6 @@ module CanCan
end
end
module CanCan
# This module is automatically included into all Active Record models.
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
ActiveRecord::Base.class_eval do
include CanCan::ModelAdditions
end

View File

@ -20,35 +20,6 @@ module CanCan
end
end
module CanCan
module DataMapperAdditions
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
DataMapper::Model.class_eval do
include CanCan::ModelAdditions::ClassMethods
end

View File

@ -2,7 +2,7 @@ module CanCan
module ModelAdapters
class MongoidAdapter < AbstractAdapter
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
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?, :matches_conditions_hash_with_mongoid_subject?
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
# Info on monkeypatching Mongoid :
@ -90,7 +61,7 @@ if defined?(::Mongoid)
old_block = @_included_block
@_included_block = Proc.new do
class_eval(&old_block) if old_block
include CanCan::MongoidAdditions
include CanCan::ModelAdditions
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
# 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
def initialize(sanitizer, rules)
@sanitizer = sanitizer
@ -9,7 +9,7 @@ module CanCan
end
# 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.
#

View File

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