can_opener 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in can_opener.gemspec
4
+ gemspec
@@ -0,0 +1,68 @@
1
+ can-opener
2
+ ==========
3
+
4
+ Split up your CanCan Ability by allowing you to easily create abilities in separate classes which you reference in your main ability model. This is mainly useful if you want to break down your abilities into smaller classes for organizational purposes.
5
+
6
+ Usage
7
+ -----
8
+
9
+ gem install can_opener
10
+
11
+ Declare ability classes than inherit from CanOpener::Ability, and implement the `abilities` public instance method. By default, the method will have access to the the local `user` as per typical use in CanCan.
12
+
13
+ require 'can_opener'
14
+
15
+ class AdminAbility < CanOpener::Ability
16
+ def abilities
17
+ if user.admin?
18
+ can :manage, :all
19
+ end
20
+ end
21
+ end
22
+
23
+ class SupportAbility < CanOpener::Ability
24
+ def abilities
25
+ if user.support?
26
+ can :read, :all
27
+ can :write, :all
28
+ end
29
+ end
30
+ end
31
+
32
+ class BannedAbility < CanOpener::Ability
33
+ def abilities
34
+ if user.banned?
35
+ cannot do |action, object_class, object|
36
+ true
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Then declare your Ability class, but include `CanOpener` rather than `CanCan::Abilities`
43
+
44
+ class Ability
45
+ include CanOpener
46
+
47
+ configure_abilities do |c|
48
+ c.add ReaderAbility
49
+ c.add SupportAbility
50
+ c.add AdminAbility, BannedAbility
51
+ end
52
+ end
53
+
54
+ Remember that CanCan processes abilities in a top down fashion, so add your general abilities up top, and then things you want to override everything (like banning a user) at the bottom. You can add line by line or multiple on one line if you wish.
55
+
56
+ ### But I want to check the IP Address, Project, etc, in the ability
57
+
58
+ Just override your Ability#initialize and setup your accessors to be used in the `CanOpener::Ability` subclasses.
59
+
60
+ Why?
61
+ ----
62
+
63
+ A couple times when I used CanCan, my abilities definition method got a little long, and I wanted a simple way to break it up for readability.
64
+
65
+ Todo
66
+ ----
67
+
68
+ * Perhaps a generator for CanOpener::Ability subclasses.
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc "Run the specs"
5
+ task :spec do
6
+ exec "spec spec/can_opener_spec.rb"
7
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "can_opener/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "can_opener"
7
+ s.version = CanOpener::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Brendon Murphy"]
10
+ s.email = ["xternal1+github@gmail.com"]
11
+ s.homepage = "http://github.com/bemurphy/can-opener"
12
+ s.summary = %q{Split up your CanCan Ability}
13
+ s.description = %q{Split up your CanCan Ability by allowing you to easily create abilities in separate classes which you reference in your main ability model. This is mainly useful if you want to break down your abilities into smaller classes for organizational purposes.'}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,35 @@
1
+ require "forwardable"
2
+ require "cancan"
3
+ require "can_opener/ability"
4
+
5
+ module CanOpener
6
+ include CanCan::Ability
7
+
8
+ def self.included(base)
9
+ base.extend ClassMethods
10
+ class << base;
11
+ attr_accessor :ability_classes
12
+ protected :ability_classes=
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def configure_abilities(&block)
18
+ yield self
19
+ end
20
+
21
+ protected
22
+
23
+ def add(*klasses)
24
+ self.ability_classes ||= []
25
+ self.ability_classes.concat Array(klasses)
26
+ self.ability_classes.uniq!
27
+ end
28
+ end
29
+
30
+ def initialize(user)
31
+ self.class.ability_classes.each do |ability_class|
32
+ ability_class.new(self, user)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ module CanOpener
2
+ class Ability
3
+ extend Forwardable
4
+
5
+ def_delegators :@base, *CanCan::Ability.public_instance_methods
6
+
7
+ attr_accessor :user
8
+ protected :user=
9
+
10
+ def initialize(base, user)
11
+ @base = base
12
+ self.user = user
13
+ abilities
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module CanOpener
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+ require "cancan/matchers"
3
+
4
+ class AdminAbility < CanOpener::Ability
5
+ def abilities
6
+ if user.admin?
7
+ can :manage, :all
8
+ end
9
+ end
10
+ end
11
+
12
+ class SupportAbility < CanOpener::Ability
13
+ def abilities
14
+ if user.support?
15
+ can :read, :all
16
+ can :write, :all
17
+ end
18
+ end
19
+ end
20
+
21
+ class ReaderAbility < CanOpener::Ability
22
+ def abilities
23
+ can :read, :all
24
+ alias_action :read, :to => :speed_read
25
+ end
26
+ end
27
+
28
+ class BannedAbility < CanOpener::Ability
29
+ def abilities
30
+ if user.banned?
31
+ cannot do |action, object_class, object|
32
+ true
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ class Ability
39
+ include CanOpener
40
+
41
+ configure_abilities do |c|
42
+ c.add ReaderAbility
43
+ c.add SupportAbility
44
+ c.add AdminAbility
45
+ c.add BannedAbility
46
+ end
47
+ end
48
+
49
+ describe CanOpener do
50
+ def user_double(opts = {})
51
+ double(:user,
52
+ { :admin? => false, :support? => false, :banned? => false }.merge(opts)
53
+ )
54
+ end
55
+
56
+ let(:admin_user) { user_double(:admin? => true) }
57
+ let(:support_user) { user_double(:support? => true) }
58
+ let(:reader_user) { user_double }
59
+ let(:banned_user) { user_double(:admin? => true, :banned? => true) }
60
+
61
+ describe "loading abilities" do
62
+ before(:each) { @ability = Ability.new(admin_user) }
63
+
64
+ it "should have the abilities loaded in the expected order" do
65
+ Ability.ability_classes.should == [ReaderAbility, SupportAbility, AdminAbility, BannedAbility]
66
+ end
67
+ end
68
+
69
+ describe "checking abilities" do
70
+ context "for the admin user" do
71
+ before(:each) { @ability = Ability.new(admin_user) }
72
+
73
+ it "should allow management" do
74
+ @ability.should be_able_to(:manage, :foo)
75
+ end
76
+
77
+ it "should allow reading" do
78
+ @ability.should be_able_to(:read, :foo)
79
+ end
80
+
81
+ it "should allow writing" do
82
+ @ability.should be_able_to(:write, :foo)
83
+ end
84
+ end
85
+
86
+ context "for the support user" do
87
+ before(:each) { @ability = Ability.new(support_user) }
88
+
89
+ it "should not allow management" do
90
+ @ability.should_not be_able_to(:manage, :foo)
91
+ end
92
+
93
+ it "should allow reading" do
94
+ @ability.should be_able_to(:read, :foo)
95
+ end
96
+
97
+ it "should not allow writing" do
98
+ @ability.should be_able_to(:write, :foo)
99
+ end
100
+ end
101
+
102
+ context "for the reader user" do
103
+ before(:each) { @ability = Ability.new(reader_user) }
104
+
105
+ it "should not allow management" do
106
+ @ability.should_not be_able_to(:manage, :foo)
107
+ end
108
+
109
+ it "should allow reading" do
110
+ @ability.should be_able_to(:read, :foo)
111
+ end
112
+
113
+ it "should not allow writing" do
114
+ @ability.should_not be_able_to(:write, :foo)
115
+ end
116
+ end
117
+
118
+ context "for the banned user" do
119
+ before(:each) { @ability = Ability.new(banned_user) }
120
+
121
+ it "should not allow management" do
122
+ @ability.should_not be_able_to(:manage, :foo)
123
+ end
124
+
125
+ it "should not allow reading" do
126
+ @ability.should_not be_able_to(:read, :foo)
127
+ end
128
+
129
+ it "should not allow writing" do
130
+ @ability.should_not be_able_to(:write, :foo)
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "aliasing actions" do
136
+ it "should still work" do
137
+ ability = Ability.new(reader_user)
138
+ ability.should be_able_to(:read, :foo)
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
4
+ require 'can_opener'
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: can_opener
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Brendon Murphy
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-20 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Split up your CanCan Ability by allowing you to easily create abilities in separate classes which you reference in your main ability model. This is mainly useful if you want to break down your abilities into smaller classes for organizational purposes.'
23
+ email:
24
+ - xternal1+github@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - README.markdown
35
+ - Rakefile
36
+ - can_opener.gemspec
37
+ - lib/can_opener.rb
38
+ - lib/can_opener/ability.rb
39
+ - lib/can_opener/version.rb
40
+ - spec/can_opener_spec.rb
41
+ - spec/spec_helper.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/bemurphy/can-opener
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.7
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Split up your CanCan Ability
76
+ test_files: []
77
+