rolify 4.1.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.hakiri.yml +1 -0
  3. data/.travis.yml +40 -31
  4. data/Appraisals +54 -0
  5. data/CHANGELOG.rdoc +44 -8
  6. data/CONTRIBUTORS +11 -0
  7. data/Gemfile +5 -13
  8. data/LICENSE +1 -1
  9. data/README.md +74 -26
  10. data/Rakefile +6 -1
  11. data/gemfiles/activerecord_4.gemfile +21 -0
  12. data/gemfiles/activerecord_5.gemfile +28 -0
  13. data/gemfiles/activerecord_6.gemfile +28 -0
  14. data/gemfiles/mongoid_5.gemfile +21 -0
  15. data/gemfiles/mongoid_6.gemfile +20 -0
  16. data/gemfiles/mongoid_7.gemfile +21 -0
  17. data/lib/generators/active_record/rolify_generator.rb +45 -11
  18. data/lib/generators/active_record/templates/migration.rb +2 -3
  19. data/lib/generators/active_record/templates/model.rb +15 -0
  20. data/lib/generators/rolify/templates/initializer.rb +4 -1
  21. data/lib/rolify.rb +3 -4
  22. data/lib/rolify/adapters/active_record/resource_adapter.rb +14 -8
  23. data/lib/rolify/adapters/active_record/role_adapter.rb +26 -9
  24. data/lib/rolify/adapters/mongoid/role_adapter.rb +24 -1
  25. data/lib/rolify/configure.rb +4 -2
  26. data/lib/rolify/dynamic.rb +2 -17
  27. data/lib/rolify/matchers.rb +2 -2
  28. data/lib/rolify/role.rb +11 -2
  29. data/lib/rolify/version.rb +1 -1
  30. data/rolify.gemspec +14 -7
  31. data/spec/common_helper.rb +16 -0
  32. data/spec/generators/rolify/rolify_activerecord_generator_spec.rb +112 -6
  33. data/spec/generators_helper.rb +9 -2
  34. data/spec/rolify/config_spec.rb +2 -0
  35. data/spec/rolify/custom_spec.rb +1 -1
  36. data/spec/rolify/resource_spec.rb +6 -0
  37. data/spec/rolify/shared_examples/shared_examples_for_has_role.rb +65 -0
  38. data/spec/rolify/utils_spec.rb +19 -0
  39. data/spec/spec_helper.rb +19 -6
  40. data/spec/support/adapters/active_record.rb +4 -3
  41. data/spec/support/adapters/mongoid.rb +19 -2
  42. data/spec/support/adapters/{mongoid.yml → mongoid_5.yml} +2 -2
  43. data/spec/support/adapters/mongoid_6.yml +6 -0
  44. data/spec/support/adapters/mongoid_7.yml +6 -0
  45. data/spec/support/adapters/utils/active_record.rb +12 -0
  46. data/spec/support/adapters/utils/mongoid.rb +13 -0
  47. metadata +41 -22
  48. data/gemfiles/Gemfile.rails-3.2 +0 -27
  49. data/gemfiles/Gemfile.rails-4.0 +0 -33
  50. data/gemfiles/Gemfile.rails-4.1 +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: edae47a21706d1859520df05876acf68d95c0d48
4
- data.tar.gz: 09dbd84321d04321d1ef889db0911fa86f1ccbe4
2
+ SHA256:
3
+ metadata.gz: 63187a09a4130c5a7f1066f306783ac5c2fba4e54d5f7130e4b60bdc921b7834
4
+ data.tar.gz: f66383e7b30ead36d1f2dac277cb473dc41479db4656a4bea0ac85f6c6253f69
5
5
  SHA512:
6
- metadata.gz: 910c97443cd78a0386a36f2d6645708c7f6eadf5b84815ca51f8b1cbd39f4a6e1236a16688c37ef99a48234deb44a25c684e7852ce146f7d0e75cc22817a841c
7
- data.tar.gz: 4525bec755d35bb470d364088bdfe2c7f2a39b61cf140944363518ed5626de9f4c438c088d432002a7b41edc750dccc7a032b94f76d075d068f0770b762223cb
6
+ metadata.gz: 6e212c338c8f11662d4bf7f267ae4ecf7e9a4206667cf051053cbaf55b72bd9ba08f7022aed3f85737e29919c3b045129bdec8dfb2922dcb1544232583ce6fcd
7
+ data.tar.gz: e0d2c815832045141b1be4ff76a419704785d57e7195b9c18cafa35885267a4cecd3cf9b11ce7952192317d47ae57115d4831860694227aceb072ac56e5ed9ad
@@ -0,0 +1 @@
1
+ dependency_source: gemspec_file
@@ -1,8 +1,5 @@
1
1
  language: ruby
2
2
 
3
- rvm:
4
- - 2.1.2
5
-
6
3
  before_install:
7
4
  - gem update --system
8
5
  - gem install bundler
@@ -10,40 +7,52 @@ before_install:
10
7
 
11
8
  script: bundle exec rake
12
9
 
10
+ after_success:
11
+ - bundle exec codeclimate-test-reporter
12
+
13
+ rvm:
14
+ - 2.7.0
15
+ - 2.6.3
16
+ - 2.5.5
17
+ - 2.4.6
18
+ - 2.3.8
19
+
20
+ gemfile:
21
+ - gemfiles/activerecord_4.gemfile
22
+ - gemfiles/activerecord_5.gemfile
23
+ - gemfiles/activerecord_6.gemfile
24
+ - gemfiles/mongoid_5.gemfile
25
+ - gemfiles/mongoid_6.gemfile
26
+ - gemfiles/mongoid_7.gemfile
27
+
13
28
  env:
14
29
  - ADAPTER=active_record
15
30
  - ADAPTER=mongoid
16
31
 
32
+ matrix:
33
+ exclude:
34
+ - gemfile: gemfiles/activerecord_4.gemfile
35
+ env: ADAPTER=mongoid
36
+ - gemfile: gemfiles/activerecord_5.gemfile
37
+ env: ADAPTER=mongoid
38
+ - gemfile: gemfiles/activerecord_6.gemfile
39
+ env: ADAPTER=mongoid
40
+ - gemfile: gemfiles/activerecord_6.gemfile
41
+ rvm: 2.4.6
42
+ - gemfile: gemfiles/activerecord_6.gemfile
43
+ rvm: 2.3.8
44
+ - gemfile: gemfiles/mongoid_5.gemfile
45
+ env: ADAPTER=active_record
46
+ - gemfile: gemfiles/mongoid_6.gemfile
47
+ env: ADAPTER=active_record
48
+ - gemfile: gemfiles/mongoid_7.gemfile
49
+ env: ADAPTER=active_record
50
+ allow_failures:
51
+ - gemfile: gemfiles/mongoid_6.gemfile
52
+ - gemfile: gemfiles/mongoid_7.gemfile
53
+
17
54
  services: mongodb
18
55
 
19
56
  addons:
20
57
  code_climate:
21
58
  repo_token: 6bd8d374b120a5449b9a4b7dfda40cc0609dbade48a1b6655f04a9bc8de3a3ee
22
- # language: ruby
23
- #
24
- # rvm:
25
- # - 1.9.3
26
- # - 2.0.0
27
- # - 2.1.1
28
- # - 2.1.2
29
- # - rbx-2
30
- # - jruby-19mode
31
- #
32
- # script: bundle exec rake
33
- #
34
- # gemfile:
35
- # - gemfiles/Gemfile.rails-3.2
36
- # - gemfiles/Gemfile.rails-4.0
37
- # - gemfiles/Gemfile.rails-4.1
38
- #
39
- # env:
40
- # - ADAPTER=active_record
41
- # - ADAPTER=mongoid
42
- #
43
- # services: mongodb
44
- #
45
- # matrix:
46
- # fast_finish: true
47
- # exclude:
48
- # - rvm: 1.9.3
49
- # gemfile: gemfiles/Gemfile.rails-4.1
@@ -0,0 +1,54 @@
1
+ appraise 'mongoid-5' do
2
+ gem "mongoid", "~> 5"
3
+ gem "bson_ext", "1.5.1"
4
+ gem 'bigdecimal', '1.4.2'
5
+ end
6
+
7
+ appraise 'mongoid-6' do
8
+ gem "mongoid", "~> 6"
9
+ gem "bson_ext", "1.5.1"
10
+ end
11
+
12
+ appraise 'mongoid-7' do
13
+ gem "mongoid", "~> 7"
14
+ gem "bson_ext", "1.5.1"
15
+ gem "railties", "5.2.4.1"
16
+ end
17
+
18
+ appraise 'activerecord-4' do
19
+ gem "sqlite3", "~> 1.3.6"
20
+ gem "activerecord", "~> 4.2.11", :require => "active_record"
21
+ gem 'bigdecimal', '1.4.2'
22
+ end
23
+
24
+ appraise 'activerecord-5' do
25
+ gem "sqlite3", "~> 1.3.6"
26
+ gem "activerecord", "~> 5.2.4", :require => "active_record"
27
+
28
+ # Ammeter dependencies:
29
+ gem "actionpack", "~> 5.2.4"
30
+ gem "activemodel", "~> 5.2.4"
31
+ gem "railties", "~> 5.2.4"
32
+
33
+ gem 'rspec-rails' , github: 'rspec/rspec-rails'
34
+ gem 'rspec-core' , github: 'rspec/rspec-core'
35
+ gem 'rspec-expectations', github: 'rspec/rspec-expectations'
36
+ gem 'rspec-mocks' , github: 'rspec/rspec-mocks'
37
+ gem 'rspec-support' , github: 'rspec/rspec-support'
38
+ end
39
+
40
+ appraise 'activerecord-6' do
41
+ gem "sqlite3", "~> 1.4", :platform => "ruby"
42
+ gem "activerecord", ">= 6.0.0", :require => "active_record"
43
+
44
+ # Ammeter dependencies:
45
+ gem "actionpack", ">= 6.0.0"
46
+ gem "activemodel", ">= 6.0.0"
47
+ gem "railties", ">= 6.0.0"
48
+
49
+ gem 'rspec-rails' , github: 'rspec/rspec-rails'
50
+ gem 'rspec-core' , github: 'rspec/rspec-core'
51
+ gem 'rspec-expectations', github: 'rspec/rspec-expectations'
52
+ gem 'rspec-mocks' , github: 'rspec/rspec-mocks'
53
+ gem 'rspec-support' , github: 'rspec/rspec-support'
54
+ end
@@ -1,3 +1,39 @@
1
+ = 5.3.0 (June 1, 2020)
2
+
3
+ 5.3.0 will be the last version to support Ruby < 2.5 and Rails < 5.2. Support for these will be dropped in the next major release.
4
+
5
+ * Fix deprecation warning in Ruby 2.7
6
+ * Add Rails 6 support to migration generator
7
+ * Significant ActiveRecord performance improvements to <tt>add_role</tt> and <tt>without_role</tt>
8
+ * Mongoid fix and performance improvement and to <tt>roles_name</tt>
9
+ * Make it safe to call <tt>Thing.with_role(:admin, user)</tt> with new record
10
+
11
+ = 5.2.0 (Dec 14, 2017)
12
+ * Fix regression in generator around belongs_to options compatibility
13
+ * Update version of database_cleaner
14
+ * Update initializer.rb to include the remove_role_if_empty option and description
15
+ * Allow inverse_of option on rolify method
16
+ * Fix the code-climate-reporter issue that's causing travis to fail
17
+ * Remove a separate index for the name column
18
+ * Fix migration generator for AR 5.x
19
+ * Fixed ambiguous column error
20
+
21
+ = 5.1.0 (Mar 19, 2016)
22
+ * Rails 5 Support (thanks @lorefnon)
23
+ * Fix user handling in generator (thanks @lorefnon)
24
+ * Fix quoting issues (thanks @lorefnon)
25
+ * Improvements to dynamic module loading (thanks to @DmitryKK)
26
+
27
+ = 5.0.0 (Nov 17, 2015)
28
+ * Fix migration warning showing when it shouldn't
29
+ * Add role lazy-loading
30
+ * Add has_cached_role and has_cached_strict_role to project.
31
+ See: https://github.com/RolifyCommunity/rolify#cached-roles-to-avoid-n1-issue
32
+ * Update specs to pass with all Mongoid version.
33
+
34
+ = 4.1.1 (Aug 06, 2015)
35
+ * Fix a regression in the dynamic method loader.
36
+
1
37
  = 4.1.0 (Aug 04, 2015)
2
38
  * added `without_role` method for resources and classes
3
39
  * fix `has_role?` with :any and an unsaved user
@@ -100,7 +136,7 @@
100
136
  * fixed a backward incompatible change introduced in Rails 3.2 release (<tt>find_or_create_by_* generated methods</tt>)
101
137
 
102
138
  = 2.2 (Jan 18, 2012)
103
- * fixed a bug in the initializer file regarding dynamic shortcuts
139
+ * fixed a bug in the initializer file regarding dynamic shortcuts
104
140
 
105
141
  = 2.1 (Nov 30, 2011)
106
142
  * added syntactic sugar: <tt>grant</tt> and <tt>revoke</tt> are aliases for <tt>has_role</tt> and <tt>has_no_role</tt>
@@ -141,8 +177,8 @@
141
177
 
142
178
  = 1.0 (Aug 25, 2011)
143
179
  * added a new parameter to disable dynamic shortcut methods due to potential incompatibility with other gems using method_missing with the same pattern
144
- * add <tt>Rolify.dynamic_shortcuts = false</tt> in the initializer file or
145
- * use the generator command with a third parameter:
180
+ * add <tt>Rolify.dynamic_shortcuts = false</tt> in the initializer file or
181
+ * use the generator command with a third parameter:
146
182
  * <tt>rails g rolify:role Role User false</tt>
147
183
  * removed the railtie as it created more problems than it solved
148
184
  * code refactoring to do some speed improvements and code clean up
@@ -151,16 +187,16 @@
151
187
  * rolify is now on travis-ci to monitor build status
152
188
 
153
189
  = 0.7 (June 20, 2011)
154
- * added a method_missing to catch newly created role outside the current ruby process (i.e. dynamic shortcut methods are not defined within this process)
155
- * dynamic shortcut is created on the fly in the method_missing to avoid extra method_missing for the same dynamic shortcut
156
- * check if the role actually exists in the database before defining the new method
190
+ * added a method_missing to catch newly created role outside the current ruby process (i.e. dynamic shortcut methods are not defined within this process)
191
+ * dynamic shortcut is created on the fly in the method_missing to avoid extra method_missing for the same dynamic shortcut
192
+ * check if the role actually exists in the database before defining the new method
157
193
  * first call is slower due to method_missing but next calls are fast
158
194
  * avoid strange bugs when spawning many ruby processes as the dynamic shortcut methods were only defined in the process that used the <tt>has_role</tt> command
159
195
 
160
196
  = 0.6 (June 19, 2011)
161
197
  * custom User and Role class names support
162
198
  * can now use other class names for Role and User classes
163
- * fixed generators and templates
199
+ * fixed generators and templates
164
200
  * join table is explicitly set to avoid alphabetical order issue
165
201
  * created a new railtie to load the dynamic shortcuts at startup
166
202
 
@@ -182,7 +218,7 @@
182
218
  * Trying to remove a role scoped to a resource whereas the user has a global role won't remove it
183
219
 
184
220
  = v0.3 (June 06, 2011)
185
- * multiple roles check:
221
+ * multiple roles check:
186
222
  * <tt>has_all_roles?</tt> returns true if the user has ALL the roles in arguments
187
223
  * <tt>has_any_role?</tt> returns true if the user has ANY the roles in arguments
188
224
 
@@ -4,3 +4,14 @@ Joel Azemar (@joel)
4
4
  Alex Klim (@AlexKlim)
5
5
  Mauro George (@MauroGeorge)
6
6
  Cheri Allen(@cherimarie)
7
+ Gaurab Paul (@lorefnon)
8
+ Dmitry Krakosevich (@DmitryKK)
9
+ Michael Watts (@mikwat)
10
+ Derek Ethier (@ethier)
11
+ Michael (@mibamur)
12
+ Undo1 (@Undo1)
13
+ Hitabis Engineering (@Hitabis)
14
+ Sergey Alekseev (@sergey-alekseev)
15
+ Sankalp Kulshreshtha (@sankalpk)
16
+ Kirill Sevastyanenko (@kirillseva)
17
+ Denis Shevchenko (@SimplySorc)
data/Gemfile CHANGED
@@ -1,22 +1,14 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  group :test do
4
- case ENV["ADAPTER"]
5
- when nil, "active_record"
6
- gem "activerecord-jdbcsqlite3-adapter", ">= 1.3.0.rc", :platform => "jruby"
7
- gem "sqlite3", :platform => "ruby"
8
- gem "activerecord", ">= 3.2.0", :require => "active_record"
9
- when "mongoid"
10
- gem "mongoid", ">= 3.1"
11
- gem "bson_ext", :platform => "ruby"
12
- else
13
- raise "Unknown model adapter: #{ENV["ADAPTER"]}"
14
- end
15
-
4
+ gem 'appraisal'
16
5
  gem 'coveralls', :require => false
17
6
  gem 'its'
7
+ gem 'pry', '< 0.13.0' # pry pins can be removed when we drop Ruby 2.3
18
8
  gem 'byebug'
19
- gem 'pry-byebug'
9
+ gem 'pry-byebug', '< 3.8.0'
10
+ gem 'test-unit' # Implicitly loaded by ammeter
11
+ gem 'database_cleaner', '~> 1.6.2'
20
12
  gem 'codeclimate-test-reporter', :require => nil
21
13
  end
22
14
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Florent Monbillard
1
+ Copyright (c) 2017 Florent Monbillard
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,28 +1,28 @@
1
- # rolify [![Gem Version](https://badge.fury.io/rb/rolify.svg)](http://badge.fury.io/rb/rolify) [![build status](https://secure.travis-ci.org/RolifyCommunity/rolify.png)](http://travis-ci.org/RolifyCommunity/rolify) [![Dependency Status](https://gemnasium.com/RolifyCommunity/rolify.svg)](https://gemnasium.com/RolifyCommunity/rolify) [![Code Climate](https://codeclimate.com/github/RolifyCommunity/rolify.png)](https://codeclimate.com/github/RolifyCommunity/rolify) [![Coverage Status](https://img.shields.io/coveralls/RolifyCommunity/rolify.svg)](https://coveralls.io/r/RolifyCommunity/rolify?branch=master)
1
+ # rolify [![Gem Version](https://badge.fury.io/rb/rolify.svg)](http://badge.fury.io/rb/rolify) [![build status](https://travis-ci.org/RolifyCommunity/rolify.svg)](http://travis-ci.org/RolifyCommunity/rolify) [![Code Climate](https://codeclimate.com/github/RolifyCommunity/rolify.svg)](https://codeclimate.com/github/RolifyCommunity/rolify) [![Coverage Status](https://coveralls.io/repos/RolifyCommunity/rolify/badge.svg?branch=master&service=github)](https://coveralls.io/github/RolifyCommunity/rolify?branch=master)
2
2
 
3
3
  Very simple Roles library without any authorization enforcement supporting scope on resource object.
4
4
 
5
5
  Let's see an example:
6
6
 
7
7
  ```ruby
8
- user.has_role?(:moderator, Forum.first)
8
+ user.has_role?(:moderator, @forum)
9
9
  => false # if user is moderator of another Forum
10
10
  ```
11
11
 
12
- This library can be easily integrated with any authentication gem ([devise](https://github.com/plataformatec/devise), [Authlogic](https://github.com/binarylogic/authlogic), [Clearance](https://github.com/thoughtbot/clearance)) and authorization gem<span style="color: red"><strong>*</strong></span> ([CanCanCan](https://github.com/CanCanCommunity/cancancan), [authority](https://github.com/nathanl/authority))
12
+ This library can be easily integrated with any authentication gem ([devise](https://github.com/plataformatec/devise), [Authlogic](https://github.com/binarylogic/authlogic), [Clearance](https://github.com/thoughtbot/clearance)) and authorization gem<span style="color: red"><strong>*</strong></span> ([CanCanCan](https://github.com/CanCanCommunity/cancancan), [authority](https://github.com/nathanl/authority), [Pundit](https://github.com/elabs/pundit))
13
13
 
14
14
  <span style="color: red"><strong>*</strong></span>: authorization gem that doesn't provide a role class
15
15
 
16
16
  ## Requirements
17
17
 
18
- * Rails >= 3.2
19
- * ActiveRecord >= 3.2 <b>or</b> Mongoid >= 3.1
20
- * supports ruby 2.0/1.9.3, JRuby 1.6.0+ (in 1.9 mode) and Rubinius 2.0.0dev (in 1.9 mode)
18
+ * Rails >= 4.2
19
+ * ActiveRecord >= 4.2 <b>or</b> Mongoid >= 4.0
20
+ * supports ruby 2.2+, JRuby 1.6.0+ (in 1.9 mode) and Rubinius 2.0.0dev (in 1.9 mode)
21
21
  * support of ruby 1.8 has been dropped due to Mongoid >=3.0 that only supports 1.9 new hash syntax
22
22
 
23
23
  ## Installation
24
24
 
25
- Add this to your Gemfile and run the +bundle+ command.
25
+ Add this to your Gemfile and run the `bundle` command.
26
26
 
27
27
  ```ruby
28
28
  gem "rolify"
@@ -32,7 +32,9 @@ gem "rolify"
32
32
 
33
33
  ### 1. Generate Role Model
34
34
 
35
- First, create your Role model and migration file using this generator:
35
+ First, use the generator to setup Rolify. Role and User class are the default names. However, you can specify any class name you want. For the User class name, you would probably use the one provided by your authentication solution.
36
+
37
+ If you want to use Mongoid instead of ActiveRecord, just add `--orm=mongoid` argument, and skip to step #3.
36
38
 
37
39
  ```
38
40
  rails g rolify Role User
@@ -44,14 +46,11 @@ rails g rolify Role User
44
46
  rails g rolify:role Role User
45
47
  ```
46
48
 
47
- Role and User classes are the default. You can specify any Role class name you want. This is completly a new file so any name can do the job.
48
- For the User class name, you would probably use the one provided by your authentication solution. rolify just adds some class methods in an existing User class.
49
-
50
- If you want to use Mongoid instead of ActiveRecord, just add `--orm=mongoid` argument, and skip to step #3
49
+ The generator will create your Role model, add a migration file, and update your User class with new class methods.
51
50
 
52
51
  ### 2. Run the migration (only required when using ActiveRecord)
53
52
 
54
- Let's migrate !
53
+ Let's migrate!
55
54
 
56
55
  ```
57
56
  rake db:migrate
@@ -80,6 +79,8 @@ The `rolify` method accepts the following callback options:
80
79
 
81
80
  Mongoid callbacks are also supported and works the same way.
82
81
 
82
+ The `rolify` method also accepts the `inverse_of` option if you need to disambiguate the relationship.
83
+
83
84
  ### 3.2 Configure your resource models
84
85
 
85
86
  In the resource models you want to apply roles on, just add ``resourcify`` method.
@@ -91,6 +92,18 @@ class Forum < ActiveRecord::Base
91
92
  end
92
93
  ```
93
94
 
95
+ ### 3.3 Assign default role
96
+
97
+ ```ruby
98
+ class User < ActiveRecord::Base
99
+ after_create :assign_default_role
100
+
101
+ def assign_default_role
102
+ self.add_role(:newuser) if self.roles.blank?
103
+ end
104
+ end
105
+ ```
106
+
94
107
  ### 4. Add a role to a user
95
108
 
96
109
  To define a global role:
@@ -100,21 +113,27 @@ user = User.find(1)
100
113
  user.add_role :admin
101
114
  ```
102
115
 
103
- To define a role scoped to a resource instance
116
+ To define a role scoped to a resource instance:
104
117
 
105
118
  ```ruby
106
119
  user = User.find(2)
107
120
  user.add_role :moderator, Forum.first
108
121
  ```
109
122
 
110
- To define a role scoped to a resource class
123
+ To define a role scoped to a resource class:
111
124
 
112
125
  ```ruby
113
126
  user = User.find(3)
114
127
  user.add_role :moderator, Forum
115
128
  ```
116
129
 
117
- That's it !
130
+ Remove role:
131
+ ```ruby
132
+ user = User.find(3)
133
+ user.remove_role :moderator
134
+ ```
135
+
136
+ That's it!
118
137
 
119
138
  ### 5. Role queries
120
139
 
@@ -162,6 +181,17 @@ user.has_role? :moderator, Forum.last
162
181
  => true
163
182
  ```
164
183
 
184
+ To check if a user has the exact role scoped to a resource class:
185
+
186
+ ```ruby
187
+ user = User.find(5)
188
+ user.add_role :moderator # sets a global role
189
+ user.has_role? :moderator, Forum.first
190
+ => true
191
+ user.has_strict_role? :moderator, Forum.last
192
+ => false
193
+ ```
194
+
165
195
  ### 6. Resource roles querying
166
196
 
167
197
  Starting from rolify 3.0, you can search roles on instance level or class level resources.
@@ -171,34 +201,38 @@ Starting from rolify 3.0, you can search roles on instance level or class level
171
201
  ```ruby
172
202
  forum = Forum.first
173
203
  forum.roles
174
- # => [ list of roles that are only binded to forum instance ]
204
+ # => [ list of roles that are only bound to forum instance ]
175
205
  forum.applied_roles
176
- # => [ list of roles binded to forum instance and to the Forum class ]
206
+ # => [ list of roles bound to forum instance and to the Forum class ]
177
207
  ```
178
208
 
179
209
  #### Class level
180
210
 
181
211
  ```ruby
182
212
  Forum.with_role(:admin)
183
- # => [ list of Forum instances that has role "admin" binded to it ]
213
+ # => [ list of Forum instances that have role "admin" bound to them ]
214
+ Forum.without_role(:admin)
215
+ # => [ list of Forum instances that do NOT have role "admin" bound to them ]
184
216
  Forum.with_role(:admin, current_user)
185
- # => [ list of Forum instances that has role "admin" binded to it and belongs to current_user roles ]
186
- Forum.with_all_roles([:admin, :user], current_user)
187
- # => [ list of Forum instances that has role "admin" or "user" binded to it and belongs to current_user roles ]
217
+ # => [ list of Forum instances that have role "admin" bound to them and belong to current_user roles ]
218
+ Forum.with_roles([:admin, :user], current_user)
219
+ # => [ list of Forum instances that have role "admin" or "user" bound to them and belong to current_user roles ]
188
220
 
189
221
  User.with_any_role(:user, :admin)
190
- # => [ list of User instances that has role "admin" or "user" binded to it ]
222
+ # => [ list of User instances that have role "admin" or "user" bound to them ]
191
223
  User.with_role(:site_admin, current_site)
192
224
  # => [ list of User instances that have a scoped role of "site_admin" to a site instance ]
193
225
  User.with_role(:site_admin, :any)
194
226
  # => [ list of User instances that have a scoped role of "site_admin" for any site instances ]
227
+ User.with_all_roles(:site_admin, :admin)
228
+ # => [ list of User instances that have a role of "site_admin" and a role of "admin" bound to it ]
195
229
 
196
230
  Forum.find_roles
197
- # => [ list of roles that binded to any Forum instance or to the Forum class ]
231
+ # => [ list of roles that are bound to any Forum instance or to the Forum class ]
198
232
  Forum.find_roles(:admin)
199
- # => [ list of roles that binded to any Forum instance or to the Forum class with "admin" as a role name ]
233
+ # => [ list of roles that are bound to any Forum instance or to the Forum class, with "admin" as a role name ]
200
234
  Forum.find_roles(:admin, current_user)
201
- # => [ list of roles that binded to any Forum instance or to the Forum class with "admin" as a role name and belongs to current_user roles ]
235
+ # => [ list of roles that are bound to any Forum instance, or to the Forum class with "admin" as a role name, and belongs to current_user ]
202
236
  ```
203
237
 
204
238
  ### Strict Mode
@@ -219,6 +253,20 @@ end
219
253
  ```
220
254
  I.e. you get true only on a role that you manually add.
221
255
 
256
+ ### Cached Roles (to avoid N+1 issue)
257
+
258
+ ```ruby
259
+ @user.add_role :admin, Forum
260
+ @user.add_role :member, Forum
261
+
262
+ users = User.with_role(:admin, Forum).preload(:roles)
263
+ users.each do |user|
264
+ user.has_cached_role?(:member, Forum) # no extra queries
265
+ end
266
+ ```
267
+
268
+ This method should be used with caution. If you don't preload the roles, the `has_cached_role?` might return `false`. In the above example, it would return `false` for `@user.has_cached_role?(:member, Forum)`, because `User.with_role(:admin, Forum)` will load only the `:admin` roles.
269
+
222
270
  ## Resources
223
271
 
224
272
  * [Wiki](https://github.com/RolifyCommunity/rolify/wiki)