rolify 4.1.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/activerecord.yml +27 -0
  3. data/.github/workflows/mongoid.yml +32 -0
  4. data/.hakiri.yml +1 -0
  5. data/Appraisals +42 -0
  6. data/CHANGELOG.rdoc +52 -8
  7. data/CONTRIBUTORS +11 -0
  8. data/Gemfile +6 -14
  9. data/LICENSE +1 -1
  10. data/README.md +72 -26
  11. data/Rakefile +6 -1
  12. data/gemfiles/activerecord_4.gemfile +20 -0
  13. data/gemfiles/activerecord_5.gemfile +22 -0
  14. data/gemfiles/activerecord_6.gemfile +22 -0
  15. data/gemfiles/mongoid_5.gemfile +20 -0
  16. data/gemfiles/mongoid_6.gemfile +19 -0
  17. data/gemfiles/mongoid_7.gemfile +20 -0
  18. data/lib/generators/active_record/rolify_generator.rb +45 -11
  19. data/lib/generators/active_record/templates/migration.rb +2 -3
  20. data/lib/generators/active_record/templates/model.rb +15 -0
  21. data/lib/generators/rolify/templates/initializer.rb +4 -1
  22. data/lib/rolify.rb +3 -4
  23. data/lib/rolify/adapters/active_record/resource_adapter.rb +14 -8
  24. data/lib/rolify/adapters/active_record/role_adapter.rb +40 -17
  25. data/lib/rolify/adapters/mongoid/role_adapter.rb +38 -8
  26. data/lib/rolify/configure.rb +4 -2
  27. data/lib/rolify/dynamic.rb +2 -16
  28. data/lib/rolify/finders.rb +6 -1
  29. data/lib/rolify/matchers.rb +2 -2
  30. data/lib/rolify/resource.rb +1 -1
  31. data/lib/rolify/role.rb +11 -2
  32. data/lib/rolify/version.rb +1 -1
  33. data/rolify.gemspec +15 -7
  34. data/spec/common_helper.rb +16 -0
  35. data/spec/generators/rolify/rolify_activerecord_generator_spec.rb +112 -6
  36. data/spec/generators_helper.rb +9 -2
  37. data/spec/rolify/config_spec.rb +2 -0
  38. data/spec/rolify/custom_spec.rb +1 -1
  39. data/spec/rolify/resource_spec.rb +6 -0
  40. data/spec/rolify/shared_examples/shared_examples_for_finders.rb +50 -32
  41. data/spec/rolify/shared_examples/shared_examples_for_has_role.rb +65 -0
  42. data/spec/rolify/utils_spec.rb +19 -0
  43. data/spec/spec_helper.rb +19 -6
  44. data/spec/support/adapters/active_record.rb +4 -3
  45. data/spec/support/adapters/mongoid.rb +19 -2
  46. data/spec/support/adapters/{mongoid.yml → mongoid_5.yml} +2 -2
  47. data/spec/support/adapters/mongoid_6.yml +6 -0
  48. data/spec/support/adapters/mongoid_7.yml +6 -0
  49. data/spec/support/adapters/utils/active_record.rb +12 -0
  50. data/spec/support/adapters/utils/mongoid.rb +13 -0
  51. metadata +60 -26
  52. data/.travis.yml +0 -25
  53. data/gemfiles/Gemfile.rails-3.2 +0 -27
  54. data/gemfiles/Gemfile.rails-4.0 +0 -33
  55. data/gemfiles/Gemfile.rails-4.1 +0 -37
@@ -52,9 +52,8 @@ module Rolify
52
52
  private
53
53
 
54
54
  def sanity_check(role_cnames)
55
- return true if (ARGV[0] =~ /assets:/) == 0
55
+ return true if ARGV.reduce(nil) { |acc,arg| arg =~ /assets:/ if acc.nil? } == 0
56
56
 
57
- role_cnames = [ "Role" ] if role_cnames.empty?
58
57
  role_cnames.each do |role_cname|
59
58
  role_class = role_cname.constantize
60
59
  if role_class.superclass.to_s == "ActiveRecord::Base" && role_table_missing?(role_class)
@@ -67,6 +66,9 @@ module Rolify
67
66
 
68
67
  def role_table_missing?(role_class)
69
68
  !role_class.table_exists?
69
+ rescue ActiveRecord::NoDatabaseError
70
+ true
70
71
  end
72
+
71
73
  end
72
74
  end
@@ -2,29 +2,15 @@ require "rolify/configure"
2
2
 
3
3
  module Rolify
4
4
  module Dynamic
5
- def load_dynamic_methods
6
- if ENV['ADAPTER'] == 'active_record'
7
- # supported Rails version >= 3.2 with AR should use find_each, since use of .all.each is deprecated
8
- self.role_class.includes(:resource).find_each do |r|
9
- define_dynamic_method(r.name, r.resource)
10
- end
11
- else
12
- # for compatibility with MongoidDB and older Rails AR - does not support polymorphic includes
13
- self.role_class.all.each do |r|
14
- define_dynamic_method(r.name, r.resource)
15
- end
16
- end
17
- end
18
-
19
5
  def define_dynamic_method(role_name, resource)
20
6
  class_eval do
21
7
  define_method("is_#{role_name}?".to_sym) do
22
8
  has_role?("#{role_name}")
23
- end if !method_defined?("is_#{role_name}?".to_sym)
9
+ end if !method_defined?("is_#{role_name}?".to_sym) && self.adapter.where_strict(self.role_class, name: role_name).exists?
24
10
 
25
11
  define_method("is_#{role_name}_of?".to_sym) do |arg|
26
12
  has_role?("#{role_name}", arg)
27
- end if !method_defined?("is_#{role_name}_of?".to_sym) && resource
13
+ end if !method_defined?("is_#{role_name}_of?".to_sym) && resource && self.adapter.where_strict(self.role_class, name: role_name, resource: resource).exists?
28
14
  end
29
15
  end
30
16
  end
@@ -1,7 +1,12 @@
1
1
  module Rolify
2
2
  module Finders
3
3
  def with_role(role_name, resource = nil)
4
- self.adapter.scope(self, :name => role_name, :resource => resource)
4
+ strict = self.strict_rolify and resource and resource != :any
5
+ self.adapter.scope(
6
+ self,
7
+ { :name => role_name, :resource => resource },
8
+ strict
9
+ )
5
10
  end
6
11
 
7
12
  def without_role(role_name, resource = nil)
@@ -5,11 +5,11 @@ RSpec::Matchers.define :have_role do |*args|
5
5
  resource.has_role?(*args)
6
6
  end
7
7
 
8
- failure_message_for_should do |resource|
8
+ failure_message do |resource|
9
9
  "expected to have role #{args.map(&:inspect).join(" ")}"
10
10
  end
11
11
 
12
- failure_message_for_should_not do |resource|
12
+ failure_message_when_negated do |resource|
13
13
  "expected not to have role #{args.map(&:inspect).join(" ")}"
14
14
  end
15
15
  end
@@ -11,7 +11,7 @@ module Rolify
11
11
 
12
12
  def with_role(role_name, user = nil)
13
13
  if role_name.is_a? Array
14
- role_name.map!(&:to_s)
14
+ role_name = role_name.map(&:to_s)
15
15
  else
16
16
  role_name = role_name.to_s
17
17
  end
data/lib/rolify/role.rb CHANGED
@@ -44,6 +44,15 @@ module Rolify
44
44
  self.class.adapter.where_strict(self.roles, name: role_name, resource: resource).any?
45
45
  end
46
46
 
47
+ def has_cached_role?(role_name, resource = nil)
48
+ return has_strict_cached_role?(role_name, resource) if self.class.strict_rolify and resource and resource != :any
49
+ self.class.adapter.find_cached(self.roles, name: role_name, resource: resource).any?
50
+ end
51
+
52
+ def has_strict_cached_role?(role_name, resource = nil)
53
+ self.class.adapter.find_cached_strict(self.roles, name: role_name, resource: resource).any?
54
+ end
55
+
47
56
  def has_all_roles?(*args)
48
57
  args.each do |arg|
49
58
  if arg.is_a? Hash
@@ -77,7 +86,7 @@ module Rolify
77
86
  deprecate :has_no_role, :remove_role
78
87
 
79
88
  def roles_name
80
- self.roles.select(:name).map { |r| r.name }
89
+ self.roles.pluck(:name)
81
90
  end
82
91
 
83
92
  def method_missing(method, *args, &block)
@@ -85,7 +94,7 @@ module Rolify
85
94
  resource = args.first
86
95
  self.class.define_dynamic_method $1, resource
87
96
  return has_role?("#{$1}", resource)
88
- end unless !Rolify.dynamic_shortcuts
97
+ end if Rolify.dynamic_shortcuts
89
98
  super
90
99
  end
91
100
 
@@ -1,3 +1,3 @@
1
1
  module Rolify
2
- VERSION = "4.1.1"
2
+ VERSION = "6.0.0"
3
3
  end
data/rolify.gemspec CHANGED
@@ -9,20 +9,28 @@ Gem::Specification.new do |s|
9
9
  s.version = Rolify::VERSION
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.homepage = 'https://github.com/RolifyCommunity/rolify'
12
- s.rubyforge_project = s.name
13
12
 
14
13
  s.license = 'MIT'
15
14
 
16
- s.authors = ['Florent Monbillard']
17
- s.email = ['f.monbillard@gmail.com']
15
+ s.authors = [
16
+ 'Florent Monbillard',
17
+ 'Wellington Cordeiro'
18
+ ]
19
+ s.email = [
20
+ 'f.monbillard@gmail.com',
21
+ 'wellington@wellingtoncordeiro.com'
22
+ ]
18
23
 
19
24
  s.files = `git ls-files`.split("\n")
20
25
  s.test_files = `git ls-files -- spec/*`.split("\n")
21
26
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
27
  s.require_paths = ['lib']
23
28
 
24
- s.add_development_dependency 'ammeter', '~> 1.1.2' # Spec generator
25
- s.add_development_dependency 'bundler', '>= 1.7.12' # packaging feature
26
- s.add_development_dependency 'rake', '~> 10.4.2' # Tasks manager
27
- s.add_development_dependency 'rspec-rails', '2.99.0'
29
+ s.required_ruby_version = '>= 2.5'
30
+
31
+ s.add_development_dependency 'ammeter', '~> 1.1' # Spec generator
32
+ s.add_development_dependency 'appraisal', '~> 2.0'
33
+ s.add_development_dependency 'bundler', '~> 2.0' # packaging feature
34
+ s.add_development_dependency 'rake', '~> 12.3' # Tasks manager
35
+ s.add_development_dependency 'rspec-rails', '~> 3.8'
28
36
  end
@@ -0,0 +1,16 @@
1
+ require 'test-unit'
2
+
3
+ begin
4
+ require 'pry'
5
+ rescue LoadError
6
+ end
7
+
8
+ # `Test::Unit::AutoRunner.need_auto_run=` was introduced to the test-unit
9
+ # gem in version 2.4.9. Previous to this version `Test::Unit.run=` was
10
+ # used. The implementation of test-unit included with Ruby has neither
11
+ # method.
12
+ if defined? Test::Unit::AutoRunner
13
+ Test::Unit::AutoRunner.need_auto_run = false
14
+ elsif defined?(Test::Unit)
15
+ Test::Unit.run = false
16
+ end
@@ -8,6 +8,7 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
8
8
  destination File.expand_path("../../../../tmp", __FILE__)
9
9
  teardown :cleanup_destination_root
10
10
 
11
+ let(:adapter) { 'SQLite3Adapter' }
11
12
  before {
12
13
  prepare_destination
13
14
  }
@@ -20,6 +21,8 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
20
21
  before(:all) { arguments %w(Role) }
21
22
 
22
23
  before {
24
+ allow(ActiveRecord::Base).to receive_message_chain(
25
+ 'connection.class.to_s.demodulize') { adapter }
23
26
  capture(:stdout) {
24
27
  generator.create_file "app/models/user.rb" do
25
28
  <<-RUBY
@@ -43,12 +46,32 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
43
46
  describe 'app/models/role.rb' do
44
47
  subject { file('app/models/role.rb') }
45
48
  it { should exist }
46
- it { should contain "class Role < ActiveRecord::Base" }
49
+ it do
50
+ if Rails::VERSION::MAJOR < 5
51
+ should contain "class Role < ActiveRecord::Base"
52
+ else
53
+ should contain "class Role < ApplicationRecord"
54
+ end
55
+ end
47
56
  it { should contain "has_and_belongs_to_many :users, :join_table => :users_roles" }
48
- it { should contain "belongs_to :resource, :polymorphic => true" }
57
+ it do
58
+ if Rails::VERSION::MAJOR < 5
59
+ should contain "belongs_to :resource,\n"
60
+ " :polymorphic => true"
61
+ else
62
+ should contain "belongs_to :resource,\n"
63
+ " :polymorphic => true,\n"
64
+ " :optional => true"
65
+ end
66
+ end
67
+ it { should contain "belongs_to :resource,\n"
68
+ " :polymorphic => true,\n"
69
+ " :optional => true"
70
+ }
49
71
  it { should contain "validates :resource_type,\n"
50
72
  " :inclusion => { :in => Rolify.resource_types },\n"
51
73
  " :allow_nil => true" }
74
+ it { should contain "scopify" }
52
75
  end
53
76
 
54
77
  describe 'app/models/user.rb' do
@@ -62,6 +85,24 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
62
85
  it { should be_a_migration }
63
86
  it { should contain "create_table(:roles) do" }
64
87
  it { should contain "create_table(:users_roles, :id => false) do" }
88
+
89
+ context 'mysql2' do
90
+ let(:adapter) { 'Mysql2Adapter' }
91
+
92
+ it { expect(subject).to contain('add_index(:roles, :name)') }
93
+ end
94
+
95
+ context 'sqlite3' do
96
+ let(:adapter) { 'SQLite3Adapter' }
97
+
98
+ it { expect(subject).to contain('add_index(:roles, :name)') }
99
+ end
100
+
101
+ context 'pg' do
102
+ let(:adapter) { 'PostgreSQLAdapter' }
103
+
104
+ it { expect(subject).not_to contain('add_index(:roles, :name)') }
105
+ end
65
106
  end
66
107
  end
67
108
 
@@ -69,6 +110,8 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
69
110
  before(:all) { arguments %w(AdminRole AdminUser) }
70
111
 
71
112
  before {
113
+ allow(ActiveRecord::Base).to receive_message_chain(
114
+ 'connection.class.to_s.demodulize') { adapter }
72
115
  capture(:stdout) {
73
116
  generator.create_file "app/models/admin_user.rb" do
74
117
  "class AdminUser < ActiveRecord::Base\nend"
@@ -91,9 +134,18 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
91
134
  subject { file('app/models/admin_role.rb') }
92
135
 
93
136
  it { should exist }
94
- it { should contain "class AdminRole < ActiveRecord::Base" }
137
+ it do
138
+ if Rails::VERSION::MAJOR < 5
139
+ should contain "class AdminRole < ActiveRecord::Base"
140
+ else
141
+ should contain "class AdminRole < ApplicationRecord"
142
+ end
143
+ end
95
144
  it { should contain "has_and_belongs_to_many :admin_users, :join_table => :admin_users_admin_roles" }
96
- it { should contain "belongs_to :resource, :polymorphic => true" }
145
+ it { should contain "belongs_to :resource,\n"
146
+ " :polymorphic => true,\n"
147
+ " :optional => true"
148
+ }
97
149
  end
98
150
 
99
151
  describe 'app/models/admin_user.rb' do
@@ -108,6 +160,24 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
108
160
  it { should be_a_migration }
109
161
  it { should contain "create_table(:admin_roles)" }
110
162
  it { should contain "create_table(:admin_users_admin_roles, :id => false) do" }
163
+
164
+ context 'mysql2' do
165
+ let(:adapter) { 'Mysql2Adapter' }
166
+
167
+ it { expect(subject).to contain('add_index(:admin_roles, :name)') }
168
+ end
169
+
170
+ context 'sqlite3' do
171
+ let(:adapter) { 'SQLite3Adapter' }
172
+
173
+ it { expect(subject).to contain('add_index(:admin_roles, :name)') }
174
+ end
175
+
176
+ context 'pg' do
177
+ let(:adapter) { 'PostgreSQLAdapter' }
178
+
179
+ it { expect(subject).not_to contain('add_index(:admin_roles, :name)') }
180
+ end
111
181
  end
112
182
  end
113
183
 
@@ -115,6 +185,8 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
115
185
  before(:all) { arguments %w(Admin::Role Admin::User) }
116
186
 
117
187
  before {
188
+ allow(ActiveRecord::Base).to receive_message_chain(
189
+ 'connection.class.to_s.demodulize') { adapter }
118
190
  capture(:stdout) {
119
191
  generator.create_file "app/models/admin/user.rb" do
120
192
  <<-RUBY
@@ -143,9 +215,18 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
143
215
  subject { file('app/models/admin/role.rb') }
144
216
 
145
217
  it { should exist }
146
- it { should contain "class Admin::Role < ActiveRecord::Base" }
218
+ it do
219
+ if Rails::VERSION::MAJOR < 5
220
+ should contain "class Admin::Role < ActiveRecord::Base"
221
+ else
222
+ should contain "class Admin::Role < ApplicationRecord"
223
+ end
224
+ end
147
225
  it { should contain "has_and_belongs_to_many :admin_users, :join_table => :admin_users_admin_roles" }
148
- it { should contain "belongs_to :resource, :polymorphic => true" }
226
+ it { should contain "belongs_to :resource,\n"
227
+ " :polymorphic => true,\n"
228
+ " :optional => true"
229
+ }
149
230
  end
150
231
 
151
232
  describe 'app/models/admin/user.rb' do
@@ -160,6 +241,31 @@ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_r
160
241
  it { should be_a_migration }
161
242
  it { should contain "create_table(:admin_roles)" }
162
243
  it { should contain "create_table(:admin_users_admin_roles, :id => false) do" }
244
+ it do
245
+ if Rails::VERSION::MAJOR < 5
246
+ should contain "< ActiveRecord::Migration"
247
+ else
248
+ should contain "< ActiveRecord::Migration[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
249
+ end
250
+ end
251
+
252
+ context 'mysql2' do
253
+ let(:adapter) { 'Mysql2Adapter' }
254
+
255
+ it { expect(subject).to contain('add_index(:admin_roles, :name)') }
256
+ end
257
+
258
+ context 'sqlite3' do
259
+ let(:adapter) { 'SQLite3Adapter' }
260
+
261
+ it { expect(subject).to contain('add_index(:admin_roles, :name)') }
262
+ end
263
+
264
+ context 'pg' do
265
+ let(:adapter) { 'PostgreSQLAdapter' }
266
+
267
+ it { expect(subject).not_to contain('add_index(:admin_roles, :name)') }
268
+ end
163
269
  end
164
270
  end
165
271
  end
@@ -1,21 +1,28 @@
1
1
  require 'rubygems'
2
2
  require "bundler/setup"
3
3
 
4
+ require 'pry'
5
+
4
6
  require 'rolify'
5
7
  require 'rolify/matchers'
6
- require 'rails'
8
+ require 'rails/all'
7
9
  require_relative 'support/stream_helpers'
8
10
  include StreamHelpers
9
11
 
10
12
  require 'coveralls'
11
13
  Coveralls.wear_merged!
12
14
 
15
+ require 'common_helper'
16
+
13
17
  ENV['ADAPTER'] ||= 'active_record'
14
18
 
15
19
  if ENV['ADAPTER'] == 'active_record'
20
+ load File.dirname(__FILE__) + '/support/adapters/utils/active_record.rb'
16
21
  require 'active_record/railtie'
22
+ establish_connection
17
23
  else
18
- require 'mongoid'
24
+ load File.dirname(__FILE__) + '/support/adapters/utils/mongoid.rb'
25
+ load_mongoid_config
19
26
  end
20
27
 
21
28
  module TestApp
@@ -161,6 +161,8 @@ describe Rolify do
161
161
  config.orm = "mongoid"
162
162
  end
163
163
  end
164
+
165
+ subject { Rolify }
164
166
 
165
167
  its(:dynamic_shortcuts) { should be_truthy }
166
168
  its(:orm) { should eq("mongoid") }
@@ -17,4 +17,4 @@ describe "Using Rolify with custom User and Role class names" do
17
17
  it_behaves_like "Role.scopes"
18
18
  it_behaves_like Rolify::Dynamic
19
19
  it_behaves_like "Rolify.callbacks"
20
- end
20
+ end
@@ -542,29 +542,35 @@ describe Rolify::Resource do
542
542
  context "strict user" do
543
543
  before(:all) do
544
544
  @strict_user = StrictUser.first
545
+ @strict_user.role_ids
545
546
  @strict_user.add_role(:forum, Forum.first)
546
547
  @strict_user.add_role(:forum, Forum)
547
548
  end
548
549
 
549
550
  it "should return only strict forum" do
550
551
  @strict_user.has_role?(:forum, Forum.first).should be true
552
+ @strict_user.has_cached_role?(:forum, Forum.first).should be true
551
553
  end
552
554
 
553
555
  it "should return false on strict another forum" do
554
556
  @strict_user.has_role?(:forum, Forum.last).should be false
557
+ @strict_user.has_cached_role?(:forum, Forum.last).should be false
555
558
  end
556
559
 
557
560
  it "should return true if user has role on Forum model" do
558
561
  @strict_user.has_role?(:forum, Forum).should be true
562
+ @strict_user.has_cached_role?(:forum, Forum).should be true
559
563
  end
560
564
 
561
565
  it "should return true if user has role any forum name" do
562
566
  @strict_user.has_role?(:forum, :any).should be true
567
+ @strict_user.has_cached_role?(:forum, :any).should be true
563
568
  end
564
569
 
565
570
  it "should return false when deleted role on Forum model" do
566
571
  @strict_user.remove_role(:forum, Forum)
567
572
  @strict_user.has_role?(:forum, Forum).should be false
573
+ @strict_user.has_cached_role?(:forum, Forum).should be false
568
574
  end
569
575
  end
570
576
  end