mayi 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,9 +8,9 @@ GEM
8
8
  git (>= 1.2.5)
9
9
  rake
10
10
  rdoc
11
- json (1.7.5)
12
- rake (0.9.2.2)
13
- rdoc (3.12)
11
+ json (1.8.0)
12
+ rake (10.0.4)
13
+ rdoc (3.12.2)
14
14
  json (~> 1.4)
15
15
  rspec (2.8.0)
16
16
  rspec-core (~> 2.8.0)
@@ -2,41 +2,44 @@
2
2
 
3
3
  A plugable access rights API. Meant to make integrations easier. Verry useful as an integration point for blog,forum and CMS components. Also its much nicer to read than the basic stuff i usually do.
4
4
 
5
- Before without MayI.
5
+ An example basic way to do rights handeling
6
6
 
7
7
  ```ruby
8
8
  if user_object.is_admin?
9
-
9
+ ...
10
10
  end
11
11
  ```
12
12
 
13
- Now with MayI.
13
+ With mayi this changes to method with an explicit mening to it.
14
14
 
15
15
  ```ruby
16
16
  access.may_add_user! do
17
-
17
+ ...
18
18
  end
19
19
  ```
20
20
 
21
21
 
22
22
 
23
23
 
24
- ## Basics
24
+ ## An example
25
25
 
26
- You have a class that implements boolean questions.
26
+ Your rights implements with boolean questions.
27
27
 
28
28
  ```ruby
29
- class MyBasicAccess
30
- def initialize(data)
31
- @data = data
29
+ class MyAccessHandler
30
+
31
+ include MayI
32
+
33
+ def initialize(user)
34
+ @user = user
32
35
  end
33
36
 
34
- def may_view_secret_stuff(stuff)
35
- stuff.owner_id == data[:session][:user_id]
37
+ def may_view_secret_project(project)
38
+ stuff.owner_id == @user.id
36
39
  end
37
40
 
38
41
  def may_create_new_record
39
- data[:session][:user_type] == "admin"
42
+ @user.type == "admin"
40
43
  end
41
44
  end
42
45
  ```
@@ -45,7 +48,8 @@ This can then be used with the MayI::Access class.
45
48
 
46
49
 
47
50
  ```ruby
48
- access = MayI::Access.new(MyBasicAccess)
51
+
52
+ access = MyAccessHandler.new(user)
49
53
 
50
54
  # Simple boolean
51
55
  if access.may_create_new_record?
@@ -56,84 +60,41 @@ end
56
60
  access.may_create_new_record? do
57
61
  # You do stuff here
58
62
  end
59
- ```
60
63
 
61
- Now with exceptions. On failure the MayI::AccessDeniedError error is raised.
64
+ # Raise errors on false
65
+ access.may_view_secret_project!(project)
66
+ # or
67
+ access.error_message("A custom error message").may_view_secret_project!(project)
62
68
 
63
- ```ruby
64
- access = MayI::Access.new(MyBasicAccess)
65
-
66
- # Simple boolean
67
- if access.may_create_new_record!
68
- # You do stuff here
69
- end
70
-
71
- # With a block
72
- access.may_create_new_record! do
73
- # You do stuff here
74
- end
75
- ```
76
-
77
- With custom error message
78
-
79
- ```ruby
80
- access.error_message("Sorry but you are not allowed to do this!").may_create_new_record! do
81
- # You do stuff here
82
- end
83
69
  ```
84
70
 
85
-
86
-
87
-
88
-
89
71
  ## A Rails example
90
72
 
91
- On each request we create a new instance of MyBasicAccess with the current session.
92
-
93
73
  ```ruby
94
74
  class ApplicationController < ActionController::Base
95
- before_filter :init_access
96
-
97
- def init_access
98
- # Create a new instance of MyBasicAccess with the current session
99
- ApplicationController.access.refresh({:session => session})
100
- end
101
-
102
- def self.access
103
- @@access_cache
75
+
76
+ helper_method :current_user
77
+ def current_user
78
+ ...
104
79
  end
105
80
 
81
+ helper_method :access
106
82
  def access
107
- @@access_cache
83
+ @@access_cache ||= MyAccessHandler.new(current_user)
108
84
  end
109
85
 
110
- @@access_cache = MayI::Access.new
111
- @@access_cache.implementation = MyBasicAccess
112
86
  end
113
87
  ```
114
88
 
115
- We use the API to check if a user should be able to view some secret stuff.
89
+ Check if a user should be able to view some secret stuff.
116
90
 
117
91
  ```ruby
118
- class SecretStuffController < ApplicationController
92
+ class StuffController < ApplicationController
119
93
 
120
94
  def show
121
95
  stuff = Stuff.find(params[:id])
122
- access.may_view_secret_stuff?(stuff) do
123
96
 
124
- end
125
- end
126
-
127
- end
128
- ```
129
-
130
- We can also use it in a model.
131
-
132
- ```ruby
133
- class ShortUrl < ActiveRecord::Base
134
-
135
- def method_that_requires_special_access
136
- ApplicationController.access.may_create_new_record! do
97
+ access.may_view_secret_stuff?(stuff) do
137
98
 
138
99
  end
139
100
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 2.0.0
@@ -2,8 +2,11 @@
2
2
  # Add the directory containing this file to the start of the load path if it
3
3
  # isn't there already.
4
4
  $:.unshift(File.dirname(__FILE__)) unless
5
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ module MayI
8
+
9
+ end
6
10
 
7
- require 'mayi/proxy'
8
11
  require 'mayi/access_denied_error'
9
- require 'mayi/access'
12
+ require 'mayi/methods'
@@ -1,9 +1,8 @@
1
- module MayI
2
- class AccessDeniedError < RuntimeError
3
1
 
4
- def initialize(message = 'Access Denied')
5
- super message
6
- end
2
+ class MayI::AccessDeniedError < RuntimeError
7
3
 
4
+ def initialize(message = 'Access Denied')
5
+ super message
8
6
  end
9
- end
7
+
8
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module MayI
3
+
4
+ def method_missing(meth, *args, &block)
5
+ if is_a_may_i_method?(meth)
6
+ if self.send(meth.to_s[0..-2].to_sym,*args)
7
+ yield if block_given?
8
+ true
9
+ else
10
+ meth.to_s.end_with?("!") ? raise_may_i_error(meth) : false
11
+ end
12
+ else
13
+ super(meth,*args,&block)
14
+ end
15
+ ensure
16
+ @may_i_error_message = nil
17
+ end
18
+
19
+ def respond_to?(meth)
20
+ if is_a_may_i_method?(meth)
21
+ super(meth.to_s[0..-2].to_sym)
22
+ else
23
+ super(meth)
24
+ end
25
+ end
26
+
27
+ def error_message(message)
28
+ @custom_may_i_error_message = message
29
+ self
30
+ end
31
+
32
+ private
33
+
34
+ def is_a_may_i_method?(sym)
35
+ sym.to_s.match(/^(may)_.*(\?|!)$/)
36
+ end
37
+
38
+ def raise_may_i_error(meth)
39
+ raise MayI::AccessDeniedError.new(@custom_may_i_error_message || meth.to_s[0..-2].gsub("_", " ").gsub("may","may not"))
40
+ end
41
+
42
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "mayi"
8
- s.version = "1.0.2"
8
+ s.version = "2.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Darwin"]
12
- s.date = "2012-08-23"
12
+ s.date = "2013-05-16"
13
13
  s.description = " A plugable access rights API. Meant to make integrations easier. Werry useful as an integration point for blog,forum and CMS components. Also its much nicer to read than the basic stuff i usually do. "
14
14
  s.email = "darwin@bits2life.com"
15
15
  s.extra_rdoc_files = [
@@ -26,10 +26,10 @@ Gem::Specification.new do |s|
26
26
  "Rakefile",
27
27
  "VERSION",
28
28
  "lib/mayi.rb",
29
- "lib/mayi/access.rb",
30
29
  "lib/mayi/access_denied_error.rb",
31
- "lib/mayi/proxy.rb",
30
+ "lib/mayi/methods.rb",
32
31
  "mayi.gemspec",
32
+ "spec/lib/test_helper.rb",
33
33
  "spec/mayi_spec.rb",
34
34
  "spec/spec_helper.rb"
35
35
  ]
@@ -0,0 +1,6 @@
1
+
2
+ class TestHelper
3
+
4
+ include MayI
5
+
6
+ end
@@ -1,7 +1,77 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe "MayI" do
4
- it "fails" do
5
- fail "hey buddy, you should probably rename this file and start specing for real"
3
+ describe "MayI::Methods" do
4
+
5
+ subject { TestHelper.new }
6
+
7
+ context "call a may method with question mark" do
8
+
9
+ it 'should call the map_do_something method' do
10
+ subject.should_receive(:may_do_something).and_return(true)
11
+ subject.may_do_something?.should be_true
12
+ end
13
+
14
+ it 'should yield to the block when true' do
15
+
16
+ subject.should_receive(:may_do_something).and_return(true)
17
+ has_yielded = false
18
+ subject.may_do_something? do
19
+ has_yielded = true
20
+ end
21
+
22
+ has_yielded.should be_true
23
+
24
+ end
25
+
26
+ it 'should not yield to the block when false' do
27
+
28
+ subject.should_receive(:may_do_something).and_return(false)
29
+ has_yielded = false
30
+ subject.may_do_something? do
31
+ has_yielded = true
32
+ end
33
+
34
+ has_yielded.should be_false
35
+
36
+ end
37
+
6
38
  end
39
+
40
+ context "call a may method with exclimation point " do
41
+
42
+ it 'should call the map_do_something method' do
43
+ subject.should_receive(:may_do_something).and_return(true)
44
+ subject.may_do_something!.should be_true
45
+ end
46
+
47
+ it 'should raise an error on false' do
48
+ subject.should_receive(:may_do_something).and_return(false)
49
+ lambda{ subject.may_do_something! }.should raise_error(MayI::AccessDeniedError)
50
+ end
51
+
52
+ it 'should yield to the block' do
53
+
54
+ subject.should_receive(:may_do_something).and_return(true)
55
+ has_yielded = false
56
+ subject.may_do_something! do
57
+ has_yielded = true
58
+ end
59
+
60
+ has_yielded.should be_true
61
+
62
+ end
63
+
64
+ end
65
+
66
+ describe "call a may method with an error message" do
67
+
68
+ it 'should set the error message for the exception' do
69
+
70
+ subject.should_receive(:may_do_something).and_return(false)
71
+ lambda{ subject.error_message("A error message").may_do_something! }.should raise_error(MayI::AccessDeniedError, "A error message")
72
+
73
+ end
74
+
75
+ end
76
+
7
77
  end
@@ -1,7 +1,8 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
- require 'may-i'
4
+ require 'mayi'
5
+ require_relative 'lib/test_helper'
5
6
 
6
7
  # Requires supporting files with custom matchers and macros, etc,
7
8
  # in ./support/ and its subdirectories.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mayi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-23 00:00:00.000000000 Z
12
+ date: 2013-05-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -94,10 +94,10 @@ files:
94
94
  - Rakefile
95
95
  - VERSION
96
96
  - lib/mayi.rb
97
- - lib/mayi/access.rb
98
97
  - lib/mayi/access_denied_error.rb
99
- - lib/mayi/proxy.rb
98
+ - lib/mayi/methods.rb
100
99
  - mayi.gemspec
100
+ - spec/lib/test_helper.rb
101
101
  - spec/mayi_spec.rb
102
102
  - spec/spec_helper.rb
103
103
  homepage: http://github.com/bjornblomqvist/mayi
@@ -115,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
115
  version: '0'
116
116
  segments:
117
117
  - 0
118
- hash: -398463573678793695
118
+ hash: -3855034540096933122
119
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  none: false
121
121
  requirements:
@@ -1,79 +0,0 @@
1
- module MayI
2
- class Access
3
-
4
- attr_accessor :implementation
5
-
6
- def initialize(implementation = nil)
7
- self.implementation = implementation
8
- end
9
-
10
- def refresh(data = {})
11
- raise "You have not set any implementation yet" unless self.implementation
12
- if self.implementation.is_a?(Class)
13
- Thread.current["mayi_access_implementation_#{self.object_id}"] = self.implementation.new(data)
14
- else
15
- instance = self.implementation.to_s.split('::').reduce(Object){|cls, c| cls.const_get(c) }.new(data)
16
- Thread.current["mayi_access_implementation_#{self.object_id}"] = instance
17
- end
18
-
19
- end
20
-
21
- def clear
22
- Thread.current["mayi_access_implementation_#{self.object_id}"] = nil
23
- end
24
-
25
- def current_instance
26
- raise "You must call refresh to create a new instance of your Access implementation before being able to use the access object." unless Thread.current["mayi_access_implementation_#{self.object_id}"]
27
-
28
- Thread.current["mayi_access_implementation_#{self.object_id}"]
29
- end
30
-
31
- def method_missing(meth, *args, &block)
32
- if meth.to_s =~ /^(may)_.*(\?|!)$/
33
- if meth.to_s.end_with?("!")
34
- if current_instance.send(meth.to_s[0..-2].to_sym,*args)
35
- yield if block_given?
36
- true
37
- else
38
- raise_error(meth)
39
- end
40
- elsif meth.to_s.end_with?("?")
41
- if current_instance.send(meth.to_s[0..-2].to_sym,*args)
42
- yield if block_given?
43
- true
44
- else
45
- false
46
- end
47
- end
48
- else
49
- super(meth,*args,&block)
50
- end
51
- end
52
-
53
- def respond_to?(meth)
54
- if meth.to_s =~ /^(may)_.*(\?|!)$/
55
- super(meth.to_s[0..-2].to_sym)
56
- else
57
- super(meth)
58
- end
59
- end
60
-
61
- def error_message(message)
62
- Proxy.new(self) do |state|
63
- if state == :before
64
- @error_message = message
65
- else
66
- @error_message = nil
67
- end
68
- end
69
- end
70
-
71
- private
72
-
73
- def raise_error(meth)
74
- error_message = meth.to_s[0..-2].gsub("_", " ").gsub("may","may not")
75
- raise AccessDeniedError.new(@error_message || error_message)
76
- end
77
-
78
- end
79
- end
@@ -1,19 +0,0 @@
1
- module MayI
2
- class Proxy
3
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
4
-
5
- def initialize(target,&block)
6
- @target = target
7
- @block = block
8
- end
9
-
10
- protected
11
-
12
- def method_missing(name, *args, &block)
13
- @block.call(:before)
14
- @target.send(name, *args, &block)
15
- ensure
16
- @block.call(:after)
17
- end
18
- end
19
- end