mayi 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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