canard 0.5.0.pre → 0.6.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/.hound.yml +3 -0
  3. data/.rubocop.yml +27 -0
  4. data/.rubocop_todo.yml +37 -0
  5. data/.travis.yml +1 -1
  6. data/Gemfile +7 -6
  7. data/README.md +40 -37
  8. data/Rakefile +5 -2
  9. data/canard.gemspec +8 -7
  10. data/lib/ability.rb +14 -13
  11. data/lib/canard.rb +4 -2
  12. data/lib/canard/abilities.rb +7 -9
  13. data/lib/canard/adapters/active_record.rb +32 -29
  14. data/lib/canard/adapters/mongoid.rb +18 -11
  15. data/lib/canard/find_abilities.rb +8 -9
  16. data/lib/canard/railtie.rb +11 -16
  17. data/lib/canard/user_model.rb +66 -67
  18. data/lib/canard/version.rb +3 -1
  19. data/lib/generators/ability_definition.rb +16 -14
  20. data/lib/generators/canard/ability/ability_generator.rb +16 -12
  21. data/lib/generators/rspec/ability/ability_generator.rb +9 -9
  22. data/lib/tasks/canard.rake +6 -6
  23. data/test/abilities/administrators.rb +2 -2
  24. data/test/canard/abilities_test.rb +14 -21
  25. data/test/canard/ability_test.rb +40 -52
  26. data/test/canard/adapters/active_record_test.rb +71 -135
  27. data/test/canard/adapters/mongoid_test.rb +61 -132
  28. data/test/canard/canard_test.rb +8 -10
  29. data/test/canard/find_abilities_test.rb +9 -11
  30. data/test/canard/user_model_test.rb +22 -32
  31. data/test/dummy/Rakefile +3 -1
  32. data/test/dummy/app/abilities/admins.rb +4 -4
  33. data/test/dummy/app/abilities/authors.rb +3 -3
  34. data/test/dummy/app/abilities/editors.rb +2 -2
  35. data/test/dummy/app/abilities/guests.rb +3 -3
  36. data/test/dummy/app/abilities/users.rb +4 -4
  37. data/test/dummy/app/controllers/application_controller.rb +2 -0
  38. data/test/dummy/app/models/activity.rb +3 -1
  39. data/test/dummy/app/models/member.rb +3 -3
  40. data/test/dummy/app/models/mongoid_user.rb +5 -3
  41. data/test/dummy/app/models/plain_ruby_non_user.rb +2 -2
  42. data/test/dummy/app/models/plain_ruby_user.rb +3 -3
  43. data/test/dummy/app/models/post.rb +3 -1
  44. data/test/dummy/app/models/user.rb +3 -2
  45. data/test/dummy/app/models/user_without_role.rb +4 -4
  46. data/test/dummy/app/models/user_without_role_mask.rb +3 -3
  47. data/test/dummy/config.ru +3 -1
  48. data/test/dummy/config/application.rb +9 -8
  49. data/test/dummy/config/boot.rb +4 -2
  50. data/test/dummy/config/environment.rb +3 -1
  51. data/test/dummy/config/environments/development.rb +2 -0
  52. data/test/dummy/config/environments/test.rb +4 -2
  53. data/test/dummy/config/initializers/secret_token.rb +2 -0
  54. data/test/dummy/config/initializers/session_store.rb +3 -1
  55. data/test/dummy/config/initializers/wrap_parameters.rb +3 -1
  56. data/test/dummy/config/mongoid3.yml +5 -1
  57. data/test/dummy/config/routes.rb +2 -0
  58. data/test/dummy/db/migrate/20120430083231_initialize_db.rb +7 -7
  59. data/test/dummy/db/schema.rb +11 -11
  60. data/test/dummy/script/rails +4 -2
  61. data/test/support/reloadable.rb +14 -15
  62. data/test/test_helper.rb +7 -13
  63. metadata +18 -18
  64. data/test/dummy/config/mongoid2.yml +0 -9
@@ -1,51 +1,54 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canard
2
4
  module Adapters
3
- module ActiveRecord
4
-
5
+ module ActiveRecord # :nodoc:
5
6
  private
6
7
 
7
- def add_role_scopes(*args)
8
- options = args.extract_options!
9
- # TODO change to check has_roles_attribute?
10
- if active_record_table?
11
- valid_roles.each do |role|
12
- define_scopes_for_role role, options[:prefix]
13
- end
14
-
15
- # TODO change hard coded :role_mask to roles_attribute_name
16
- define_singleton_method(:with_any_role) do |*roles|
17
- where("#{role_mask_column} & :role_mask > 0", { :role_mask => mask_for(*roles) })
18
- end
19
-
20
- define_singleton_method(:with_all_roles) do |*roles|
21
- where("#{role_mask_column} & :role_mask = :role_mask", { :role_mask => mask_for(*roles) })
22
- end
23
-
24
- define_singleton_method(:with_only_roles) do |*roles|
25
- where("#{role_mask_column} = :role_mask", { :role_mask => mask_for(*roles) })
26
- end
8
+ def add_role_scopes(**options)
9
+ define_scopes(options) if active_record_table_exists?
10
+ end
11
+
12
+ def define_scopes(options)
13
+ valid_roles.each do |role|
14
+ define_scopes_for_role role, options[:prefix]
15
+ end
16
+
17
+ # TODO: change hard coded :role_mask to roles_attribute_name
18
+ define_singleton_method(:with_any_role) do |*roles|
19
+ where("#{role_mask_column} & :role_mask > 0", role_mask: mask_for(*roles))
20
+ end
21
+
22
+ define_singleton_method(:with_all_roles) do |*roles|
23
+ where("#{role_mask_column} & :role_mask = :role_mask", role_mask: mask_for(*roles))
24
+ end
25
+
26
+ define_singleton_method(:with_only_roles) do |*roles|
27
+ where("#{role_mask_column} = :role_mask", role_mask: mask_for(*roles))
27
28
  end
28
29
  end
29
30
 
30
- def active_record_table?
31
+ def active_record_table_exists?
31
32
  respond_to?(:table_exists?) && table_exists?
33
+ rescue ActiveRecord::NoDatabaseError, StandardError
34
+ false
32
35
  end
33
36
 
34
- # TODO extract has_roles_attribute? and change to has_roles_attribute? || super
37
+ # TODO: extract has_roles_attribute? and change to has_roles_attribute? || super
35
38
  def has_roles_mask_accessors?
36
- active_record_table? && column_names.include?(roles_attribute_name.to_s) || super
39
+ active_record_table_exists? && column_names.include?(roles_attribute_name.to_s) || super
37
40
  end
38
41
 
39
- def define_scopes_for_role(role, prefix=nil)
42
+ def define_scopes_for_role(role, prefix = nil)
40
43
  include_scope = [prefix, String(role).pluralize].compact.join('_')
41
44
  exclude_scope = "non_#{include_scope}"
42
45
 
43
46
  define_singleton_method(include_scope) do
44
- where("#{role_mask_column} & :role_mask > 0", { :role_mask => mask_for(role) })
47
+ where("#{role_mask_column} & :role_mask > 0", role_mask: mask_for(role))
45
48
  end
46
49
 
47
50
  define_singleton_method(exclude_scope) do
48
- where("#{role_mask_column} & :role_mask = 0 or #{role_mask_column} is null", { :role_mask => mask_for(role) })
51
+ where("#{role_mask_column} & :role_mask = 0 or #{role_mask_column} is null", role_mask: mask_for(role))
49
52
  end
50
53
  end
51
54
 
@@ -54,4 +57,4 @@ module Canard
54
57
  end
55
58
  end
56
59
  end
57
- end
60
+ end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canard
2
4
  module Adapters
3
- module Mongoid
4
-
5
+ module Mongoid # :nodoc:
5
6
  private
6
7
 
7
8
  def add_role_scopes(*args)
@@ -10,34 +11,40 @@ module Canard
10
11
  define_scopes_for_role role, options[:prefix]
11
12
  end
12
13
 
13
- def with_any_role(*roles)
14
+ define_singleton_method(:with_any_role) do |*roles|
14
15
  where("(this.#{roles_attribute_name} & #{mask_for(*roles)}) > 0")
15
16
  end
16
17
 
17
- def with_all_roles(*roles)
18
+ define_singleton_method(:with_all_roles) do |*roles|
18
19
  where("(this.#{roles_attribute_name} & #{mask_for(*roles)}) === #{mask_for(*roles)}")
19
20
  end
20
21
 
21
- def with_only_roles(*roles)
22
+ define_singleton_method(:with_only_roles) do |*roles|
22
23
  where("this.#{roles_attribute_name} === #{mask_for(*roles)}")
23
24
  end
24
25
  end
25
26
 
26
27
  def has_roles_mask_accessors?
27
- fields.include?(roles_attribute_name.to_s) || super
28
+ fields.include?(roles_attribute_name.to_s) || super
28
29
  end
29
30
 
30
- def define_scopes_for_role(role, prefix=nil)
31
+ def define_scopes_for_role(role, prefix = nil)
31
32
  include_scope = [prefix, String(role).pluralize].compact.join('_')
32
33
  exclude_scope = "non_#{include_scope}"
33
34
 
34
35
  scope include_scope, -> { where("(this.#{roles_attribute_name} & #{mask_for(role)}) > 0") }
35
- scope exclude_scope, -> { any_of({roles_attribute_name => { "$exists" => false }}, {roles_attribute_name => nil}, {"$where" => "(this.#{roles_attribute_name} & #{mask_for(role)}) === 0"}) }
36
+ scope exclude_scope, lambda {
37
+ any_of(
38
+ { roles_attribute_name => { '$exists' => false } },
39
+ { roles_attribute_name => nil },
40
+ '$where' => "(this.#{roles_attribute_name} & #{mask_for(role)}) === 0"
41
+ )
42
+ }
36
43
  end
37
44
  end
38
45
  end
39
46
  end
40
47
 
41
- Mongoid::Document::ClassMethods.send :include, Canard::Adapters::Mongoid
42
- Mongoid::Document::ClassMethods.send :include, Canard::UserModel
43
- Canard.find_abilities
48
+ Mongoid::Document::ClassMethods.send(:include, Canard::Adapters::Mongoid)
49
+ Mongoid::Document::ClassMethods.send(:include, Canard::UserModel)
50
+ Canard.find_abilities
@@ -1,15 +1,16 @@
1
- module Canard
1
+ # frozen_string_literal: true
2
2
 
3
+ module Canard # :nodoc:
3
4
  def self.ability_definitions
4
5
  Abilities.definitions
5
6
  end
6
7
 
7
8
  def self.ability_key(class_name)
8
- klass_name = String(class_name)
9
- klass_name.gsub!('::', '')
10
- klass_name.gsub!(/(.)([A-Z])/,'\1_\2')
11
- klass_name.downcase!
12
- klass_name.to_sym
9
+ String(class_name)
10
+ .gsub('::', '')
11
+ .gsub(/(.)([A-Z])/, '\1_\2')
12
+ .downcase
13
+ .to_sym
13
14
  end
14
15
 
15
16
  def self.load_paths
@@ -22,7 +23,5 @@ module Canard
22
23
  load file
23
24
  end
24
25
  end
25
-
26
26
  end
27
-
28
- end
27
+ end
@@ -1,21 +1,18 @@
1
- require 'canard'
2
- require 'rails'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Canard
5
- class Railtie < Rails::Railtie
6
-
7
- initializer "canard.no_eager_loading", :before => 'before_eager_loading' do |app|
8
- ActiveSupport::Dependencies.autoload_paths.reject!{ |path| Canard.load_paths.include?(path) }
4
+ class Railtie < Rails::Railtie # :nodoc:
5
+ initializer 'canard.no_eager_loading', before: 'before_eager_loading' do |app|
6
+ ActiveSupport::Dependencies.autoload_paths.reject! { |path| Canard.load_paths.include?(path) }
9
7
  # Don't eagerload our configs, we'll deal with them ourselves
10
8
  app.config.eager_load_paths = app.config.eager_load_paths.reject do |path|
11
9
  Canard.load_paths.include?(path)
12
10
  end
13
- if app.config.respond_to?(:watchable_dirs)
14
- app.config.watchable_dirs.merge! Hash[ Canard.load_paths.product([[:rb]]) ]
15
- end
11
+
12
+ app.config.watchable_dirs.merge! Hash[Canard.load_paths.product([[:rb]])] if app.config.respond_to?(:watchable_dirs)
16
13
  end
17
14
 
18
- initializer "canard.active_record" do |app|
15
+ initializer 'canard.active_record' do |_app|
19
16
  ActiveSupport.on_load :active_record do
20
17
  require 'canard/adapters/active_record'
21
18
  Canard::Abilities.default_path = File.expand_path('app/abilities', Rails.root)
@@ -24,19 +21,17 @@ module Canard
24
21
  end
25
22
  end
26
23
 
27
- initializer "canard.mongoid" do |app|
24
+ initializer 'canard.mongoid' do |_app|
28
25
  require 'canard/adapters/mongoid' if defined?(Mongoid)
29
26
  end
30
27
 
31
- initializer "canard.abilities_reloading", :after => "action_dispatch.configure" do |app|
28
+ initializer 'canard.abilities_reloading', after: 'action_dispatch.configure' do |_app|
32
29
  reloader = rails5? ? ActiveSupport::Reloader : ActionDispatch::Reloader
33
- if reloader.respond_to?(:to_prepare)
34
- reloader.to_prepare { Canard.find_abilities }
35
- end
30
+ reloader.to_prepare { Canard.find_abilities } if reloader.respond_to?(:to_prepare)
36
31
  end
37
32
 
38
33
  rake_tasks do
39
- load File.expand_path('../../tasks/canard.rake', __FILE__)
34
+ load File.expand_path('../tasks/canard.rake', __dir__)
40
35
  end
41
36
 
42
37
  private
@@ -1,77 +1,78 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canard
4
+ # Canard applies roles to a model using the acts_as_user class method. The following User model
5
+ # will be given the :manager and :admin roles
6
+ #
7
+ # class User < ActiveRecord::Base
8
+ #
9
+ # acts_as_user :roles => [:manager, :admin]
10
+ #
11
+ # end
12
+ #
13
+ # If using Canard with a non ActiveRecord class you can still assign roles but you will need to
14
+ # extend the class with Canard::UserModel and add a roles_mask attribute.
15
+ #
16
+ # class User
17
+ #
18
+ # extend Canard::UserModel
19
+ #
20
+ # attr_accessor :roles_mask
21
+ #
22
+ # acts_as_user :roles => [:manager, :admin]
23
+ #
24
+ # end
25
+ #
26
+ # You can choose the attribute used for the roles_mask by specifying :roles_mask. If no
27
+ # roles_mask is specified it uses RoleModel's default of 'roles_mask'
28
+ #
29
+ # acts_as_user :roles_mask => :my_roles_mask, :roles => [:manager, :admin]
30
+ #
31
+ # == Scopes
32
+ #
33
+ # Beyond applying the roles to the model, acts_as_user also creates some useful scopes for
34
+ # ActiveRecord models;
35
+ #
36
+ # User.with_any_role(:manager, :admin)
37
+ #
38
+ # returns all the managers and admins
39
+ #
40
+ # User.with_all_roles(:manager, :admin)
41
+ #
42
+ # returns only the users with both the manager and admin roles
43
+ #
44
+ # User.admins
45
+ #
46
+ # returns all the admins as
47
+ #
48
+ # User.managers
49
+ #
50
+ # returns all the users with the maager role likewise
51
+ #
52
+ # User.non_admins
53
+ #
54
+ # returns all the users who don't have the admin role and
55
+ #
56
+ # User.non_managers
57
+ #
58
+ # returns all the users who don't have the manager role.
2
59
  module UserModel
3
-
4
- # Canard applies roles to a model using the acts_as_user class method. The following User model
5
- # will be given the :manager and :admin roles
6
- #
7
- # class User < ActiveRecord::Base
8
- #
9
- # acts_as_user :roles => [:manager, :admin]
10
- #
11
- # end
12
- #
13
- # If using Canard with a non ActiveRecord class you can still assign roles but you will need to
14
- # extend the class with Canard::UserModel and add a roles_mask attribute.
15
- #
16
- # class User
17
- #
18
- # extend Canard::UserModel
19
- #
20
- # attr_accessor :roles_mask
21
- #
22
- # acts_as_user :roles => [:manager, :admin]
23
- #
24
- # end
25
- #
26
- # You can choose the attribute used for the roles_mask by specifying :roles_mask. If no
27
- # roles_mask is specified it uses RoleModel's default of 'roles_mask'
28
- #
29
- # acts_as_user :roles_mask => :my_roles_mask, :roles => [:manager, :admin]
30
- #
31
- # == Scopes
32
- #
33
- # Beyond applying the roles to the model, acts_as_user also creates some useful scopes for
34
- # ActiveRecord models;
35
- #
36
- # User.with_any_role(:manager, :admin)
37
- #
38
- # returns all the managers and admins
39
- #
40
- # User.with_all_roles(:manager, :admin)
41
- #
42
- # returns only the users with both the manager and admin roles
43
- #
44
- # User.admins
45
- #
46
- # returns all the admins as
47
- #
48
- # User.managers
49
- #
50
- # returns all the users with the maager role likewise
51
- #
52
- # User.non_admins
53
- #
54
- # returns all the users who don't have the admin role and
55
- #
56
- # User.non_managers
57
- #
58
- # returns all the users who don't have the manager role.
59
60
  def acts_as_user(*args)
60
61
  include RoleModel
61
62
  include InstanceMethods
62
-
63
+
63
64
  options = args.last.is_a?(Hash) ? args.pop : {}
64
-
65
+
65
66
  if defined?(ActiveRecord) && self < ActiveRecord::Base
66
67
  extend Adapters::ActiveRecord
67
- elsif defined?(Mongoid) && self.included_modules.include?(Mongoid::Document)
68
+ elsif defined?(Mongoid) && included_modules.include?(Mongoid::Document)
68
69
  extend Adapters::Mongoid
69
- field (options[:roles_mask] || :roles_mask), :type => Integer
70
+ field (options[:roles_mask] || :roles_mask), type: Integer
70
71
  end
71
72
 
72
- roles_attribute options[:roles_mask] if options.has_key?(:roles_mask)
73
+ roles_attribute options[:roles_mask] if options.key?(:roles_mask)
73
74
 
74
- roles options[:roles] if options.has_key?(:roles) && has_roles_mask_accessors?
75
+ roles options[:roles] if options.key?(:roles) && has_roles_mask_accessors?
75
76
 
76
77
  add_role_scopes(prefix: options[:prefix]) if respond_to?(:add_role_scopes, true)
77
78
  end
@@ -81,18 +82,16 @@ module Canard
81
82
  # This is overridden by the ActiveRecord adapter as the attribute accessors
82
83
  # don't show up in instance_methods.
83
84
  def has_roles_mask_accessors?
84
- instance_method_names = instance_methods.map { |method_name| method_name.to_s }
85
- [roles_attribute_name.to_s, "#{roles_attribute_name}="].all? do |accessor|
85
+ instance_method_names = instance_methods.map(&:to_s)
86
+ [roles_attribute_name.to_s, "#{roles_attribute_name}="].all? do |accessor|
86
87
  instance_method_names.include?(accessor)
87
88
  end
88
89
  end
89
90
 
90
- module InstanceMethods
91
-
91
+ module InstanceMethods # :nodoc:
92
92
  def ability
93
93
  @ability ||= Ability.new(self)
94
94
  end
95
-
96
95
  end
97
96
  end
98
97
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canard
2
- VERSION = "0.5.0.pre"
4
+ VERSION = '0.6.0.pre'
3
5
  end
@@ -1,43 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/inflector'
2
4
 
3
- class AbilityDefinition
4
-
5
+ class AbilityDefinition # :nodoc:
5
6
  attr_accessor :cans, :cannots
6
-
7
+
7
8
  def self.parse(definitions)
8
9
  @@ability_definitions ||= {}
9
- limitation, ability_list, model_list = *definitions.split(':')
10
- ability_names, model_names = extract(ability_list), extract(model_list)
10
+ limitation, ability_list, model_list = definitions.split(':')
11
+ ability_names = extract(ability_list)
12
+ model_names = extract(model_list)
11
13
  model_names.each do |model_name|
12
14
  definition = @@ability_definitions[model_name] || AbilityDefinition.new
13
15
  definition.merge(limitation.pluralize, ability_names)
14
16
  @@ability_definitions[model_name] = definition
15
17
  end
16
18
  end
17
-
19
+
18
20
  def self.extract(string)
19
- return *string.gsub(/[\[\]\s]/, '').split(',')
21
+ string.gsub(/[\[\]\s]/, '').split(',')
20
22
  end
21
-
23
+
22
24
  def self.models
23
25
  @@ability_definitions
24
26
  end
25
-
27
+
26
28
  def initialize
27
- @cans, @cannots = [], []
29
+ @cans = []
30
+ @cannots = []
28
31
  end
29
-
32
+
30
33
  def merge(limitation, ability_names)
31
34
  combined_ability_names = instance_variable_get("@#{limitation}") | ability_names
32
35
  instance_variable_set("@#{limitation}", combined_ability_names)
33
36
  end
34
-
37
+
35
38
  def can
36
39
  @cans
37
40
  end
38
-
41
+
39
42
  def cannot
40
43
  @cannots
41
44
  end
42
-
43
45
  end