i_am_i_can 3.0.1 → 4.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +236 -174
  4. data/lib/generators/i_am_i_can/setup_generator.rb +3 -7
  5. data/lib/generators/i_am_i_can/templates/migrations/i_am_i_can.erb +8 -8
  6. data/lib/generators/i_am_i_can/templates/models/permission.erb +4 -2
  7. data/lib/generators/i_am_i_can/templates/models/role.erb +3 -1
  8. data/lib/generators/i_am_i_can/templates/models/role_group.erb +3 -1
  9. data/lib/i_am_i_can/configs/config.rb +2 -3
  10. data/lib/i_am_i_can/configs/configs.rb +1 -7
  11. data/lib/i_am_i_can/helpers/dynamic.rb +102 -0
  12. data/lib/i_am_i_can/helpers/result_of.rb +71 -0
  13. data/lib/i_am_i_can/permission/assignment.rb +12 -60
  14. data/lib/i_am_i_can/permission/definition.rb +8 -28
  15. data/lib/i_am_i_can/permission.rb +18 -24
  16. data/lib/i_am_i_can/resource.rb +24 -19
  17. data/lib/i_am_i_can/role/assignment.rb +24 -45
  18. data/lib/i_am_i_can/role/definition.rb +17 -47
  19. data/lib/i_am_i_can/role.rb +14 -0
  20. data/lib/i_am_i_can/role_group/assignment.rb +6 -0
  21. data/lib/i_am_i_can/role_group/definition.rb +25 -0
  22. data/lib/i_am_i_can/subject/permission_querying.rb +28 -40
  23. data/lib/i_am_i_can/subject/role_querying.rb +8 -8
  24. data/lib/i_am_i_can/subject.rb +0 -10
  25. data/lib/i_am_i_can/support/association_class_methods.rb +43 -0
  26. data/lib/i_am_i_can/{configurable.rb → support/configurable.rb} +0 -7
  27. data/lib/i_am_i_can/support/reflection.rb +36 -0
  28. data/lib/i_am_i_can/version.rb +1 -1
  29. data/lib/i_am_i_can.rb +33 -16
  30. metadata +9 -9
  31. data/Gemfile.lock +0 -121
  32. data/lib/i_am_i_can/dynamic_generate.rb +0 -95
  33. data/lib/i_am_i_can/permission/helpers.rb +0 -75
  34. data/lib/i_am_i_can/permission/p_array.rb +0 -22
  35. data/lib/i_am_i_can/reflection.rb +0 -25
  36. data/lib/i_am_i_can/role/helpers.rb +0 -76
@@ -5,14 +5,16 @@ class <%= permission_c %> < ActiveRecord::Base
5
5
  has_and_belongs_to_many :related_role_groups,
6
6
  join_table: '<%= group_pms_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= permission_u %>_id
7
7
  <% end %>
8
+ belongs_to :obj, polymorphic: true
9
+
8
10
  acts_as_permission
9
11
  end
10
12
 
11
13
  __END__
12
14
 
13
- string :pred, null: false
15
+ string :action, null: false
14
16
  string :obj_type
15
17
  integer :obj_id
16
18
  string :desc
17
19
 
18
- index %i[ pred obj_type obj_id ], unique: true
20
+ index %i[ action obj_type obj_id ], unique: true
@@ -5,9 +5,11 @@ class <%= role_c %> < ActiveRecord::Base
5
5
  has_and_belongs_to_many :related_stored_groups,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= role_u %>_id
7
7
  <% end %>
8
- has_and_belongs_to_many :stored_permissions,
8
+ has_and_belongs_to_many :permissions,
9
9
  join_table: '<%= role_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= role_u %>_id
10
10
 
11
+ has_many_temporary_permissions
12
+
11
13
  acts_as_role
12
14
 
13
15
  # default_scope { with_stored_permissions }
@@ -1,10 +1,12 @@
1
1
  class RoleGroup < ActiveRecord::Base
2
- has_and_belongs_to_many :stored_permissions,
2
+ has_and_belongs_to_many :permissions,
3
3
  join_table: '<%= group_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= group_u %>_id
4
4
 
5
5
  has_and_belongs_to_many :members,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= role_u %>_id, class_name: '<%= role_c %>', association_foreign_key: :<%= group_u %>_id
7
7
 
8
+ has_many_temporary_permissions
9
+
8
10
  acts_as_role_group
9
11
 
10
12
  # default_scope { with_members.with_stored_permissions) }
@@ -2,14 +2,13 @@ module IAmICan
2
2
  module Configs
3
3
  class Config
4
4
  attr_accessor :subject_class, :role_class, :role_group_class, :permission_class,
5
- :auto_define_before, :strict_mode, :without_group, :default_save, :act
5
+ :auto_definition, :strict_mode, :without_group, :act
6
6
 
7
7
  def initialize(*classes)
8
8
  self.subject_class, self.role_class, self.permission_class, self.role_group_class = classes
9
- self.auto_define_before = false
9
+ self.auto_definition = false
10
10
  self.strict_mode = false
11
11
  self.without_group = false
12
- self.default_save = true
13
12
  end
14
13
 
15
14
  def subject_model
@@ -2,9 +2,7 @@ require 'i_am_i_can/configs/config'
2
2
 
3
3
  module IAmICan
4
4
  module Configs
5
- cattr_accessor :configs do
6
- { }
7
- end
5
+ cattr_accessor :configs, default: { }
8
6
 
9
7
  def self.set_for(subject:, role:, permission:, role_group: nil, &block)
10
8
  config = Config.new(subject, role, permission, role_group)
@@ -21,9 +19,5 @@ module IAmICan
21
19
  def self.get(class_name)
22
20
  configs[class_name]
23
21
  end
24
-
25
- def self.take
26
- configs.values.first
27
- end
28
22
  end
29
23
  end
@@ -0,0 +1,102 @@
1
+ module IAmICan
2
+ module Dynamic
3
+ extend self
4
+
5
+ def scopes
6
+ #
7
+ # Generate scopes of each specified i_am_i_can association
8
+ #
9
+ # scope :with_stored_roles, -> { includes(:stored_roles) }
10
+ #
11
+ proc do |keys|
12
+ keys.each do |k|
13
+ scope :"with_#{_reflect_of(k)}", -> { includes(_reflect_of(k)) }
14
+ end
15
+ end
16
+ end
17
+
18
+ def class_reflections
19
+ #
20
+ # Extend each associated querying to a class method that returns ActiveRecord::Relation
21
+ #
22
+ # Suppose: in UserRole model,
23
+ # has_and_belongs_to_many :related_users
24
+ #
25
+ # It will do like this:
26
+ # def self.related_users
27
+ # User.with_stored_roles.where(user_roles: { id: self.ids })
28
+ # end
29
+ #
30
+ # Usage:
31
+ # UserRole.all.related_users
32
+ #
33
+ proc do
34
+ %w[ subject role role_group permission ].each do |k|
35
+ next if _reflect_of(k).blank?
36
+ define_singleton_method _reflect_of(k) do
37
+ model = i_am_i_can.send("#{k}_model")
38
+ raise NoMethodError unless (reflect_name = model._reflect_of(i_am_i_can.act))
39
+
40
+ model.send("with_#{reflect_name}").where(
41
+ self.name.underscore.pluralize => { id: self.ids }
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def assignment_helpers
49
+ #
50
+ # Generate methods for each Content of Assignment
51
+ #
52
+ # Example for a subject model called User, which `has_and_belongs_to_many :stored_roles`.
53
+ # You call the proc below by given contents [:role], then:
54
+ #
55
+ proc { |contents| contents.each do |content|
56
+ content_cls = i_am_i_can.send("#{content}_class")
57
+ _plural = '_' + content.to_s.pluralize
58
+
59
+ # _stored_roles_exec
60
+ # Add / Remove (by passing action :cancel) roles to a user instance
61
+ define_method "_#{_reflect_of(content)}_exec" do |action = :assignment, instances = [ ], **conditions|
62
+ collection = send(_plural)
63
+ if conditions.present? && action == :assignment
64
+ # Role.where(name: [...]).where.not(id: roles.ids)
65
+ query_result = content_cls.constantize.where(conditions).where.not(id: collection.ids)
66
+ elsif conditions.present? && action == :cancel
67
+ # Role.where(id: roles.ids, name: [...])
68
+ query_result = content_cls.constantize.where(id: collection.ids, **conditions)
69
+ end
70
+
71
+ objects = [*(query_result || [ ]), *(instances - collection)].uniq
72
+ action == :assignment ? collection << objects : collection.destroy(objects)
73
+ objects
74
+ end
75
+ #
76
+ alias_method "_stored#{_plural}_exec", "_#{_reflect_of(content)}_exec"
77
+ end }
78
+ end
79
+
80
+ def definition_helpers
81
+ #
82
+ # Generate class methods for each Content of Definition
83
+ #
84
+ # Example for a subject model called User,
85
+ # which `has_many_temporary_roles` and `has_and_belongs_to_many :stored_roles`.
86
+ # You call the proc below by given contents [:role], then:
87
+ #
88
+ proc { |contents| contents.each do |content|
89
+ content_cls = i_am_i_can.send("#{content}_class")
90
+ _plural = '_' + content.to_s.pluralize
91
+
92
+ # _create_roles
93
+ # Define and store roles of Subject
94
+ define_singleton_method "_create#{_plural}" do |objects|
95
+ # Role.create([{ name: .. }]).reject { the roles that validation failed }
96
+ content_cls.constantize.create(objects)
97
+ .reject {|record| record.new_record? }
98
+ end
99
+ end }
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,71 @@
1
+ module IAmICan
2
+ module ResultOf
3
+ module Role
4
+ def roles definition, i_am_i_can, given: [ ]
5
+ ResultOf.(definition, [ [], given ], config: i_am_i_can,
6
+ msg_prefix: 'Role Definition: ',
7
+ fail_msg: 'have been used by other roles!'
8
+ )
9
+ end
10
+
11
+ def role assignment, i_am_i_can, given: [ ]
12
+ ResultOf.(assignment, given, config: i_am_i_can,
13
+ msg_prefix: 'Role Assignment: ',
14
+ fail_msg: 'have not been defined or have been repeatedly assigned!'
15
+ )
16
+ end
17
+
18
+ ResultOf.include self
19
+ end
20
+
21
+ module RoleGroup
22
+ def members assignment, i_am_i_can, given: [ ]
23
+ ResultOf.(assignment, given, config: i_am_i_can,
24
+ msg_prefix: 'Role Grouping: ',
25
+ fail_msg: 'have not been defined!'
26
+ )
27
+ end
28
+
29
+ ResultOf.include self
30
+ end
31
+
32
+ module Permission
33
+ def permissions definition, i_am_i_can, given: [ ]
34
+ ResultOf.(definition, [ [], given ], config: i_am_i_can,
35
+ msg_prefix: 'Permission Definition: ',
36
+ fail_msg: 'have been used by other permissions!'
37
+ )
38
+ end
39
+
40
+ def permission assignment, i_am_i_can, given: [ ]
41
+ ResultOf.(assignment, given, config: i_am_i_can,
42
+ msg_prefix: 'Permission Assignment: ',
43
+ fail_msg: 'have not been defined or have been repeatedly assigned!'
44
+ )
45
+ end
46
+
47
+ ResultOf.include self
48
+ end
49
+
50
+ def call(assignment, given, msg_prefix:, fail_msg:, config:)
51
+ instances, names = given
52
+ instances.map!(&:name).map!(&:to_sym)
53
+ assignment = assignment.map(&:name).map(&:to_sym) unless assignment.first.is_a?(Symbol)
54
+
55
+ to_be_assigned_names = (instances + names).uniq
56
+ failed_items = to_be_assigned_names - assignment
57
+
58
+ msg = msg_prefix + (assignment.blank? ? 'do nothing' : "#{assignment} DONE")
59
+ msg << "; And #{failed_items} #{fail_msg}" if failed_items.present?
60
+
61
+ if config.strict_mode && failed_items.present?
62
+ raise Error, msg
63
+ else
64
+ Rails.logger.info(msg) unless ENV['ITEST']
65
+ assignment
66
+ end
67
+ end
68
+
69
+ extend self
70
+ end
71
+ end
@@ -1,75 +1,27 @@
1
- require 'i_am_i_can/permission/helpers'
2
-
3
1
  module IAmICan
4
2
  module Permission
5
3
  module Assignment
6
- include Helpers::Ins
7
-
8
- # permission assignment for stored role
9
- def can *preds, obj: nil, strict_mode: false, auto_define_before: i_am_i_can.auto_define_before
10
- self.class.have_permissions *preds, obj: obj if auto_define_before
11
- not_defined_items, covered_items = [ ], [ ]
12
-
13
- preds.each do |pred|
14
- pms_name = pms_naming(pred, obj)
15
- covered_items << pms_name if pms_matched?(pms_name, in: stored_permission_names)
16
- not_defined_items << pms_name unless stored_permissions_add(pred: pred, **deconstruct_obj(obj))
17
- end
18
-
19
- _pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
4
+ def can *actions,
5
+ resource: nil, obj: resource,
6
+ _d: i_am_i_can.auto_definition, auto_definition: _d
7
+ self.class.have_permissions *actions, obj: obj if auto_definition
8
+ _permissions_assignment(actions, obj)
20
9
  end
21
10
 
22
11
  alias has_permission can
23
12
 
24
- def temporarily_can *preds, obj: nil, strict_mode: false, auto_define_before: i_am_i_can.auto_define_before
25
- raise Error, "Permission Assignment: local role `#{name}` was not defined" unless i_am_i_can.subject_model.defined_local_roles.key?(self.name.to_sym)
26
- self.class.have_permissions *preds, obj: obj, save: false if auto_define_before
27
- not_defined_items, covered_items = [ ], [ ]
28
-
29
- preds.each do |pred|
30
- pms_name = pms_naming(pred, obj)
31
- next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
32
- covered_items << pms_name if pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
33
- pms_of_defined_local_role(self.name) << pms_name
34
- end
35
-
36
- _pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
37
- end
38
-
39
- alias locally_can temporarily_can
40
-
41
- def cannot *preds, obj: nil, saved: true
42
- not_defined_items = [ ]
43
-
44
- preds.each do |pred|
45
- pms_name = pms_naming(pred, obj)
46
- if saved
47
- next if stored_permissions_rmv(pred: pred, **deconstruct_obj(obj))
48
- not_defined_items << pms_name
49
- else
50
- next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
51
- pms_of_defined_local_role(self.name).delete(pms_name)
52
- end
53
- end
54
-
55
- _pms_assignment_result(preds, obj, not_defined_items)
13
+ def cannot *actions, obj: nil
14
+ _permissions_assignment(:cancel, actions, obj)
56
15
  end
57
16
 
58
17
  alias is_not_allowed_to cannot
59
18
 
60
- # `can? :manage, User` / `can? :manage, obj: User`
61
- def can? pred, obj0 = nil, obj: nil
62
- obj = obj0 || obj
63
- pms_name = pms_naming(pred, obj)
64
- temporarily_can?(pred, obj) || pms_matched?(pms_name, in: stored_permission_names)
19
+ def _permissions_assignment(action = :assignment, actions, obj)
20
+ permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
21
+ assignment = _stored_permissions_exec(action,
22
+ permissions.reduce({ }) { |a, b| a.merge(b) { |_, x, y| [x, y] } })
23
+ ResultOf.permission assignment, i_am_i_can, given: [[], permissions.map { |pms| pms.values.compact.join('_').to_sym }]
65
24
  end
66
-
67
- def temporarily_can? pred, obj
68
- pms_name = pms_naming(pred, obj)
69
- pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
70
- end
71
-
72
- alias locally_can? temporarily_can?
73
25
  end
74
26
  end
75
27
  end
@@ -1,40 +1,20 @@
1
- require 'i_am_i_can/permission/helpers'
2
- require 'i_am_i_can/permission/p_array'
3
-
4
1
  module IAmICan
5
2
  module Permission
6
3
  module Definition
7
- include Helpers::Cls
8
-
9
- def have_permission *preds, obj: nil, desc: nil, save: i_am_i_can.default_save
10
- failed_items = [ ]
11
-
12
- preds.each do |pred|
13
- pms_name = pms_naming(pred, obj)
14
- description = desc || pms_name.to_s.tr('_', ' ')
15
- if save
16
- failed_items << pms_name unless _to_store_permission(pred, obj, desc: description)
17
- else
18
- failed_items << pms_name if pms_name.in?(defined_local_permissions.keys)
19
- defined_local_permissions[pms_name] ||= { desc: description }
20
- end
21
- end
22
-
23
- _pms_definition_result(preds, obj, failed_items)
4
+ def have_permission *actions, obj: nil
5
+ permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
6
+ definition = _create_permissions(permissions)
7
+ ResultOf.roles definition, i_am_i_can, given: permissions.map { |pms| pms.values.compact.join('_').to_sym }
24
8
  end
25
9
 
26
- alias have_permissions have_permission
27
- alias has_permission have_permission
28
- alias has_permissions have_permission
10
+ %i[ have_permissions has_permission has_permissions ].each { |aname| alias_method aname, :have_permission }
29
11
 
30
- def declare_permission *preds, **options
31
- have_permission *preds, **options, save: false
12
+ def deconstruct_obj(obj)
13
+ i_am_i_can.permission_model.deconstruct_obj(obj)
32
14
  end
33
15
 
34
- alias declare_permissions declare_permission
35
-
36
16
  def self.extended(kls)
37
- kls.delegate :defined_permissions, :pms_naming, :deconstruct_obj, :pms_of_defined_local_role, to: kls
17
+ kls.delegate :deconstruct_obj, to: kls
38
18
  end
39
19
  end
40
20
  end
@@ -1,4 +1,3 @@
1
- require 'i_am_i_can/permission/p_array'
2
1
  require 'i_am_i_can/permission/definition'
3
2
  require 'i_am_i_can/permission/assignment'
4
3
 
@@ -7,19 +6,23 @@ module IAmICan
7
6
  extend ActiveSupport::Concern
8
7
 
9
8
  class_methods do
10
- def matched?(pms_name = nil, pred: nil, obj: nil, **options)
11
- PArray.new(options[:in]).matched?(pms_name || naming(pred, obj))
9
+ def matched(actions, obj)
10
+ _ = deconstruct_obj(obj)
11
+ where(action: actions,
12
+ obj_type: [nil, _[:obj_type]],
13
+ obj_id: [nil, _[:obj_id]])
12
14
  end
13
15
 
14
- def which(pred:, obj: nil, **conditions)
15
- find_by!(pred: pred, **deconstruct_obj(obj), **conditions)
16
+ def matched?(actions, obj)
17
+ matched(actions, obj).present?
16
18
  end
17
19
 
18
- def naming(pred, obj)
19
- obj_type, obj_id = deconstruct_obj(obj).values
20
- otp = "_#{obj_type}" if obj_type.present?
21
- oid = "_#{obj_id}" if obj_id.present?
22
- [pred, otp, oid].join.to_sym
20
+ def matched_all?(actions, obj)
21
+ matched(actions, obj).count == Array(actions).count
22
+ end
23
+
24
+ def which(action:, obj: nil, **conditions)
25
+ find_by!(action: action, **deconstruct_obj(obj), **conditions)
23
26
  end
24
27
 
25
28
  def deconstruct_obj(obj)
@@ -34,32 +37,23 @@ module IAmICan
34
37
  end
35
38
  end
36
39
 
37
- def exists?(pred, obj)
38
- super(pred: pred, **deconstruct_obj(obj))
40
+ def names
41
+ all.map(&:name)
39
42
  end
40
43
  end
41
44
 
42
45
  included do
43
46
  # like: manage_User_1
44
47
  def name
45
- otp = "_#{obj_type}" if obj_type.present?
46
- oid = "_#{obj_id}" if obj_id.present?
47
- [pred, otp, oid].join.to_sym
48
+ [action, obj_type, obj_id].compact.join('_').to_sym
48
49
  end
49
50
 
50
51
  # def assign_to role: nil, group: nil
51
- # obj = if role
52
- # role.is_a?(Symbol) ? i_am_i_can.role_model.find(name: role) : role
53
- # else
54
- # group.is_a?(Symbol) ? i_am_i_can.role_group_model.find(name: role) : group
55
- # end
56
- # obj.have_permission self.pred, obj: self.obj
57
52
  # end
58
- #
59
- # alias is_assigned_to assign_to
60
53
 
61
- # :user, User, user
54
+ # returns :user, User, user
62
55
  def obj
56
+ return if obj_type.blank?
63
57
  return obj_type.constantize.find(obj_id) if obj_id.present?
64
58
  obj_type[/[A-Z]/] ? obj_type.constantize : obj_type.to_sym
65
59
  end
@@ -2,28 +2,33 @@ module IAmICan
2
2
  module Resource
3
3
  extend ActiveSupport::Concern
4
4
 
5
- class_methods do
6
- # Book.that_allow(User.all).to(:read)
7
- # Book.that_allow(User.last).to(:write)
8
- def that_allow(subject)
9
- ThatAllow.new(self, subject)
5
+ included do
6
+ # Book.that_allow(User.all, to: :read)
7
+ # Book.that_allow(User.last, to: :write)
8
+ scope :that_allow, -> (subject, to:) do
9
+ tmp_role_ids = Array(subject).flat_map(&:temporary_roles).map(&:id).uniq
10
+ allowed_ids = subject.i_am_i_can.role_model.where(id: (subject._roles.ids + tmp_role_ids).uniq)
11
+ ._permissions.where(action: to, obj_type: self.name).pluck(:obj_id).uniq
12
+ where(id: allowed_ids)
10
13
  end
11
14
  end
12
- end
13
15
 
14
- class ThatAllow
15
- attr_accessor :records, :subject
16
-
17
- def initialize(records, subject)
18
- self.records = records
19
- self.subject = subject
20
- end
21
-
22
- def to(pred)
23
- roles = Configs.take.subject_model._roles
24
- permissions = Configs.take.role_model._permissions
25
- allowed_ids = subject.send(roles).send(permissions).where(pred: pred, obj_type: records.name).pluck(:obj_id).uniq
26
- records.where(id: allowed_ids)
16
+ class_methods do
17
+ # def that_allow(subject)
18
+ # ThatAllow.new(self, subject)
19
+ # end
27
20
  end
28
21
  end
22
+
23
+ # class ThatAllow
24
+ # attr_accessor :records, :subject
25
+ #
26
+ # def initialize(records, subject)
27
+ # self.records = records
28
+ # self.subject = subject
29
+ # end
30
+ #
31
+ # def to(action)
32
+ # end
33
+ # end
29
34
  end
@@ -1,62 +1,41 @@
1
- require 'i_am_i_can/role/helpers'
2
-
3
1
  module IAmICan
4
2
  module Role
5
3
  module Assignment
6
- include Helpers::Ins
7
-
8
- def becomes_a *roles, which_can: [ ], obj: nil, auto_define_before: i_am_i_can.auto_define_before, save: i_am_i_can.default_save
9
- should_define_role = which_can.present? || auto_define_before
10
- self.class.have_roles *roles, which_can: which_can, obj: obj, save: save if should_define_role
11
- failed_items = [ ]
12
-
13
- roles.map(&__role).each do |role|
14
- if save
15
- failed_items << role unless stored_roles_add(role)
16
- else
17
- next failed_items << role unless role.in?(defined_roles.keys)
18
- local_role_names << role unless role.in?(local_role_names)
19
- end
20
- end
21
-
22
- _role_assignment_result(roles, failed_items)
4
+ def becomes_a *roles, which_can: [ ], obj: nil,
5
+ _d: i_am_i_can.auto_definition,
6
+ auto_definition: _d || which_can.present?,
7
+ save: true
8
+ self.class.have_roles *roles, which_can: which_can, obj: obj if auto_definition
9
+ _roles_assignment(roles, save)
23
10
  end
24
11
 
25
- alias is becomes_a
26
- alias is_a_role becomes_a
27
- alias is_roles becomes_a
28
- alias has_role becomes_a
29
- alias has_roles becomes_a
30
- alias role_is becomes_a
31
- alias roles_are becomes_a
12
+ %i[ is is_a is_a_role is_roles has_role has_roles role_is role_are ].each { |aname| alias_method aname, :becomes_a }
32
13
 
33
- def temporarily_is *roles, **options
14
+ def is_a_temporary *roles, **options
34
15
  becomes_a *roles, save: false, **options
35
16
  end
36
17
 
37
- alias locally_is temporarily_is
18
+ def falls_from *roles, saved: true
19
+ _roles_assignment(:cancel, roles, saved)
20
+ end
21
+
22
+ %i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
38
23
 
39
- def falls_from *roles, saved: i_am_i_can.default_save
40
- failed_items = [ ]
24
+ def is_not_a_temporary *roles
25
+ falls_from *roles, saved: false
26
+ end
41
27
 
42
- roles.each do |role|
43
- if saved
44
- failed_items << role unless stored_roles_rmv(role)
45
- else
46
- next failed_items << role unless role.in?(defined_roles.keys)
47
- local_role_names.delete(role)
48
- end
28
+ def _roles_assignment(action = :assignment, roles, save)
29
+ instances, names = Role.extract(roles, i_am_i_can)
30
+ if save
31
+ assignment = _stored_roles_exec(action, instances, name: names)
32
+ else
33
+ to_be_assigned_names = (instances.map(&:name).map(&:to_sym) + names).uniq
34
+ assignment = _temporary_roles_exec(action, to_be_assigned_names)
49
35
  end
50
36
 
51
- _role_assignment_result(roles, failed_items)
37
+ ResultOf.role assignment, i_am_i_can, given: [instances, names]
52
38
  end
53
-
54
- alias is_not_a falls_from
55
- alias will_not_be falls_from
56
- alias removes_role falls_from
57
- alias leaves falls_from
58
- alias has_not_role falls_from
59
- alias has_not_roles falls_from
60
39
  end
61
40
  end
62
41
  end